s3-spoolss: fix memleak of spoolss_Notify array in _spoolss_RouterRefreshPrinterChang...
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED;
114         case LPQ_USER_INTERVENTION:
115                 return JOB_STATUS_USER_INTERVENTION;
116         }
117         return 0;
118 }
119
120 static int nt_printq_status(int v)
121 {
122         switch (v) {
123         case LPQ_PAUSED:
124                 return PRINTER_STATUS_PAUSED;
125         case LPQ_QUEUED:
126         case LPQ_SPOOLING:
127         case LPQ_PRINTING:
128                 return 0;
129         }
130         return 0;
131 }
132
133 /****************************************************************************
134  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
136
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 {
139         if (*pp == NULL)
140                 return;
141
142         SAFE_FREE((*pp)->ctr.type);
143         SAFE_FREE(*pp);
144 }
145
146 /***************************************************************************
147  Disconnect from the client
148 ****************************************************************************/
149
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
151 {
152         WERROR result;
153         NTSTATUS status;
154
155         /*
156          * Tell the specific printing tdb we no longer want messages for this printer
157          * by deregistering our PID.
158          */
159
160         if (!print_notify_deregister_pid(snum))
161                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162
163         /* weird if the test succeds !!! */
164         if (smb_connections==0) {
165                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166                 return;
167         }
168
169         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170                                                   handle,
171                                                   &result);
172         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174                         win_errstr(result)));
175
176         /* if it's the last connection, deconnect the IPC$ share */
177         if (smb_connections==1) {
178
179                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181
182                 messaging_deregister(smbd_messaging_context(),
183                                      MSG_PRINTER_NOTIFY2, NULL);
184
185                 /* Tell the connections db we're no longer interested in
186                  * printer notify messages. */
187
188                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189         }
190
191         smb_connections--;
192 }
193
194 /****************************************************************************
195  Functions to free a printer entry datastruct.
196 ****************************************************************************/
197
198 static int printer_entry_destructor(Printer_entry *Printer)
199 {
200         if (Printer->notify.client_connected==True) {
201                 int snum = -1;
202
203                 if ( Printer->printer_type == SPLHND_SERVER) {
204                         snum = -1;
205                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206                 } else if (Printer->printer_type == SPLHND_PRINTER) {
207                         snum = print_queue_snum(Printer->sharename);
208                         if (snum != -1)
209                                 srv_spoolss_replycloseprinter(snum,
210                                                 &Printer->notify.client_hnd);
211                 }
212         }
213
214         Printer->notify.flags=0;
215         Printer->notify.options=0;
216         Printer->notify.localmachine[0]='\0';
217         Printer->notify.printerlocal=0;
218         free_spool_notify_option(&Printer->notify.option);
219         Printer->notify.option=NULL;
220         Printer->notify.client_connected=False;
221
222         free_nt_devicemode( &Printer->nt_devmode );
223         free_a_printer( &Printer->printer_info, 2 );
224
225         /* Remove from the internal list. */
226         DLIST_REMOVE(printers_list, Printer);
227         return 0;
228 }
229
230 /****************************************************************************
231  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
233
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 {
236         SPOOL_NOTIFY_OPTION *new_sp = NULL;
237
238         if (!sp)
239                 return NULL;
240
241         new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
242         if (!new_sp)
243                 return NULL;
244
245         *new_sp = *sp;
246
247         if (sp->ctr.count) {
248                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249
250                 if (!new_sp->ctr.type) {
251                         SAFE_FREE(new_sp);
252                         return NULL;
253                 }
254         }
255
256         return new_sp;
257 }
258
259 /****************************************************************************
260   find printer index by handle
261 ****************************************************************************/
262
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 {
265         Printer_entry *find_printer = NULL;
266
267         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
268                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269                 return NULL;
270         }
271
272         return find_printer;
273 }
274
275 /****************************************************************************
276  Close printer index by handle.
277 ****************************************************************************/
278
279 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 {
281         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282
283         if (!Printer) {
284                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
285                 return False;
286         }
287
288         close_policy_hnd(p, hnd);
289
290         return True;
291 }
292
293 /****************************************************************************
294  Delete a printer given a handle.
295 ****************************************************************************/
296
297 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
298 {
299         char *cmd = lp_deleteprinter_cmd();
300         char *command = NULL;
301         int ret;
302         SE_PRIV se_printop = SE_PRINT_OPERATOR;
303         bool is_print_op = False;
304
305         /* can't fail if we don't try */
306
307         if ( !*cmd )
308                 return WERR_OK;
309
310         command = talloc_asprintf(ctx,
311                         "%s \"%s\"",
312                         cmd, sharename);
313         if (!command) {
314                 return WERR_NOMEM;
315         }
316         if ( token )
317                 is_print_op = user_has_privileges( token, &se_printop );
318
319         DEBUG(10,("Running [%s]\n", command));
320
321         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
322
323         if ( is_print_op )
324                 become_root();
325
326         if ( (ret = smbrun(command, NULL)) == 0 ) {
327                 /* Tell everyone we updated smb.conf. */
328                 message_send_all(smbd_messaging_context(),
329                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
330         }
331
332         if ( is_print_op )
333                 unbecome_root();
334
335         /********** END SePrintOperatorPrivlege BLOCK **********/
336
337         DEBUGADD(10,("returned [%d]\n", ret));
338
339         TALLOC_FREE(command);
340
341         if (ret != 0)
342                 return WERR_BADFID; /* What to return here? */
343
344         /* go ahead and re-read the services immediately */
345         reload_services( False );
346
347         if ( lp_servicenumber( sharename )  < 0 )
348                 return WERR_ACCESS_DENIED;
349
350         return WERR_OK;
351 }
352
353 /****************************************************************************
354  Delete a printer given a handle.
355 ****************************************************************************/
356
357 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
358 {
359         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
360
361         if (!Printer) {
362                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
363                 return WERR_BADFID;
364         }
365
366         /*
367          * It turns out that Windows allows delete printer on a handle
368          * opened by an admin user, then used on a pipe handle created
369          * by an anonymous user..... but they're working on security.... riiight !
370          * JRA.
371          */
372
373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
374                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
375                 return WERR_ACCESS_DENIED;
376         }
377
378         /* this does not need a become root since the access check has been
379            done on the handle already */
380
381         if (del_a_printer( Printer->sharename ) != 0) {
382                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
383                 return WERR_BADFID;
384         }
385
386         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
387                                    Printer->sharename );
388 }
389
390 /****************************************************************************
391  Return the snum of a printer corresponding to an handle.
392 ****************************************************************************/
393
394 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
395                              struct share_params **params)
396 {
397         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
398
399         if (!Printer) {
400                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
401                 return False;
402         }
403
404         switch (Printer->printer_type) {
405                 case SPLHND_PRINTER:
406                         DEBUG(4,("short name:%s\n", Printer->sharename));
407                         *number = print_queue_snum(Printer->sharename);
408                         return (*number != -1);
409                 case SPLHND_SERVER:
410                         return False;
411                 default:
412                         return False;
413         }
414 }
415
416 /****************************************************************************
417  Set printer handle type.
418  Check if it's \\server or \\server\printer
419 ****************************************************************************/
420
421 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
422 {
423         DEBUG(3,("Setting printer type=%s\n", handlename));
424
425         if ( strlen(handlename) < 3 ) {
426                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
427                 return False;
428         }
429
430         /* it's a print server */
431         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
432                 DEBUGADD(4,("Printer is a print server\n"));
433                 Printer->printer_type = SPLHND_SERVER;
434         }
435         /* it's a printer (set_printer_hnd_name() will handle port monitors */
436         else {
437                 DEBUGADD(4,("Printer is a printer\n"));
438                 Printer->printer_type = SPLHND_PRINTER;
439         }
440
441         return True;
442 }
443
444 /****************************************************************************
445  Set printer handle name..  Accept names like \\server, \\server\printer,
446  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
447  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
448  XcvDataPort() interface.
449 ****************************************************************************/
450
451 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
452 {
453         int snum;
454         int n_services=lp_numservices();
455         char *aprinter, *printername;
456         const char *servername;
457         fstring sname;
458         bool found=False;
459         NT_PRINTER_INFO_LEVEL *printer = NULL;
460         WERROR result;
461
462         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
463
464         aprinter = handlename;
465         if ( *handlename == '\\' ) {
466                 servername = canon_servername(handlename);
467                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
468                         *aprinter = '\0';
469                         aprinter++;
470                 }
471         } else {
472                 servername = "";
473         }
474
475         /* save the servername to fill in replies on this handle */
476
477         if ( !is_myname_or_ipaddr( servername ) )
478                 return False;
479
480         fstrcpy( Printer->servername, servername );
481
482         if ( Printer->printer_type == SPLHND_SERVER )
483                 return True;
484
485         if ( Printer->printer_type != SPLHND_PRINTER )
486                 return False;
487
488         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
489
490         /* check for the Port Monitor Interface */
491
492         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
493                 Printer->printer_type = SPLHND_PORTMON_TCP;
494                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
495                 found = True;
496         }
497         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
498                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
499                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
500                 found = True;
501         }
502
503         /* Search all sharenames first as this is easier than pulling
504            the printer_info_2 off of disk. Don't use find_service() since
505            that calls out to map_username() */
506
507         /* do another loop to look for printernames */
508
509         for (snum=0; !found && snum<n_services; snum++) {
510
511                 /* no point going on if this is not a printer */
512
513                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
514                         continue;
515
516                 fstrcpy(sname, lp_servicename(snum));
517                 if ( strequal( aprinter, sname ) ) {
518                         found = True;
519                         break;
520                 }
521
522                 /* no point looking up the printer object if
523                    we aren't allowing printername != sharename */
524
525                 if ( lp_force_printername(snum) )
526                         continue;
527
528                 fstrcpy(sname, lp_servicename(snum));
529
530                 printer = NULL;
531
532                 /* This call doesn't fill in the location or comment from
533                  * a CUPS server for efficiency with large numbers of printers.
534                  * JRA.
535                  */
536
537                 result = get_a_printer_search( NULL, &printer, 2, sname );
538                 if ( !W_ERROR_IS_OK(result) ) {
539                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
540                                 sname, win_errstr(result)));
541                         continue;
542                 }
543
544                 /* printername is always returned as \\server\printername */
545                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
546                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
547                                 printer->info_2->printername));
548                         free_a_printer( &printer, 2);
549                         continue;
550                 }
551
552                 printername++;
553
554                 if ( strequal(printername, aprinter) ) {
555                         free_a_printer( &printer, 2);
556                         found = True;
557                         break;
558                 }
559
560                 DEBUGADD(10, ("printername: %s\n", printername));
561
562                 free_a_printer( &printer, 2);
563         }
564
565         free_a_printer( &printer, 2);
566
567         if ( !found ) {
568                 DEBUGADD(4,("Printer not found\n"));
569                 return False;
570         }
571
572         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
573
574         fstrcpy(Printer->sharename, sname);
575
576         return True;
577 }
578
579 /****************************************************************************
580  Find first available printer slot. creates a printer handle for you.
581  ****************************************************************************/
582
583 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
584 {
585         Printer_entry *new_printer;
586
587         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
588
589         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
590         if (new_printer == NULL) {
591                 return false;
592         }
593         talloc_set_destructor(new_printer, printer_entry_destructor);
594
595         if (!create_policy_hnd(p, hnd, new_printer)) {
596                 TALLOC_FREE(new_printer);
597                 return False;
598         }
599
600         /* Add to the internal list. */
601         DLIST_ADD(printers_list, new_printer);
602
603         new_printer->notify.option=NULL;
604
605         if (!set_printer_hnd_printertype(new_printer, name)) {
606                 close_printer_handle(p, hnd);
607                 return False;
608         }
609
610         if (!set_printer_hnd_name(new_printer, name)) {
611                 close_printer_handle(p, hnd);
612                 return False;
613         }
614
615         new_printer->access_granted = access_granted;
616
617         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
618
619         return True;
620 }
621
622 /***************************************************************************
623  check to see if the client motify handle is monitoring the notification
624  given by (notify_type, notify_field).
625  **************************************************************************/
626
627 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
628                                       uint16 notify_field)
629 {
630         return True;
631 }
632
633 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
634                                 uint16 notify_field)
635 {
636         SPOOL_NOTIFY_OPTION *option = p->notify.option;
637         uint32 i, j;
638
639         /*
640          * Flags should always be zero when the change notify
641          * is registered by the client's spooler.  A user Win32 app
642          * might use the flags though instead of the NOTIFY_OPTION_INFO
643          * --jerry
644          */
645
646         if (!option) {
647                 return False;
648         }
649
650         if (p->notify.flags)
651                 return is_monitoring_event_flags(
652                         p->notify.flags, notify_type, notify_field);
653
654         for (i = 0; i < option->count; i++) {
655
656                 /* Check match for notify_type */
657
658                 if (option->ctr.type[i].type != notify_type)
659                         continue;
660
661                 /* Check match for field */
662
663                 for (j = 0; j < option->ctr.type[i].count; j++) {
664                         if (option->ctr.type[i].fields[j] == notify_field) {
665                                 return True;
666                         }
667                 }
668         }
669
670         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
671                    p->servername, p->sharename, notify_type, notify_field));
672
673         return False;
674 }
675
676 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
677         _data->data.integer[0] = _integer; \
678         _data->data.integer[1] = 0;
679
680
681 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
682         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
683         if (!_data->data.string.string) {\
684                 _data->data.string.size = 0; \
685         } \
686         _data->data.string.size = strlen_m_term(_p) * 2;
687
688 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
689         _data->data.devmode.devmode = _devmode;
690
691 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
692         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
693         if (!_data->data.sd.sd) { \
694                 _data->data.sd.sd_size = 0; \
695         } \
696         _data->data.sd.sd_size = _size;
697
698 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
699                                    struct tm *t,
700                                    const char **pp,
701                                    uint32_t *plen)
702 {
703         struct spoolss_Time st;
704         uint32_t len = 16;
705         char *p;
706
707         if (!init_systemtime(&st, t)) {
708                 return;
709         }
710
711         p = talloc_array(mem_ctx, char, len);
712         if (!p) {
713                 return;
714         }
715
716         /*
717          * Systemtime must be linearized as a set of UINT16's.
718          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
719          */
720
721         SSVAL(p, 0, st.year);
722         SSVAL(p, 2, st.month);
723         SSVAL(p, 4, st.day_of_week);
724         SSVAL(p, 6, st.day);
725         SSVAL(p, 8, st.hour);
726         SSVAL(p, 10, st.minute);
727         SSVAL(p, 12, st.second);
728         SSVAL(p, 14, st.millisecond);
729
730         *pp = p;
731         *plen = len;
732 }
733
734 /* Convert a notification message to a struct spoolss_Notify */
735
736 static void notify_one_value(struct spoolss_notify_msg *msg,
737                              struct spoolss_Notify *data,
738                              TALLOC_CTX *mem_ctx)
739 {
740         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
741 }
742
743 static void notify_string(struct spoolss_notify_msg *msg,
744                           struct spoolss_Notify *data,
745                           TALLOC_CTX *mem_ctx)
746 {
747         /* The length of the message includes the trailing \0 */
748
749         data->data.string.size = msg->len * 2;
750         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
751         if (!data->data.string.string) {
752                 data->data.string.size = 0;
753                 return;
754         }
755 }
756
757 static void notify_system_time(struct spoolss_notify_msg *msg,
758                                struct spoolss_Notify *data,
759                                TALLOC_CTX *mem_ctx)
760 {
761         data->data.string.string = NULL;
762         data->data.string.size = 0;
763
764         if (msg->len != sizeof(time_t)) {
765                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
766                           msg->len));
767                 return;
768         }
769
770         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
771                                &data->data.string.string,
772                                &data->data.string.size);
773 }
774
775 struct notify2_message_table {
776         const char *name;
777         void (*fn)(struct spoolss_notify_msg *msg,
778                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
779 };
780
781 static struct notify2_message_table printer_notify_table[] = {
782         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
783         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
784         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
785         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
786         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
787         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
788         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
789         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
790         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
791         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
792         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
793         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
794         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
795         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
796         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
797         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
798         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
799         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
801 };
802
803 static struct notify2_message_table job_notify_table[] = {
804         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
805         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
806         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
807         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
808         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
809         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
810         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
811         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
812         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
813         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
814         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
815         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
816         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
817         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
818         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
819         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
820         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
821         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
822         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
823         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
824         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
825         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
826         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
827         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 };
829
830
831 /***********************************************************************
832  Allocate talloc context for container object
833  **********************************************************************/
834
835 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 {
837         if ( !ctr )
838                 return;
839
840         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
841
842         return;
843 }
844
845 /***********************************************************************
846  release all allocated memory and zero out structure
847  **********************************************************************/
848
849 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 {
851         if ( !ctr )
852                 return;
853
854         if ( ctr->ctx )
855                 talloc_destroy(ctr->ctx);
856
857         ZERO_STRUCTP(ctr);
858
859         return;
860 }
861
862 /***********************************************************************
863  **********************************************************************/
864
865 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 {
867         if ( !ctr )
868                 return NULL;
869
870         return ctr->ctx;
871 }
872
873 /***********************************************************************
874  **********************************************************************/
875
876 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
877 {
878         if ( !ctr || !ctr->msg_groups )
879                 return NULL;
880
881         if ( idx >= ctr->num_groups )
882                 return NULL;
883
884         return &ctr->msg_groups[idx];
885
886 }
887
888 /***********************************************************************
889  How many groups of change messages do we have ?
890  **********************************************************************/
891
892 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
893 {
894         if ( !ctr )
895                 return 0;
896
897         return ctr->num_groups;
898 }
899
900 /***********************************************************************
901  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
902  **********************************************************************/
903
904 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
905 {
906         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
907         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
908         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
909         int                             i, new_slot;
910
911         if ( !ctr || !msg )
912                 return 0;
913
914         /* loop over all groups looking for a matching printer name */
915
916         for ( i=0; i<ctr->num_groups; i++ ) {
917                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
918                         break;
919         }
920
921         /* add a new group? */
922
923         if ( i == ctr->num_groups ) {
924                 ctr->num_groups++;
925
926                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
927                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
928                         return 0;
929                 }
930                 ctr->msg_groups = groups;
931
932                 /* clear the new entry and set the printer name */
933
934                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
935                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
936         }
937
938         /* add the change messages; 'i' is the correct index now regardless */
939
940         msg_grp = &ctr->msg_groups[i];
941
942         msg_grp->num_msgs++;
943
944         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
945                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
946                 return 0;
947         }
948         msg_grp->msgs = msg_list;
949
950         new_slot = msg_grp->num_msgs-1;
951         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
952
953         /* need to allocate own copy of data */
954
955         if ( msg->len != 0 )
956                 msg_grp->msgs[new_slot].notify.data = (char *)
957                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
958
959         return ctr->num_groups;
960 }
961
962 /***********************************************************************
963  Send a change notication message on all handles which have a call
964  back registered
965  **********************************************************************/
966
967 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
968 {
969         Printer_entry            *p;
970         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
971         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
972         SPOOLSS_NOTIFY_MSG       *messages;
973         int                      sending_msg_count;
974
975         if ( !msg_group ) {
976                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
977                 return;
978         }
979
980         messages = msg_group->msgs;
981
982         if ( !messages ) {
983                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
984                 return;
985         }
986
987         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
988
989         /* loop over all printers */
990
991         for (p = printers_list; p; p = p->next) {
992                 struct spoolss_Notify *notifies;
993                 uint32_t count = 0;
994                 uint32_t id;
995                 int     i;
996
997                 /* Is there notification on this handle? */
998
999                 if ( !p->notify.client_connected )
1000                         continue;
1001
1002                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1003
1004                 /* For this printer?  Print servers always receive
1005                    notifications. */
1006
1007                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
1008                     ( !strequal(msg_group->printername, p->sharename) ) )
1009                         continue;
1010
1011                 DEBUG(10,("Our printer\n"));
1012
1013                 /* allocate the max entries possible */
1014
1015                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1016                 if (!notifies) {
1017                         return;
1018                 }
1019
1020                 /* build the array of change notifications */
1021
1022                 sending_msg_count = 0;
1023
1024                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1025                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1026
1027                         /* Are we monitoring this event? */
1028
1029                         if (!is_monitoring_event(p, msg->type, msg->field))
1030                                 continue;
1031
1032                         sending_msg_count++;
1033
1034
1035                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1036                                 msg->type, msg->field, p->sharename));
1037
1038                         /*
1039                          * if the is a printer notification handle and not a job notification
1040                          * type, then set the id to 0.  Other wise just use what was specified
1041                          * in the message.
1042                          *
1043                          * When registering change notification on a print server handle
1044                          * we always need to send back the id (snum) matching the printer
1045                          * for which the change took place.  For change notify registered
1046                          * on a printer handle, this does not matter and the id should be 0.
1047                          *
1048                          * --jerry
1049                          */
1050
1051                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1052                                 id = 0;
1053                         else
1054                                 id = msg->id;
1055
1056
1057                         /* Convert unix jobid to smb jobid */
1058
1059                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1060                                 id = sysjob_to_jobid(msg->id);
1061
1062                                 if (id == -1) {
1063                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1064                                         goto done;
1065                                 }
1066                         }
1067
1068                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1069
1070                         switch(msg->type) {
1071                         case PRINTER_NOTIFY_TYPE:
1072                                 if ( printer_notify_table[msg->field].fn )
1073                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1074                                 break;
1075
1076                         case JOB_NOTIFY_TYPE:
1077                                 if ( job_notify_table[msg->field].fn )
1078                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1079                                 break;
1080
1081                         default:
1082                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1083                                 goto done;
1084                         }
1085
1086                         count++;
1087                 }
1088
1089                 if ( sending_msg_count ) {
1090                         NTSTATUS status;
1091                         WERROR werr;
1092                         union spoolss_ReplyPrinterInfo info;
1093                         struct spoolss_NotifyInfo info0;
1094                         uint32_t reply_result;
1095
1096                         info0.version   = 0x2;
1097                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1098                         info0.count     = count;
1099                         info0.notifies  = notifies;
1100
1101                         info.info0 = &info0;
1102
1103                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1104                                                                      &p->notify.client_hnd,
1105                                                                      p->notify.change, /* color */
1106                                                                      p->notify.flags,
1107                                                                      &reply_result,
1108                                                                      0, /* reply_type, must be 0 */
1109                                                                      info,
1110                                                                      &werr);
1111                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1112                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1113                                         notify_cli_pipe->srv_name_slash,
1114                                         win_errstr(werr)));
1115                         }
1116                         switch (reply_result) {
1117                                 case 0:
1118                                         break;
1119                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1120                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1121                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1122                                         break;
1123                                 default:
1124                                         break;
1125                         }
1126                 }
1127         }
1128
1129 done:
1130         DEBUG(8,("send_notify2_changes: Exit...\n"));
1131         return;
1132 }
1133
1134 /***********************************************************************
1135  **********************************************************************/
1136
1137 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1138 {
1139
1140         uint32 tv_sec, tv_usec;
1141         size_t offset = 0;
1142
1143         /* Unpack message */
1144
1145         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1146                              msg->printer);
1147
1148         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1149                                 &tv_sec, &tv_usec,
1150                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1151
1152         if (msg->len == 0)
1153                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1154                            &msg->notify.value[0], &msg->notify.value[1]);
1155         else
1156                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1157                            &msg->len, &msg->notify.data);
1158
1159         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1160                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1161
1162         tv->tv_sec = tv_sec;
1163         tv->tv_usec = tv_usec;
1164
1165         if (msg->len == 0)
1166                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1167                           msg->notify.value[1]));
1168         else
1169                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1170
1171         return True;
1172 }
1173
1174 /********************************************************************
1175  Receive a notify2 message list
1176  ********************************************************************/
1177
1178 static void receive_notify2_message_list(struct messaging_context *msg,
1179                                          void *private_data,
1180                                          uint32_t msg_type,
1181                                          struct server_id server_id,
1182                                          DATA_BLOB *data)
1183 {
1184         size_t                  msg_count, i;
1185         char                    *buf = (char *)data->data;
1186         char                    *msg_ptr;
1187         size_t                  msg_len;
1188         SPOOLSS_NOTIFY_MSG      notify;
1189         SPOOLSS_NOTIFY_MSG_CTR  messages;
1190         int                     num_groups;
1191
1192         if (data->length < 4) {
1193                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1194                 return;
1195         }
1196
1197         msg_count = IVAL(buf, 0);
1198         msg_ptr = buf + 4;
1199
1200         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1201
1202         if (msg_count == 0) {
1203                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1204                 return;
1205         }
1206
1207         /* initialize the container */
1208
1209         ZERO_STRUCT( messages );
1210         notify_msg_ctr_init( &messages );
1211
1212         /*
1213          * build message groups for each printer identified
1214          * in a change_notify msg.  Remember that a PCN message
1215          * includes the handle returned for the srv_spoolss_replyopenprinter()
1216          * call.  Therefore messages are grouped according to printer handle.
1217          */
1218
1219         for ( i=0; i<msg_count; i++ ) {
1220                 struct timeval msg_tv;
1221
1222                 if (msg_ptr + 4 - buf > data->length) {
1223                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1224                         return;
1225                 }
1226
1227                 msg_len = IVAL(msg_ptr,0);
1228                 msg_ptr += 4;
1229
1230                 if (msg_ptr + msg_len - buf > data->length) {
1231                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1232                         return;
1233                 }
1234
1235                 /* unpack messages */
1236
1237                 ZERO_STRUCT( notify );
1238                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1239                 msg_ptr += msg_len;
1240
1241                 /* add to correct list in container */
1242
1243                 notify_msg_ctr_addmsg( &messages, &notify );
1244
1245                 /* free memory that might have been allocated by notify2_unpack_msg() */
1246
1247                 if ( notify.len != 0 )
1248                         SAFE_FREE( notify.notify.data );
1249         }
1250
1251         /* process each group of messages */
1252
1253         num_groups = notify_msg_ctr_numgroups( &messages );
1254         for ( i=0; i<num_groups; i++ )
1255                 send_notify2_changes( &messages, i );
1256
1257
1258         /* cleanup */
1259
1260         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1261
1262         notify_msg_ctr_destroy( &messages );
1263
1264         return;
1265 }
1266
1267 /********************************************************************
1268  Send a message to ourself about new driver being installed
1269  so we can upgrade the information for each printer bound to this
1270  driver
1271  ********************************************************************/
1272
1273 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1274 {
1275         int len = strlen(drivername);
1276
1277         if (!len)
1278                 return False;
1279
1280         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1281                 drivername));
1282
1283         messaging_send_buf(smbd_messaging_context(), procid_self(),
1284                            MSG_PRINTER_DRVUPGRADE,
1285                            (uint8 *)drivername, len+1);
1286
1287         return True;
1288 }
1289
1290 /**********************************************************************
1291  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1292  over all printers, upgrading ones as necessary
1293  **********************************************************************/
1294
1295 void do_drv_upgrade_printer(struct messaging_context *msg,
1296                             void *private_data,
1297                             uint32_t msg_type,
1298                             struct server_id server_id,
1299                             DATA_BLOB *data)
1300 {
1301         fstring drivername;
1302         int snum;
1303         int n_services = lp_numservices();
1304         size_t len;
1305
1306         len = MIN(data->length,sizeof(drivername)-1);
1307         strncpy(drivername, (const char *)data->data, len);
1308
1309         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1310
1311         /* Iterate the printer list */
1312
1313         for (snum=0; snum<n_services; snum++)
1314         {
1315                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1316                 {
1317                         WERROR result;
1318                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1319
1320                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1321                         if (!W_ERROR_IS_OK(result))
1322                                 continue;
1323
1324                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1325                         {
1326                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1327
1328                                 /* all we care about currently is the change_id */
1329
1330                                 result = mod_a_printer(printer, 2);
1331                                 if (!W_ERROR_IS_OK(result)) {
1332                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1333                                                 win_errstr(result)));
1334                                 }
1335                         }
1336
1337                         free_a_printer(&printer, 2);
1338                 }
1339         }
1340
1341         /* all done */
1342 }
1343
1344 /********************************************************************
1345  Update the cache for all printq's with a registered client
1346  connection
1347  ********************************************************************/
1348
1349 void update_monitored_printq_cache( void )
1350 {
1351         Printer_entry *printer = printers_list;
1352         int snum;
1353
1354         /* loop through all printers and update the cache where
1355            client_connected == True */
1356         while ( printer )
1357         {
1358                 if ( (printer->printer_type == SPLHND_PRINTER)
1359                         && printer->notify.client_connected )
1360                 {
1361                         snum = print_queue_snum(printer->sharename);
1362                         print_queue_status( snum, NULL, NULL );
1363                 }
1364
1365                 printer = printer->next;
1366         }
1367
1368         return;
1369 }
1370 /********************************************************************
1371  Send a message to ourself about new driver being installed
1372  so we can upgrade the information for each printer bound to this
1373  driver
1374  ********************************************************************/
1375
1376 static bool srv_spoolss_reset_printerdata(char* drivername)
1377 {
1378         int len = strlen(drivername);
1379
1380         if (!len)
1381                 return False;
1382
1383         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1384                 drivername));
1385
1386         messaging_send_buf(smbd_messaging_context(), procid_self(),
1387                            MSG_PRINTERDATA_INIT_RESET,
1388                            (uint8 *)drivername, len+1);
1389
1390         return True;
1391 }
1392
1393 /**********************************************************************
1394  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1395  over all printers, resetting printer data as neessary
1396  **********************************************************************/
1397
1398 void reset_all_printerdata(struct messaging_context *msg,
1399                            void *private_data,
1400                            uint32_t msg_type,
1401                            struct server_id server_id,
1402                            DATA_BLOB *data)
1403 {
1404         fstring drivername;
1405         int snum;
1406         int n_services = lp_numservices();
1407         size_t len;
1408
1409         len = MIN( data->length, sizeof(drivername)-1 );
1410         strncpy( drivername, (const char *)data->data, len );
1411
1412         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1413
1414         /* Iterate the printer list */
1415
1416         for ( snum=0; snum<n_services; snum++ )
1417         {
1418                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1419                 {
1420                         WERROR result;
1421                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1422
1423                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1424                         if ( !W_ERROR_IS_OK(result) )
1425                                 continue;
1426
1427                         /*
1428                          * if the printer is bound to the driver,
1429                          * then reset to the new driver initdata
1430                          */
1431
1432                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1433                         {
1434                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1435
1436                                 if ( !set_driver_init(printer, 2) ) {
1437                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1438                                                 printer->info_2->printername, printer->info_2->drivername));
1439                                 }
1440
1441                                 result = mod_a_printer( printer, 2 );
1442                                 if ( !W_ERROR_IS_OK(result) ) {
1443                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1444                                                 get_dos_error_msg(result)));
1445                                 }
1446                         }
1447
1448                         free_a_printer( &printer, 2 );
1449                 }
1450         }
1451
1452         /* all done */
1453
1454         return;
1455 }
1456
1457 /****************************************************************
1458  _spoolss_OpenPrinter
1459 ****************************************************************/
1460
1461 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1462                             struct spoolss_OpenPrinter *r)
1463 {
1464         struct spoolss_OpenPrinterEx e;
1465         WERROR werr;
1466
1467         ZERO_STRUCT(e.in.userlevel);
1468
1469         e.in.printername        = r->in.printername;
1470         e.in.datatype           = r->in.datatype;
1471         e.in.devmode_ctr        = r->in.devmode_ctr;
1472         e.in.access_mask        = r->in.access_mask;
1473         e.in.level              = 0;
1474
1475         e.out.handle            = r->out.handle;
1476
1477         werr = _spoolss_OpenPrinterEx(p, &e);
1478
1479         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1480                 /* OpenPrinterEx returns this for a bad
1481                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1482                  * instead.
1483                  */
1484                 werr = WERR_INVALID_PRINTER_NAME;
1485         }
1486
1487         return werr;
1488 }
1489
1490 /********************************************************************
1491  FIXME: temporary convert_devicemode_new function
1492  ********************************************************************/
1493
1494 static bool convert_devicemode_new(const char *printername,
1495                                    struct spoolss_DeviceMode *devmode,
1496                                    NT_DEVICEMODE **pp_nt_devmode)
1497 {
1498         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1499
1500         /*
1501          * Ensure nt_devmode is a valid pointer
1502          * as we will be overwriting it.
1503          */
1504
1505         if (nt_devmode == NULL) {
1506                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1507                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1508                         return false;
1509         }
1510
1511         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1512         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1513
1514         nt_devmode->specversion         = devmode->specversion;
1515         nt_devmode->driverversion       = devmode->driverversion;
1516         nt_devmode->size                = devmode->size;
1517         nt_devmode->fields              = devmode->fields;
1518         nt_devmode->orientation         = devmode->orientation;
1519         nt_devmode->papersize           = devmode->papersize;
1520         nt_devmode->paperlength         = devmode->paperlength;
1521         nt_devmode->paperwidth          = devmode->paperwidth;
1522         nt_devmode->scale               = devmode->scale;
1523         nt_devmode->copies              = devmode->copies;
1524         nt_devmode->defaultsource       = devmode->defaultsource;
1525         nt_devmode->printquality        = devmode->printquality;
1526         nt_devmode->color               = devmode->color;
1527         nt_devmode->duplex              = devmode->duplex;
1528         nt_devmode->yresolution         = devmode->yresolution;
1529         nt_devmode->ttoption            = devmode->ttoption;
1530         nt_devmode->collate             = devmode->collate;
1531
1532         nt_devmode->logpixels           = devmode->logpixels;
1533         nt_devmode->bitsperpel          = devmode->bitsperpel;
1534         nt_devmode->pelswidth           = devmode->pelswidth;
1535         nt_devmode->pelsheight          = devmode->pelsheight;
1536         nt_devmode->displayflags        = devmode->displayflags;
1537         nt_devmode->displayfrequency    = devmode->displayfrequency;
1538         nt_devmode->icmmethod           = devmode->icmmethod;
1539         nt_devmode->icmintent           = devmode->icmintent;
1540         nt_devmode->mediatype           = devmode->mediatype;
1541         nt_devmode->dithertype          = devmode->dithertype;
1542         nt_devmode->reserved1           = devmode->reserved1;
1543         nt_devmode->reserved2           = devmode->reserved2;
1544         nt_devmode->panningwidth        = devmode->panningwidth;
1545         nt_devmode->panningheight       = devmode->panningheight;
1546
1547         /*
1548          * Only change private and driverextra if the incoming devmode
1549          * has a new one. JRA.
1550          */
1551
1552         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1553                 SAFE_FREE(nt_devmode->nt_dev_private);
1554                 nt_devmode->driverextra = devmode->__driverextra_length;
1555                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1556                         return false;
1557                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1558         }
1559
1560         *pp_nt_devmode = nt_devmode;
1561
1562         return true;
1563 }
1564
1565 /****************************************************************
1566  _spoolss_OpenPrinterEx
1567 ****************************************************************/
1568
1569 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1570                               struct spoolss_OpenPrinterEx *r)
1571 {
1572         POLICY_HND              *handle = r->out.handle;
1573         char *name = CONST_DISCARD(char *, r->in.printername);
1574         int snum;
1575         Printer_entry *Printer=NULL;
1576
1577         if (!name) {
1578                 return WERR_INVALID_PARAM;
1579         }
1580
1581         /* some sanity check because you can open a printer or a print server */
1582         /* aka: \\server\printer or \\server */
1583
1584         DEBUGADD(3,("checking name: %s\n",name));
1585
1586         if (!open_printer_hnd(p, handle, name, 0)) {
1587                 ZERO_STRUCTP(r->out.handle);
1588                 return WERR_INVALID_PARAM;
1589         }
1590
1591         Printer=find_printer_index_by_hnd(p, handle);
1592         if ( !Printer ) {
1593                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1594                         "handle we created for printer %s\n", name ));
1595                 close_printer_handle(p,handle);
1596                 ZERO_STRUCTP(r->out.handle);
1597                 return WERR_INVALID_PARAM;
1598         }
1599
1600         /*
1601          * First case: the user is opening the print server:
1602          *
1603          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1604          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1605          *
1606          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1607          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1608          * or if the user is listed in the smb.conf printer admin parameter.
1609          *
1610          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1611          * client view printer folder, but does not show the MSAPW.
1612          *
1613          * Note: this test needs code to check access rights here too. Jeremy
1614          * could you look at this?
1615          *
1616          * Second case: the user is opening a printer:
1617          * NT doesn't let us connect to a printer if the connecting user
1618          * doesn't have print permission.
1619          *
1620          * Third case: user is opening a Port Monitor
1621          * access checks same as opening a handle to the print server.
1622          */
1623
1624         switch (Printer->printer_type )
1625         {
1626         case SPLHND_SERVER:
1627         case SPLHND_PORTMON_TCP:
1628         case SPLHND_PORTMON_LOCAL:
1629                 /* Printserver handles use global struct... */
1630
1631                 snum = -1;
1632
1633                 /* Map standard access rights to object specific access rights */
1634
1635                 se_map_standard(&r->in.access_mask,
1636                                 &printserver_std_mapping);
1637
1638                 /* Deny any object specific bits that don't apply to print
1639                    servers (i.e printer and job specific bits) */
1640
1641                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1642
1643                 if (r->in.access_mask &
1644                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1645                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1646                         close_printer_handle(p, handle);
1647                         ZERO_STRUCTP(r->out.handle);
1648                         return WERR_ACCESS_DENIED;
1649                 }
1650
1651                 /* Allow admin access */
1652
1653                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1654                 {
1655                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1656
1657                         if (!lp_ms_add_printer_wizard()) {
1658                                 close_printer_handle(p, handle);
1659                                 ZERO_STRUCTP(r->out.handle);
1660                                 return WERR_ACCESS_DENIED;
1661                         }
1662
1663                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1664                            and not a printer admin, then fail */
1665
1666                         if ((p->server_info->utok.uid != 0) &&
1667                             !user_has_privileges(p->server_info->ptok,
1668                                                  &se_printop ) &&
1669                             !token_contains_name_in_list(
1670                                     uidtoname(p->server_info->utok.uid),
1671                                     NULL, NULL,
1672                                     p->server_info->ptok,
1673                                     lp_printer_admin(snum))) {
1674                                 close_printer_handle(p, handle);
1675                                 ZERO_STRUCTP(r->out.handle);
1676                                 return WERR_ACCESS_DENIED;
1677                         }
1678
1679                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1680                 }
1681                 else
1682                 {
1683                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1684                 }
1685
1686                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1687                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1688
1689                 /* We fall through to return WERR_OK */
1690                 break;
1691
1692         case SPLHND_PRINTER:
1693                 /* NT doesn't let us connect to a printer if the connecting user
1694                    doesn't have print permission.  */
1695
1696                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1697                         close_printer_handle(p, handle);
1698                         ZERO_STRUCTP(r->out.handle);
1699                         return WERR_BADFID;
1700                 }
1701
1702                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1703
1704                 /* map an empty access mask to the minimum access mask */
1705                 if (r->in.access_mask == 0x0)
1706                         r->in.access_mask = PRINTER_ACCESS_USE;
1707
1708                 /*
1709                  * If we are not serving the printer driver for this printer,
1710                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1711                  * will keep NT clients happy  --jerry
1712                  */
1713
1714                 if (lp_use_client_driver(snum)
1715                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1716                 {
1717                         r->in.access_mask = PRINTER_ACCESS_USE;
1718                 }
1719
1720                 /* check smb.conf parameters and the the sec_desc */
1721
1722                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1723                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1724                         ZERO_STRUCTP(r->out.handle);
1725                         return WERR_ACCESS_DENIED;
1726                 }
1727
1728                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1729                                    p->server_info->ptok, snum) ||
1730                     !print_access_check(p->server_info, snum,
1731                                         r->in.access_mask)) {
1732                         DEBUG(3, ("access DENIED for printer open\n"));
1733                         close_printer_handle(p, handle);
1734                         ZERO_STRUCTP(r->out.handle);
1735                         return WERR_ACCESS_DENIED;
1736                 }
1737
1738                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1739                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1740                         close_printer_handle(p, handle);
1741                         ZERO_STRUCTP(r->out.handle);
1742                         return WERR_ACCESS_DENIED;
1743                 }
1744
1745                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1746                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1747                 else
1748                         r->in.access_mask = PRINTER_ACCESS_USE;
1749
1750                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1751                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1752
1753                 break;
1754
1755         default:
1756                 /* sanity check to prevent programmer error */
1757                 ZERO_STRUCTP(r->out.handle);
1758                 return WERR_BADFID;
1759         }
1760
1761         Printer->access_granted = r->in.access_mask;
1762
1763         /*
1764          * If the client sent a devmode in the OpenPrinter() call, then
1765          * save it here in case we get a job submission on this handle
1766          */
1767
1768          if ( (Printer->printer_type != SPLHND_SERVER)
1769                 && r->in.devmode_ctr.devmode )
1770          {
1771                 convert_devicemode_new(Printer->sharename,
1772                                        r->in.devmode_ctr.devmode,
1773                                        &Printer->nt_devmode);
1774          }
1775
1776 #if 0   /* JERRY -- I'm doubtful this is really effective */
1777         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1778            optimization in Windows 2000 clients  --jerry */
1779
1780         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1781                 && (RA_WIN2K == get_remote_arch()) )
1782         {
1783                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1784                 sys_usleep( 500000 );
1785         }
1786 #endif
1787
1788         return WERR_OK;
1789 }
1790
1791 /****************************************************************************
1792 ****************************************************************************/
1793
1794 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1795                                               NT_PRINTER_INFO_LEVEL_2 *d)
1796 {
1797         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1798
1799         if (!r || !d) {
1800                 return false;
1801         }
1802
1803         d->attributes           = r->attributes;
1804         d->priority             = r->priority;
1805         d->default_priority     = r->defaultpriority;
1806         d->starttime            = r->starttime;
1807         d->untiltime            = r->untiltime;
1808         d->status               = r->status;
1809         d->cjobs                = r->cjobs;
1810
1811         fstrcpy(d->servername,  r->servername);
1812         fstrcpy(d->printername, r->printername);
1813         fstrcpy(d->sharename,   r->sharename);
1814         fstrcpy(d->portname,    r->portname);
1815         fstrcpy(d->drivername,  r->drivername);
1816         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1817         fstrcpy(d->location,    r->location);
1818         fstrcpy(d->sepfile,     r->sepfile);
1819         fstrcpy(d->printprocessor, r->printprocessor);
1820         fstrcpy(d->datatype,    r->datatype);
1821         fstrcpy(d->parameters,  r->parameters);
1822
1823         return true;
1824 }
1825
1826 /****************************************************************************
1827 ****************************************************************************/
1828
1829 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1830                                      NT_PRINTER_INFO_LEVEL *printer)
1831 {
1832         bool ret;
1833
1834         switch (info_ctr->level) {
1835         case 2:
1836                 /* allocate memory if needed.  Messy because
1837                    convert_printer_info is used to update an existing
1838                    printer or build a new one */
1839
1840                 if (!printer->info_2) {
1841                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1842                         if (!printer->info_2) {
1843                                 DEBUG(0,("convert_printer_info_new: "
1844                                         "talloc() failed!\n"));
1845                                 return false;
1846                         }
1847                 }
1848
1849                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1850                                                         printer->info_2);
1851                 printer->info_2->setuptime = time(NULL);
1852                 return ret;
1853         }
1854
1855         return false;
1856 }
1857
1858 /*******************************************************************
1859 ********************************************************************/
1860
1861 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1862 {
1863         int i;
1864
1865         if (!sarray) {
1866                 *farray = NULL;
1867                 return true;
1868         }
1869
1870         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1871         if (!*farray) {
1872                 return false;
1873         }
1874
1875         for (i=0; sarray[i] != NULL; i++) {
1876                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1877                 if (!*farray) {
1878                         return false;
1879                 }
1880                 fstrcpy((*farray)[i], sarray[i]);
1881         }
1882
1883         fstrcpy((*farray)[i], "");
1884
1885         return true;
1886 }
1887
1888 /*******************************************************************
1889 ********************************************************************/
1890
1891 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1892                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1893 {
1894         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1895
1896         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1897
1898         if (*p == NULL) {
1899                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1900                 if (*p == NULL) {
1901                         return false;
1902                 }
1903                 ZERO_STRUCTP(*p);
1904         }
1905
1906         d = *p;
1907
1908         d->cversion =                   r->version;
1909
1910         fstrcpy(d->name,                r->driver_name);
1911         fstrcpy(d->environment,         r->architecture);
1912         fstrcpy(d->driverpath,          r->driver_path);
1913         fstrcpy(d->datafile,            r->data_file);
1914         fstrcpy(d->configfile,          r->config_file);
1915         fstrcpy(d->helpfile,            r->help_file);
1916         fstrcpy(d->monitorname,         r->monitor_name);
1917         fstrcpy(d->defaultdatatype,     r->default_datatype);
1918
1919         DEBUGADD(8,( "version:         %d\n", d->cversion));
1920         DEBUGADD(8,( "name:            %s\n", d->name));
1921         DEBUGADD(8,( "environment:     %s\n", d->environment));
1922         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1923         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1924         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1925         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1926         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1927         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1928
1929         if (r->dependent_files) {
1930                 if (!string_array_to_fstring_array(r->dependent_files->string,
1931                                                    &d->dependentfiles)) {
1932                         SAFE_FREE(*p);
1933                         return false;
1934                 }
1935         }
1936
1937         return true;
1938 }
1939
1940 /*******************************************************************
1941 ********************************************************************/
1942
1943 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1944                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1945 {
1946         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1947
1948         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1949
1950         if (*p == NULL) {
1951                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1952                 if (*p == NULL) {
1953                         return false;
1954                 }
1955                 ZERO_STRUCTP(*p);
1956         }
1957
1958         d = *p;
1959
1960         d->version =                    r->version;
1961
1962         fstrcpy(d->name,                r->driver_name);
1963         fstrcpy(d->environment,         r->architecture);
1964         fstrcpy(d->driverpath,          r->driver_path);
1965         fstrcpy(d->datafile,            r->data_file);
1966         fstrcpy(d->configfile,          r->config_file);
1967         fstrcpy(d->helpfile,            r->help_file);
1968         fstrcpy(d->monitorname,         r->monitor_name);
1969         fstrcpy(d->defaultdatatype,     r->default_datatype);
1970
1971         DEBUGADD(8,( "version:         %d\n", d->version));
1972         DEBUGADD(8,( "name:            %s\n", d->name));
1973         DEBUGADD(8,( "environment:     %s\n", d->environment));
1974         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1975         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1976         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1977         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1978         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1979         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1980
1981         if (r->dependent_files) {
1982                 if (!string_array_to_fstring_array(r->dependent_files->string,
1983                                                    &d->dependentfiles)) {
1984                         goto error;
1985                 }
1986         }
1987
1988         if (r->previous_names) {
1989                 if (!string_array_to_fstring_array(r->previous_names->string,
1990                                                    &d->previousnames)) {
1991                         goto error;
1992                 }
1993         }
1994
1995         return true;
1996
1997  error:
1998         SAFE_FREE(*p);
1999         return false;
2000 }
2001
2002 /********************************************************************
2003  ********************************************************************/
2004
2005 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
2006                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
2007                                         uint32_t level)
2008 {
2009         switch (level) {
2010         case 3:
2011                 printer->info_3 = NULL;
2012                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
2013                         return false;
2014                 }
2015                 break;
2016         case 6:
2017                 printer->info_6 = NULL;
2018                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
2019                         return false;
2020                 }
2021                 break;
2022         default:
2023                 return false;
2024         }
2025
2026         return true;
2027 }
2028
2029 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
2030                                 NT_DEVICEMODE **pp_nt_devmode)
2031 {
2032         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2033
2034         /*
2035          * Ensure nt_devmode is a valid pointer
2036          * as we will be overwriting it.
2037          */
2038
2039         if (nt_devmode == NULL) {
2040                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2041                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2042                         return False;
2043         }
2044
2045         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2046         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2047
2048         nt_devmode->specversion=devmode->specversion;
2049         nt_devmode->driverversion=devmode->driverversion;
2050         nt_devmode->size=devmode->size;
2051         nt_devmode->fields=devmode->fields;
2052         nt_devmode->orientation=devmode->orientation;
2053         nt_devmode->papersize=devmode->papersize;
2054         nt_devmode->paperlength=devmode->paperlength;
2055         nt_devmode->paperwidth=devmode->paperwidth;
2056         nt_devmode->scale=devmode->scale;
2057         nt_devmode->copies=devmode->copies;
2058         nt_devmode->defaultsource=devmode->defaultsource;
2059         nt_devmode->printquality=devmode->printquality;
2060         nt_devmode->color=devmode->color;
2061         nt_devmode->duplex=devmode->duplex;
2062         nt_devmode->yresolution=devmode->yresolution;
2063         nt_devmode->ttoption=devmode->ttoption;
2064         nt_devmode->collate=devmode->collate;
2065
2066         nt_devmode->logpixels=devmode->logpixels;
2067         nt_devmode->bitsperpel=devmode->bitsperpel;
2068         nt_devmode->pelswidth=devmode->pelswidth;
2069         nt_devmode->pelsheight=devmode->pelsheight;
2070         nt_devmode->displayflags=devmode->displayflags;
2071         nt_devmode->displayfrequency=devmode->displayfrequency;
2072         nt_devmode->icmmethod=devmode->icmmethod;
2073         nt_devmode->icmintent=devmode->icmintent;
2074         nt_devmode->mediatype=devmode->mediatype;
2075         nt_devmode->dithertype=devmode->dithertype;
2076         nt_devmode->reserved1=devmode->reserved1;
2077         nt_devmode->reserved2=devmode->reserved2;
2078         nt_devmode->panningwidth=devmode->panningwidth;
2079         nt_devmode->panningheight=devmode->panningheight;
2080
2081         /*
2082          * Only change private and driverextra if the incoming devmode
2083          * has a new one. JRA.
2084          */
2085
2086         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2087                 SAFE_FREE(nt_devmode->nt_dev_private);
2088                 nt_devmode->driverextra=devmode->driverextra;
2089                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2090                         return False;
2091                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2092         }
2093
2094         *pp_nt_devmode = nt_devmode;
2095
2096         return True;
2097 }
2098
2099 /********************************************************************
2100  * _spoolss_enddocprinter_internal.
2101  ********************************************************************/
2102
2103 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2104 {
2105         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2106         int snum;
2107
2108         if (!Printer) {
2109                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2110                 return WERR_BADFID;
2111         }
2112
2113         if (!get_printer_snum(p, handle, &snum, NULL))
2114                 return WERR_BADFID;
2115
2116         Printer->document_started=False;
2117         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2118         /* error codes unhandled so far ... */
2119
2120         return WERR_OK;
2121 }
2122
2123 /****************************************************************
2124  _spoolss_ClosePrinter
2125 ****************************************************************/
2126
2127 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2128                              struct spoolss_ClosePrinter *r)
2129 {
2130         POLICY_HND *handle = r->in.handle;
2131
2132         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2133
2134         if (Printer && Printer->document_started)
2135                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2136
2137         if (!close_printer_handle(p, handle))
2138                 return WERR_BADFID;
2139
2140         /* clear the returned printer handle.  Observed behavior
2141            from Win2k server.  Don't think this really matters.
2142            Previous code just copied the value of the closed
2143            handle.    --jerry */
2144
2145         ZERO_STRUCTP(r->out.handle);
2146
2147         return WERR_OK;
2148 }
2149
2150 /****************************************************************
2151  _spoolss_DeletePrinter
2152 ****************************************************************/
2153
2154 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2155                               struct spoolss_DeletePrinter *r)
2156 {
2157         POLICY_HND *handle = r->in.handle;
2158         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2159         WERROR result;
2160
2161         if (Printer && Printer->document_started)
2162                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2163
2164         result = delete_printer_handle(p, handle);
2165
2166         update_c_setprinter(False);
2167
2168         return result;
2169 }
2170
2171 /*******************************************************************
2172  * static function to lookup the version id corresponding to an
2173  * long architecture string
2174  ******************************************************************/
2175
2176 static int get_version_id (char * arch)
2177 {
2178         int i;
2179         struct table_node archi_table[]= {
2180
2181                 {"Windows 4.0",          "WIN40",       0 },
2182                 {"Windows NT x86",       "W32X86",      2 },
2183                 {"Windows NT R4000",     "W32MIPS",     2 },
2184                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2185                 {"Windows NT PowerPC",   "W32PPC",      2 },
2186                 {"Windows IA64",         "IA64",        3 },
2187                 {"Windows x64",          "x64",         3 },
2188                 {NULL,                   "",            -1 }
2189         };
2190
2191         for (i=0; archi_table[i].long_archi != NULL; i++)
2192         {
2193                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2194                         return (archi_table[i].version);
2195         }
2196
2197         return -1;
2198 }
2199
2200 /****************************************************************
2201  _spoolss_DeletePrinterDriver
2202 ****************************************************************/
2203
2204 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2205                                     struct spoolss_DeletePrinterDriver *r)
2206 {
2207         char *driver;
2208         char *arch;
2209         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2210         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2211         int                             version;
2212         WERROR                          status;
2213         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2214         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2215
2216         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2217            and not a printer admin, then fail */
2218
2219         if ( (p->server_info->utok.uid != 0)
2220                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2221                 && !token_contains_name_in_list(
2222                         uidtoname(p->server_info->utok.uid), NULL,
2223                         NULL, p->server_info->ptok,
2224                         lp_printer_admin(-1)) )
2225         {
2226                 return WERR_ACCESS_DENIED;
2227         }
2228
2229         driver = CONST_DISCARD(char *, r->in.driver);
2230         arch   = CONST_DISCARD(char *, r->in.architecture);
2231
2232         /* check that we have a valid driver name first */
2233
2234         if ((version=get_version_id(arch)) == -1)
2235                 return WERR_INVALID_ENVIRONMENT;
2236
2237         ZERO_STRUCT(info);
2238         ZERO_STRUCT(info_win2k);
2239
2240         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2241         {
2242                 /* try for Win2k driver if "Windows NT x86" */
2243
2244                 if ( version == 2 ) {
2245                         version = 3;
2246                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2247                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2248                                 goto done;
2249                         }
2250                 }
2251                 /* otherwise it was a failure */
2252                 else {
2253                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2254                         goto done;
2255                 }
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         if ( version == 2 )
2265         {
2266                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2267                 {
2268                         /* if we get to here, we now have 2 driver info structures to remove */
2269                         /* remove the Win2k driver first*/
2270
2271                         status_win2k = delete_printer_driver(
2272                                 p, info_win2k.info_3, 3, False );
2273                         free_a_printer_driver( info_win2k, 3 );
2274
2275                         /* this should not have failed---if it did, report to client */
2276                         if ( !W_ERROR_IS_OK(status_win2k) )
2277                         {
2278                                 status = status_win2k;
2279                                 goto done;
2280                         }
2281                 }
2282         }
2283
2284         status = delete_printer_driver(p, info.info_3, version, False);
2285
2286         /* if at least one of the deletes succeeded return OK */
2287
2288         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2289                 status = WERR_OK;
2290
2291 done:
2292         free_a_printer_driver( info, 3 );
2293
2294         return status;
2295 }
2296
2297 /****************************************************************
2298  _spoolss_DeletePrinterDriverEx
2299 ****************************************************************/
2300
2301 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2302                                       struct spoolss_DeletePrinterDriverEx *r)
2303 {
2304         char *driver;
2305         char *arch;
2306         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2307         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2308         int                             version;
2309         uint32_t                        flags = r->in.delete_flags;
2310         bool                            delete_files;
2311         WERROR                          status;
2312         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2313         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2314
2315         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2316            and not a printer admin, then fail */
2317
2318         if ( (p->server_info->utok.uid != 0)
2319                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2320                 && !token_contains_name_in_list(
2321                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2322                         p->server_info->ptok, lp_printer_admin(-1)) )
2323         {
2324                 return WERR_ACCESS_DENIED;
2325         }
2326
2327         driver = CONST_DISCARD(char *, r->in.driver);
2328         arch   = CONST_DISCARD(char *, r->in.architecture);
2329
2330         /* check that we have a valid driver name first */
2331         if ((version=get_version_id(arch)) == -1) {
2332                 /* this is what NT returns */
2333                 return WERR_INVALID_ENVIRONMENT;
2334         }
2335
2336         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2337                 version = r->in.version;
2338
2339         ZERO_STRUCT(info);
2340         ZERO_STRUCT(info_win2k);
2341
2342         status = get_a_printer_driver(&info, 3, driver, arch, version);
2343
2344         if ( !W_ERROR_IS_OK(status) )
2345         {
2346                 /*
2347                  * if the client asked for a specific version,
2348                  * or this is something other than Windows NT x86,
2349                  * then we've failed
2350                  */
2351
2352                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2353                         goto done;
2354
2355                 /* try for Win2k driver if "Windows NT x86" */
2356
2357                 version = 3;
2358                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2359                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2360                         goto done;
2361                 }
2362         }
2363
2364         if ( printer_driver_in_use(info.info_3) ) {
2365                 status = WERR_PRINTER_DRIVER_IN_USE;
2366                 goto done;
2367         }
2368
2369         /*
2370          * we have a couple of cases to consider.
2371          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2372          *     then the delete should fail if **any** files overlap with
2373          *     other drivers
2374          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2375          *     non-overlapping files
2376          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2377          *     is set, the do not delete any files
2378          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2379          */
2380
2381         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2382
2383         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2384
2385         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2386                 /* no idea of the correct error here */
2387                 status = WERR_ACCESS_DENIED;
2388                 goto done;
2389         }
2390
2391
2392         /* also check for W32X86/3 if necessary; maybe we already have? */
2393
2394         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2395                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2396                 {
2397
2398                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2399                                 /* no idea of the correct error here */
2400                                 free_a_printer_driver( info_win2k, 3 );
2401                                 status = WERR_ACCESS_DENIED;
2402                                 goto done;
2403                         }
2404
2405                         /* if we get to here, we now have 2 driver info structures to remove */
2406                         /* remove the Win2k driver first*/
2407
2408                         status_win2k = delete_printer_driver(
2409                                 p, info_win2k.info_3, 3, delete_files);
2410                         free_a_printer_driver( info_win2k, 3 );
2411
2412                         /* this should not have failed---if it did, report to client */
2413
2414                         if ( !W_ERROR_IS_OK(status_win2k) )
2415                                 goto done;
2416                 }
2417         }
2418
2419         status = delete_printer_driver(p, info.info_3, version, delete_files);
2420
2421         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2422                 status = WERR_OK;
2423 done:
2424         free_a_printer_driver( info, 3 );
2425
2426         return status;
2427 }
2428
2429
2430 /****************************************************************************
2431  Internal routine for retreiving printerdata
2432  ***************************************************************************/
2433
2434 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2435                                   const char *key, const char *value, uint32 *type, uint8 **data,
2436                                   uint32 *needed, uint32 in_size  )
2437 {
2438         REGISTRY_VALUE          *val;
2439         uint32                  size;
2440         int                     data_len;
2441
2442         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2443                 return WERR_BADFILE;
2444
2445         *type = regval_type( val );
2446
2447         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2448
2449         size = regval_size( val );
2450
2451         /* copy the min(in_size, len) */
2452
2453         if ( in_size ) {
2454                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2455
2456                 /* special case for 0 length values */
2457                 if ( data_len ) {
2458                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2459                                 return WERR_NOMEM;
2460                 }
2461                 else {
2462                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2463                                 return WERR_NOMEM;
2464                 }
2465         }
2466         else
2467                 *data = NULL;
2468
2469         *needed = size;
2470
2471         DEBUG(5,("get_printer_dataex: copy done\n"));
2472
2473         return WERR_OK;
2474 }
2475
2476 /****************************************************************************
2477  Internal routine for removing printerdata
2478  ***************************************************************************/
2479
2480 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2481 {
2482         return delete_printer_data( printer->info_2, key, value );
2483 }
2484
2485 /****************************************************************************
2486  Internal routine for storing printerdata
2487  ***************************************************************************/
2488
2489 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2490                                   uint32 type, uint8 *data, int real_len  )
2491 {
2492         /* the registry objects enforce uniqueness based on value name */
2493
2494         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2495 }
2496
2497 /********************************************************************
2498  GetPrinterData on a printer server Handle.
2499 ********************************************************************/
2500
2501 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2502 {
2503         int i;
2504
2505         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2506
2507         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2508                 *type = REG_DWORD;
2509                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2510                         return WERR_NOMEM;
2511                 SIVAL(*data, 0, 0x00);
2512                 *needed = 0x4;
2513                 return WERR_OK;
2514         }
2515
2516         if (!StrCaseCmp(value, "BeepEnabled")) {
2517                 *type = REG_DWORD;
2518                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2519                         return WERR_NOMEM;
2520                 SIVAL(*data, 0, 0x00);
2521                 *needed = 0x4;
2522                 return WERR_OK;
2523         }
2524
2525         if (!StrCaseCmp(value, "EventLog")) {
2526                 *type = REG_DWORD;
2527                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2528                         return WERR_NOMEM;
2529                 /* formally was 0x1b */
2530                 SIVAL(*data, 0, 0x0);
2531                 *needed = 0x4;
2532                 return WERR_OK;
2533         }
2534
2535         if (!StrCaseCmp(value, "NetPopup")) {
2536                 *type = REG_DWORD;
2537                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2538                         return WERR_NOMEM;
2539                 SIVAL(*data, 0, 0x00);
2540                 *needed = 0x4;
2541                 return WERR_OK;
2542         }
2543
2544         if (!StrCaseCmp(value, "MajorVersion")) {
2545                 *type = REG_DWORD;
2546                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2547                         return WERR_NOMEM;
2548
2549                 /* Windows NT 4.0 seems to not allow uploading of drivers
2550                    to a server that reports 0x3 as the MajorVersion.
2551                    need to investigate more how Win2k gets around this .
2552                    -- jerry */
2553
2554                 if ( RA_WINNT == get_remote_arch() )
2555                         SIVAL(*data, 0, 2);
2556                 else
2557                         SIVAL(*data, 0, 3);
2558
2559                 *needed = 0x4;
2560                 return WERR_OK;
2561         }
2562
2563         if (!StrCaseCmp(value, "MinorVersion")) {
2564                 *type = REG_DWORD;
2565                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2566                         return WERR_NOMEM;
2567                 SIVAL(*data, 0, 0);
2568                 *needed = 0x4;
2569                 return WERR_OK;
2570         }
2571
2572         /* REG_BINARY
2573          *  uint32 size          = 0x114
2574          *  uint32 major         = 5
2575          *  uint32 minor         = [0|1]
2576          *  uint32 build         = [2195|2600]
2577          *  extra unicode string = e.g. "Service Pack 3"
2578          */
2579         if (!StrCaseCmp(value, "OSVersion")) {
2580                 *type = REG_BINARY;
2581                 *needed = 0x114;
2582
2583                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2584                         return WERR_NOMEM;
2585
2586                 SIVAL(*data, 0, *needed);       /* size */
2587                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2588                 SIVAL(*data, 8, 0);
2589                 SIVAL(*data, 12, 2195);         /* build */
2590
2591                 /* leave extra string empty */
2592
2593                 return WERR_OK;
2594         }
2595
2596
2597         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2598                 const char *string="C:\\PRINTERS";
2599                 *type = REG_SZ;
2600                 *needed = 2*(strlen(string)+1);
2601                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2602                         return WERR_NOMEM;
2603                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2604
2605                 /* it's done by hand ready to go on the wire */
2606                 for (i=0; i<strlen(string); i++) {
2607                         (*data)[2*i]=string[i];
2608                         (*data)[2*i+1]='\0';
2609                 }
2610                 return WERR_OK;
2611         }
2612
2613         if (!StrCaseCmp(value, "Architecture")) {
2614                 const char *string="Windows NT x86";
2615                 *type = REG_SZ;
2616                 *needed = 2*(strlen(string)+1);
2617                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2618                         return WERR_NOMEM;
2619                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2620                 for (i=0; i<strlen(string); i++) {
2621                         (*data)[2*i]=string[i];
2622                         (*data)[2*i+1]='\0';
2623                 }
2624                 return WERR_OK;
2625         }
2626
2627         if (!StrCaseCmp(value, "DsPresent")) {
2628                 *type = REG_DWORD;
2629                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2630                         return WERR_NOMEM;
2631
2632                 /* only show the publish check box if we are a
2633                    memeber of a AD domain */
2634
2635                 if ( lp_security() == SEC_ADS )
2636                         SIVAL(*data, 0, 0x01);
2637                 else
2638                         SIVAL(*data, 0, 0x00);
2639
2640                 *needed = 0x4;
2641                 return WERR_OK;
2642         }
2643
2644         if (!StrCaseCmp(value, "DNSMachineName")) {
2645                 const char *hostname = get_mydnsfullname();
2646
2647                 if (!hostname)
2648                         return WERR_BADFILE;
2649                 *type = REG_SZ;
2650                 *needed = 2*(strlen(hostname)+1);
2651                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2652                         return WERR_NOMEM;
2653                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2654                 for (i=0; i<strlen(hostname); i++) {
2655                         (*data)[2*i]=hostname[i];
2656                         (*data)[2*i+1]='\0';
2657                 }
2658                 return WERR_OK;
2659         }
2660
2661
2662         return WERR_BADFILE;
2663 }
2664
2665 /********************************************************************
2666  * spoolss_getprinterdata
2667  ********************************************************************/
2668
2669 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2670 {
2671         POLICY_HND      *handle = &q_u->handle;
2672         UNISTR2         *valuename = &q_u->valuename;
2673         uint32          in_size = q_u->size;
2674         uint32          *type = &r_u->type;
2675         uint32          *out_size = &r_u->size;
2676         uint8           **data = &r_u->data;
2677         uint32          *needed = &r_u->needed;
2678         WERROR          status;
2679         fstring         value;
2680         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2681         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2682         int             snum = 0;
2683
2684         /*
2685          * Reminder: when it's a string, the length is in BYTES
2686          * even if UNICODE is negociated.
2687          *
2688          * JFM, 4/19/1999
2689          */
2690
2691         *out_size = in_size;
2692
2693         /* in case of problem, return some default values */
2694
2695         *needed = 0;
2696         *type   = 0;
2697
2698         DEBUG(4,("_spoolss_getprinterdata\n"));
2699
2700         if ( !Printer ) {
2701                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2702                 status = WERR_BADFID;
2703                 goto done;
2704         }
2705
2706         unistr2_to_ascii(value, valuename, sizeof(value));
2707
2708         if ( Printer->printer_type == SPLHND_SERVER )
2709                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2710         else
2711         {
2712                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2713                         status = WERR_BADFID;
2714                         goto done;
2715                 }
2716
2717                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2718                 if ( !W_ERROR_IS_OK(status) )
2719                         goto done;
2720
2721                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2722
2723                 if ( strequal(value, "ChangeId") ) {
2724                         *type = REG_DWORD;
2725                         *needed = sizeof(uint32);
2726                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2727                                 status = WERR_NOMEM;
2728                                 goto done;
2729                         }
2730                         SIVAL( *data, 0, printer->info_2->changeid );
2731                         status = WERR_OK;
2732                 }
2733                 else
2734                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2735         }
2736
2737         if (*needed > *out_size)
2738                 status = WERR_MORE_DATA;
2739
2740 done:
2741         if ( !W_ERROR_IS_OK(status) )
2742         {
2743                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2744
2745                 /* reply this param doesn't exist */
2746
2747                 if ( *out_size ) {
2748                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2749                                 if ( printer )
2750                                         free_a_printer( &printer, 2 );
2751                                 return WERR_NOMEM;
2752                         }
2753                 } else {
2754                         *data = NULL;
2755                 }
2756         }
2757
2758         /* cleanup & exit */
2759
2760         if ( printer )
2761                 free_a_printer( &printer, 2 );
2762
2763         return status;
2764 }
2765
2766 /*********************************************************
2767  Connect to the client machine.
2768 **********************************************************/
2769
2770 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2771                         struct sockaddr_storage *client_ss, const char *remote_machine)
2772 {
2773         NTSTATUS ret;
2774         struct cli_state *the_cli;
2775         struct sockaddr_storage rm_addr;
2776
2777         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2778                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2779                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2780                         return False;
2781                 }
2782
2783                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2784                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2785                         return False;
2786                 }
2787         } else {
2788                 char addr[INET6_ADDRSTRLEN];
2789                 rm_addr = *client_ss;
2790                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2791                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2792                         addr));
2793         }
2794
2795         /* setup the connection */
2796
2797         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2798                 &rm_addr, 0, "IPC$", "IPC",
2799                 "", /* username */
2800                 "", /* domain */
2801                 "", /* password */
2802                 0, lp_client_signing(), NULL );
2803
2804         if ( !NT_STATUS_IS_OK( ret ) ) {
2805                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2806                         remote_machine ));
2807                 return False;
2808         }
2809
2810         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2811                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2812                 cli_shutdown(the_cli);
2813                 return False;
2814         }
2815
2816         /*
2817          * Ok - we have an anonymous connection to the IPC$ share.
2818          * Now start the NT Domain stuff :-).
2819          */
2820
2821         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2822         if (!NT_STATUS_IS_OK(ret)) {
2823                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2824                         remote_machine, nt_errstr(ret)));
2825                 cli_shutdown(the_cli);
2826                 return False;
2827         }
2828
2829         return True;
2830 }
2831
2832 /***************************************************************************
2833  Connect to the client.
2834 ****************************************************************************/
2835
2836 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2837                                         uint32 localprinter, uint32 type,
2838                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2839 {
2840         WERROR result;
2841         NTSTATUS status;
2842
2843         /*
2844          * If it's the first connection, contact the client
2845          * and connect to the IPC$ share anonymously
2846          */
2847         if (smb_connections==0) {
2848                 fstring unix_printer;
2849
2850                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2851
2852                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2853                         return False;
2854
2855                 messaging_register(smbd_messaging_context(), NULL,
2856                                    MSG_PRINTER_NOTIFY2,
2857                                    receive_notify2_message_list);
2858                 /* Tell the connections db we're now interested in printer
2859                  * notify messages. */
2860                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2861         }
2862
2863         /*
2864          * Tell the specific printing tdb we want messages for this printer
2865          * by registering our PID.
2866          */
2867
2868         if (!print_notify_register_pid(snum))
2869                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2870
2871         smb_connections++;
2872
2873         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2874                                                  printer,
2875                                                  localprinter,
2876                                                  type,
2877                                                  0,
2878                                                  NULL,
2879                                                  handle,
2880                                                  &result);
2881         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2882                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2883                         win_errstr(result)));
2884
2885         return (W_ERROR_IS_OK(result));
2886 }
2887
2888 /********************************************************************
2889  * _spoolss_rffpcnex
2890  * ReplyFindFirstPrinterChangeNotifyEx
2891  *
2892  * before replying OK: status=0 a rpc call is made to the workstation
2893  * asking ReplyOpenPrinter
2894  *
2895  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2896  * called from api_spoolss_rffpcnex
2897  ********************************************************************/
2898
2899 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2900 {
2901         POLICY_HND *handle = &q_u->handle;
2902         uint32 flags = q_u->flags;
2903         uint32 options = q_u->options;
2904         UNISTR2 *localmachine = &q_u->localmachine;
2905         uint32 printerlocal = q_u->printerlocal;
2906         int snum = -1;
2907         SPOOL_NOTIFY_OPTION *option = q_u->option;
2908         struct sockaddr_storage client_ss;
2909
2910         /* store the notify value in the printer struct */
2911
2912         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2913
2914         if (!Printer) {
2915                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2916                 return WERR_BADFID;
2917         }
2918
2919         Printer->notify.flags=flags;
2920         Printer->notify.options=options;
2921         Printer->notify.printerlocal=printerlocal;
2922
2923         if (Printer->notify.option)
2924                 free_spool_notify_option(&Printer->notify.option);
2925
2926         Printer->notify.option=dup_spool_notify_option(option);
2927
2928         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2929                        sizeof(Printer->notify.localmachine));
2930
2931         /* Connect to the client machine and send a ReplyOpenPrinter */
2932
2933         if ( Printer->printer_type == SPLHND_SERVER)
2934                 snum = -1;
2935         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2936                         !get_printer_snum(p, handle, &snum, NULL) )
2937                 return WERR_BADFID;
2938
2939         if (!interpret_string_addr(&client_ss, p->client_address,
2940                                    AI_NUMERICHOST)) {
2941                 return WERR_SERVER_UNAVAILABLE;
2942         }
2943
2944         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2945                                         Printer->notify.printerlocal, 1,
2946                                         &Printer->notify.client_hnd, &client_ss))
2947                 return WERR_SERVER_UNAVAILABLE;
2948
2949         Printer->notify.client_connected=True;
2950
2951         return WERR_OK;
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the servername
2956  ********************************************************************/
2957
2958 void spoolss_notify_server_name(int snum,
2959                                        struct spoolss_Notify *data,
2960                                        print_queue_struct *queue,
2961                                        NT_PRINTER_INFO_LEVEL *printer,
2962                                        TALLOC_CTX *mem_ctx)
2963 {
2964         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2965 }
2966
2967 /*******************************************************************
2968  * fill a notify_info_data with the printername (not including the servername).
2969  ********************************************************************/
2970
2971 void spoolss_notify_printer_name(int snum,
2972                                         struct spoolss_Notify *data,
2973                                         print_queue_struct *queue,
2974                                         NT_PRINTER_INFO_LEVEL *printer,
2975                                         TALLOC_CTX *mem_ctx)
2976 {
2977         /* the notify name should not contain the \\server\ part */
2978         char *p = strrchr(printer->info_2->printername, '\\');
2979
2980         if (!p) {
2981                 p = printer->info_2->printername;
2982         } else {
2983                 p++;
2984         }
2985
2986         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the servicename
2991  ********************************************************************/
2992
2993 void spoolss_notify_share_name(int snum,
2994                                       struct spoolss_Notify *data,
2995                                       print_queue_struct *queue,
2996                                       NT_PRINTER_INFO_LEVEL *printer,
2997                                       TALLOC_CTX *mem_ctx)
2998 {
2999         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3000 }
3001
3002 /*******************************************************************
3003  * fill a notify_info_data with the port name
3004  ********************************************************************/
3005
3006 void spoolss_notify_port_name(int snum,
3007                                      struct spoolss_Notify *data,
3008                                      print_queue_struct *queue,
3009                                      NT_PRINTER_INFO_LEVEL *printer,
3010                                      TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the printername
3017  * but it doesn't exist, have to see what to do
3018  ********************************************************************/
3019
3020 void spoolss_notify_driver_name(int snum,
3021                                        struct spoolss_Notify *data,
3022                                        print_queue_struct *queue,
3023                                        NT_PRINTER_INFO_LEVEL *printer,
3024                                        TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the comment
3031  ********************************************************************/
3032
3033 void spoolss_notify_comment(int snum,
3034                                    struct spoolss_Notify *data,
3035                                    print_queue_struct *queue,
3036                                    NT_PRINTER_INFO_LEVEL *printer,
3037                                    TALLOC_CTX *mem_ctx)
3038 {
3039         char *p;
3040
3041         if (*printer->info_2->comment == '\0') {
3042                 p = lp_comment(snum);
3043         } else {
3044                 p = printer->info_2->comment;
3045         }
3046
3047         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the comment
3052  * location = "Room 1, floor 2, building 3"
3053  ********************************************************************/
3054
3055 void spoolss_notify_location(int snum,
3056                                     struct spoolss_Notify *data,
3057                                     print_queue_struct *queue,
3058                                     NT_PRINTER_INFO_LEVEL *printer,
3059                                     TALLOC_CTX *mem_ctx)
3060 {
3061         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3062 }
3063
3064 /*******************************************************************
3065  * fill a notify_info_data with the device mode
3066  * jfm:xxxx don't to it for know but that's a real problem !!!
3067  ********************************************************************/
3068
3069 static void spoolss_notify_devmode(int snum,
3070                                    struct spoolss_Notify *data,
3071                                    print_queue_struct *queue,
3072                                    NT_PRINTER_INFO_LEVEL *printer,
3073                                    TALLOC_CTX *mem_ctx)
3074 {
3075         /* for a dummy implementation we have to zero the fields */
3076         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with the separator file name
3081  ********************************************************************/
3082
3083 void spoolss_notify_sepfile(int snum,
3084                                    struct spoolss_Notify *data,
3085                                    print_queue_struct *queue,
3086                                    NT_PRINTER_INFO_LEVEL *printer,
3087                                    TALLOC_CTX *mem_ctx)
3088 {
3089         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3090 }
3091
3092 /*******************************************************************
3093  * fill a notify_info_data with the print processor
3094  * jfm:xxxx return always winprint to indicate we don't do anything to it
3095  ********************************************************************/
3096
3097 void spoolss_notify_print_processor(int snum,
3098                                            struct spoolss_Notify *data,
3099                                            print_queue_struct *queue,
3100                                            NT_PRINTER_INFO_LEVEL *printer,
3101                                            TALLOC_CTX *mem_ctx)
3102 {
3103         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3104 }
3105
3106 /*******************************************************************
3107  * fill a notify_info_data with the print processor options
3108  * jfm:xxxx send an empty string
3109  ********************************************************************/
3110
3111 void spoolss_notify_parameters(int snum,
3112                                       struct spoolss_Notify *data,
3113                                       print_queue_struct *queue,
3114                                       NT_PRINTER_INFO_LEVEL *printer,
3115                                       TALLOC_CTX *mem_ctx)
3116 {
3117         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3118 }
3119
3120 /*******************************************************************
3121  * fill a notify_info_data with the data type
3122  * jfm:xxxx always send RAW as data type
3123  ********************************************************************/
3124
3125 void spoolss_notify_datatype(int snum,
3126                                     struct spoolss_Notify *data,
3127                                     print_queue_struct *queue,
3128                                     NT_PRINTER_INFO_LEVEL *printer,
3129                                     TALLOC_CTX *mem_ctx)
3130 {
3131         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3132 }
3133
3134 /*******************************************************************
3135  * fill a notify_info_data with the security descriptor
3136  * jfm:xxxx send an null pointer to say no security desc
3137  * have to implement security before !
3138  ********************************************************************/
3139
3140 static void spoolss_notify_security_desc(int snum,
3141                                          struct spoolss_Notify *data,
3142                                          print_queue_struct *queue,
3143                                          NT_PRINTER_INFO_LEVEL *printer,
3144                                          TALLOC_CTX *mem_ctx)
3145 {
3146         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3147                                           printer->info_2->secdesc_buf->sd_size,
3148                                           printer->info_2->secdesc_buf->sd);
3149 }
3150
3151 /*******************************************************************
3152  * fill a notify_info_data with the attributes
3153  * jfm:xxxx a samba printer is always shared
3154  ********************************************************************/
3155
3156 void spoolss_notify_attributes(int snum,
3157                                       struct spoolss_Notify *data,
3158                                       print_queue_struct *queue,
3159                                       NT_PRINTER_INFO_LEVEL *printer,
3160                                       TALLOC_CTX *mem_ctx)
3161 {
3162         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3163 }
3164
3165 /*******************************************************************
3166  * fill a notify_info_data with the priority
3167  ********************************************************************/
3168
3169 static void spoolss_notify_priority(int snum,
3170                                     struct spoolss_Notify *data,
3171                                     print_queue_struct *queue,
3172                                     NT_PRINTER_INFO_LEVEL *printer,
3173                                     TALLOC_CTX *mem_ctx)
3174 {
3175         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3176 }
3177
3178 /*******************************************************************
3179  * fill a notify_info_data with the default priority
3180  ********************************************************************/
3181
3182 static void spoolss_notify_default_priority(int snum,
3183                                             struct spoolss_Notify *data,
3184                                             print_queue_struct *queue,
3185                                             NT_PRINTER_INFO_LEVEL *printer,
3186                                             TALLOC_CTX *mem_ctx)
3187 {
3188         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3189 }
3190
3191 /*******************************************************************
3192  * fill a notify_info_data with the start time
3193  ********************************************************************/
3194
3195 static void spoolss_notify_start_time(int snum,
3196                                       struct spoolss_Notify *data,
3197                                       print_queue_struct *queue,
3198                                       NT_PRINTER_INFO_LEVEL *printer,
3199                                       TALLOC_CTX *mem_ctx)
3200 {
3201         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3202 }
3203
3204 /*******************************************************************
3205  * fill a notify_info_data with the until time
3206  ********************************************************************/
3207
3208 static void spoolss_notify_until_time(int snum,
3209                                       struct spoolss_Notify *data,
3210                                       print_queue_struct *queue,
3211                                       NT_PRINTER_INFO_LEVEL *printer,
3212                                       TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3215 }
3216
3217 /*******************************************************************
3218  * fill a notify_info_data with the status
3219  ********************************************************************/
3220
3221 static void spoolss_notify_status(int snum,
3222                                   struct spoolss_Notify *data,
3223                                   print_queue_struct *queue,
3224                                   NT_PRINTER_INFO_LEVEL *printer,
3225                                   TALLOC_CTX *mem_ctx)
3226 {
3227         print_status_struct status;
3228
3229         print_queue_length(snum, &status);
3230         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3231 }
3232
3233 /*******************************************************************
3234  * fill a notify_info_data with the number of jobs queued
3235  ********************************************************************/
3236
3237 void spoolss_notify_cjobs(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3244 }
3245
3246 /*******************************************************************
3247  * fill a notify_info_data with the average ppm
3248  ********************************************************************/
3249
3250 static void spoolss_notify_average_ppm(int snum,
3251                                        struct spoolss_Notify *data,
3252                                        print_queue_struct *queue,
3253                                        NT_PRINTER_INFO_LEVEL *printer,
3254                                        TALLOC_CTX *mem_ctx)
3255 {
3256         /* always respond 8 pages per minutes */
3257         /* a little hard ! */
3258         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3259 }
3260
3261 /*******************************************************************
3262  * fill a notify_info_data with username
3263  ********************************************************************/
3264
3265 static void spoolss_notify_username(int snum,
3266                                     struct spoolss_Notify *data,
3267                                     print_queue_struct *queue,
3268                                     NT_PRINTER_INFO_LEVEL *printer,
3269                                     TALLOC_CTX *mem_ctx)
3270 {
3271         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3272 }
3273
3274 /*******************************************************************
3275  * fill a notify_info_data with job status
3276  ********************************************************************/
3277
3278 static void spoolss_notify_job_status(int snum,
3279                                       struct spoolss_Notify *data,
3280                                       print_queue_struct *queue,
3281                                       NT_PRINTER_INFO_LEVEL *printer,
3282                                       TALLOC_CTX *mem_ctx)
3283 {
3284         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3285 }
3286
3287 /*******************************************************************
3288  * fill a notify_info_data with job name
3289  ********************************************************************/
3290
3291 static void spoolss_notify_job_name(int snum,
3292                                     struct spoolss_Notify *data,
3293                                     print_queue_struct *queue,
3294                                     NT_PRINTER_INFO_LEVEL *printer,
3295                                     TALLOC_CTX *mem_ctx)
3296 {
3297         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3298 }
3299
3300 /*******************************************************************
3301  * fill a notify_info_data with job status
3302  ********************************************************************/
3303
3304 static void spoolss_notify_job_status_string(int snum,
3305                                              struct spoolss_Notify *data,
3306                                              print_queue_struct *queue,
3307                                              NT_PRINTER_INFO_LEVEL *printer,
3308                                              TALLOC_CTX *mem_ctx)
3309 {
3310         /*
3311          * Now we're returning job status codes we just return a "" here. JRA.
3312          */
3313
3314         const char *p = "";
3315
3316 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3317         p = "unknown";
3318
3319         switch (queue->status) {
3320         case LPQ_QUEUED:
3321                 p = "Queued";
3322                 break;
3323         case LPQ_PAUSED:
3324                 p = "";    /* NT provides the paused string */
3325                 break;
3326         case LPQ_SPOOLING:
3327                 p = "Spooling";
3328                 break;
3329         case LPQ_PRINTING:
3330                 p = "Printing";
3331                 break;
3332         }
3333 #endif /* NO LONGER NEEDED. */
3334
3335         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3336 }
3337
3338 /*******************************************************************
3339  * fill a notify_info_data with job time
3340  ********************************************************************/
3341
3342 static void spoolss_notify_job_time(int snum,
3343                                     struct spoolss_Notify *data,
3344                                     print_queue_struct *queue,
3345                                     NT_PRINTER_INFO_LEVEL *printer,
3346                                     TALLOC_CTX *mem_ctx)
3347 {
3348         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3349 }
3350
3351 /*******************************************************************
3352  * fill a notify_info_data with job size
3353  ********************************************************************/
3354
3355 static void spoolss_notify_job_size(int snum,
3356                                     struct spoolss_Notify *data,
3357                                     print_queue_struct *queue,
3358                                     NT_PRINTER_INFO_LEVEL *printer,
3359                                     TALLOC_CTX *mem_ctx)
3360 {
3361         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3362 }
3363
3364 /*******************************************************************
3365  * fill a notify_info_data with page info
3366  ********************************************************************/
3367 static void spoolss_notify_total_pages(int snum,
3368                                 struct spoolss_Notify *data,
3369                                 print_queue_struct *queue,
3370                                 NT_PRINTER_INFO_LEVEL *printer,
3371                                 TALLOC_CTX *mem_ctx)
3372 {
3373         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3374 }
3375
3376 /*******************************************************************
3377  * fill a notify_info_data with pages printed info.
3378  ********************************************************************/
3379 static void spoolss_notify_pages_printed(int snum,
3380                                 struct spoolss_Notify *data,
3381                                 print_queue_struct *queue,
3382                                 NT_PRINTER_INFO_LEVEL *printer,
3383                                 TALLOC_CTX *mem_ctx)
3384 {
3385         /* Add code when back-end tracks this */
3386         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3387 }
3388
3389 /*******************************************************************
3390  Fill a notify_info_data with job position.
3391  ********************************************************************/
3392
3393 static void spoolss_notify_job_position(int snum,
3394                                         struct spoolss_Notify *data,
3395                                         print_queue_struct *queue,
3396                                         NT_PRINTER_INFO_LEVEL *printer,
3397                                         TALLOC_CTX *mem_ctx)
3398 {
3399         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3400 }
3401
3402 /*******************************************************************
3403  Fill a notify_info_data with submitted time.
3404  ********************************************************************/
3405
3406 static void spoolss_notify_submitted_time(int snum,
3407                                           struct spoolss_Notify *data,
3408                                           print_queue_struct *queue,
3409                                           NT_PRINTER_INFO_LEVEL *printer,
3410                                           TALLOC_CTX *mem_ctx)
3411 {
3412         data->data.string.string = NULL;
3413         data->data.string.size = 0;
3414
3415         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3416                                &data->data.string.string,
3417                                &data->data.string.size);
3418
3419 }
3420
3421 struct s_notify_info_data_table
3422 {
3423         enum spoolss_NotifyType type;
3424         enum spoolss_Field field;
3425         const char *name;
3426         enum spoolss_NotifyTable variable_type;
3427         void (*fn) (int snum, struct spoolss_Notify *data,
3428                     print_queue_struct *queue,
3429                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3430 };
3431
3432 /* A table describing the various print notification constants and
3433    whether the notification data is a pointer to a variable sized
3434    buffer, a one value uint32 or a two value uint32. */
3435
3436 static const struct s_notify_info_data_table notify_info_data_table[] =
3437 {
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3464 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3465 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3466 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3467 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3468 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3469 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3470 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3471 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3472 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3473 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3474 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3475 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3487 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3488 };
3489
3490 /*******************************************************************
3491  Return the variable_type of info_data structure.
3492 ********************************************************************/
3493
3494 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3495                                                   enum spoolss_Field field)
3496 {
3497         int i=0;
3498
3499         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3500                 if ( (notify_info_data_table[i].type == type) &&
3501                      (notify_info_data_table[i].field == field) ) {
3502                         return notify_info_data_table[i].variable_type;
3503                 }
3504         }
3505
3506         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3507
3508         return 0;
3509 }
3510
3511 /****************************************************************************
3512 ****************************************************************************/
3513
3514 static bool search_notify(uint16 type, uint16 field, int *value)
3515 {
3516         int i;
3517
3518         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3519                 if (notify_info_data_table[i].type == type &&
3520                     notify_info_data_table[i].field == field &&
3521                     notify_info_data_table[i].fn != NULL) {
3522                         *value = i;
3523                         return True;
3524                 }
3525         }
3526
3527         return False;
3528 }
3529
3530 /****************************************************************************
3531 ****************************************************************************/
3532
3533 void construct_info_data(struct spoolss_Notify *info_data, uint16 type, uint16 field, int id)
3534 {
3535         info_data->type                 = type;
3536         info_data->field                = field;
3537         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3538         info_data->job_id               = id;
3539 }
3540
3541 /*******************************************************************
3542  *
3543  * fill a notify_info struct with info asked
3544  *
3545  ********************************************************************/
3546
3547 static bool construct_notify_printer_info(Printer_entry *print_hnd, struct spoolss_NotifyInfo *info, int
3548                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3549                                           *option_type, uint32 id,
3550                                           TALLOC_CTX *mem_ctx)
3551 {
3552         int field_num,j;
3553         uint16 type;
3554         uint16 field;
3555
3556         struct spoolss_Notify *current_data;
3557         NT_PRINTER_INFO_LEVEL *printer = NULL;
3558         print_queue_struct *queue=NULL;
3559
3560         type=option_type->type;
3561
3562         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3563                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3564                 option_type->count, lp_servicename(snum)));
3565
3566         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3567                 return False;
3568
3569         for(field_num=0; field_num<option_type->count; field_num++) {
3570                 field = option_type->fields[field_num];
3571
3572                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3573
3574                 if (!search_notify(type, field, &j) )
3575                         continue;
3576
3577                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3578                                                       struct spoolss_Notify,
3579                                                       info->count + 1);
3580                 if (info->notifies == NULL) {
3581                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3582                         free_a_printer(&printer, 2);
3583                         return False;
3584                 }
3585
3586                 current_data = &info->notifies[info->count];
3587
3588                 construct_info_data(current_data, type, field, id);
3589
3590                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3591                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3592
3593                 notify_info_data_table[j].fn(snum, current_data, queue,
3594                                              printer, mem_ctx);
3595
3596                 info->count++;
3597         }
3598
3599         free_a_printer(&printer, 2);
3600         return True;
3601 }
3602
3603 /*******************************************************************
3604  *
3605  * fill a notify_info struct with info asked
3606  *
3607  ********************************************************************/
3608
3609 static bool construct_notify_jobs_info(print_queue_struct *queue,
3610                                        struct spoolss_NotifyInfo *info,
3611                                        NT_PRINTER_INFO_LEVEL *printer,
3612                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3613                                        *option_type, uint32 id,
3614                                        TALLOC_CTX *mem_ctx)
3615 {
3616         int field_num,j;
3617         uint16 type;
3618         uint16 field;
3619
3620         struct spoolss_Notify *current_data;
3621
3622         DEBUG(4,("construct_notify_jobs_info\n"));
3623
3624         type = option_type->type;
3625
3626         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3627                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3628                 option_type->count));
3629
3630         for(field_num=0; field_num<option_type->count; field_num++) {
3631                 field = option_type->fields[field_num];
3632
3633                 if (!search_notify(type, field, &j) )
3634                         continue;
3635
3636                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3637                                                       struct spoolss_Notify,
3638                                                       info->count + 1);
3639                 if (info->notifies == NULL) {
3640                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3641                         return False;
3642                 }
3643
3644                 current_data=&(info->notifies[info->count]);
3645
3646                 construct_info_data(current_data, type, field, id);
3647                 notify_info_data_table[j].fn(snum, current_data, queue,
3648                                              printer, mem_ctx);
3649                 info->count++;
3650         }
3651
3652         return True;
3653 }
3654
3655 /*
3656  * JFM: The enumeration is not that simple, it's even non obvious.
3657  *
3658  * let's take an example: I want to monitor the PRINTER SERVER for
3659  * the printer's name and the number of jobs currently queued.
3660  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3661  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3662  *
3663  * I have 3 printers on the back of my server.
3664  *
3665  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3666  * structures.
3667  *   Number     Data                    Id
3668  *      1       printer 1 name          1
3669  *      2       printer 1 cjob          1
3670  *      3       printer 2 name          2
3671  *      4       printer 2 cjob          2
3672  *      5       printer 3 name          3
3673  *      6       printer 3 name          3
3674  *
3675  * that's the print server case, the printer case is even worse.
3676  */
3677
3678 /*******************************************************************
3679  *
3680  * enumerate all printers on the printserver
3681  * fill a notify_info struct with info asked
3682  *
3683  ********************************************************************/
3684
3685 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3686                                       struct spoolss_NotifyInfo *info,
3687                                       TALLOC_CTX *mem_ctx)
3688 {
3689         int snum;
3690         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3691         int n_services=lp_numservices();
3692         int i;
3693         SPOOL_NOTIFY_OPTION *option;
3694         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3695
3696         DEBUG(4,("printserver_notify_info\n"));
3697
3698         if (!Printer)
3699                 return WERR_BADFID;
3700
3701         option=Printer->notify.option;
3702
3703         info->version   = 2;
3704         info->notifies  = NULL;
3705         info->count     = 0;
3706
3707         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3708            sending a ffpcn() request first */
3709
3710         if ( !option )
3711                 return WERR_BADFID;
3712
3713         for (i=0; i<option->count; i++) {
3714                 option_type=&(option->ctr.type[i]);
3715
3716                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3717                         continue;
3718
3719                 for (snum=0; snum<n_services; snum++)
3720                 {
3721                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3722                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3723                 }
3724         }
3725
3726 #if 0
3727         /*
3728          * Debugging information, don't delete.
3729          */
3730
3731         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3732         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3733         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3734
3735         for (i=0; i<info->count; i++) {
3736                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3737                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3738                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3739         }
3740 #endif
3741
3742         return WERR_OK;
3743 }
3744
3745 /*******************************************************************
3746  *
3747  * fill a notify_info struct with info asked
3748  *
3749  ********************************************************************/
3750
3751 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3752                                   TALLOC_CTX *mem_ctx)
3753 {
3754         int snum;
3755         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3756         int i;
3757         uint32 id;
3758         SPOOL_NOTIFY_OPTION *option;
3759         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3760         int count,j;
3761         print_queue_struct *queue=NULL;
3762         print_status_struct status;
3763
3764         DEBUG(4,("printer_notify_info\n"));
3765
3766         if (!Printer)
3767                 return WERR_BADFID;
3768
3769         option=Printer->notify.option;
3770         id = 0x0;
3771
3772         info->version   = 2;
3773         info->notifies  = NULL;
3774         info->count     = 0;
3775
3776         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3777            sending a ffpcn() request first */
3778
3779         if ( !option )
3780                 return WERR_BADFID;
3781
3782         get_printer_snum(p, hnd, &snum, NULL);
3783
3784         for (i=0; i<option->count; i++) {
3785                 option_type=&option->ctr.type[i];
3786
3787                 switch ( option_type->type ) {
3788                 case PRINTER_NOTIFY_TYPE:
3789                         if(construct_notify_printer_info(Printer, info, snum,
3790                                                          option_type, id,
3791                                                          mem_ctx))
3792                                 id--;
3793                         break;
3794
3795                 case JOB_NOTIFY_TYPE: {
3796                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3797
3798                         count = print_queue_status(snum, &queue, &status);
3799
3800                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3801                                 goto done;
3802
3803                         for (j=0; j<count; j++) {
3804                                 construct_notify_jobs_info(&queue[j], info,
3805                                                            printer, snum,
3806                                                            option_type,
3807                                                            queue[j].job,
3808                                                            mem_ctx);
3809                         }
3810
3811                         free_a_printer(&printer, 2);
3812
3813                 done:
3814                         SAFE_FREE(queue);
3815                         break;
3816                 }
3817                 }
3818         }
3819
3820         /*
3821          * Debugging information, don't delete.
3822          */
3823         /*
3824         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3825         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3826         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3827
3828         for (i=0; i<info->count; i++) {
3829                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3830                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3831                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3832         }
3833         */
3834         return WERR_OK;
3835 }
3836
3837 /****************************************************************
3838  _spoolss_RouterRefreshPrinterChangeNotify
3839 ****************************************************************/
3840
3841 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3842                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3843 {
3844         POLICY_HND *handle = r->in.handle;
3845         struct spoolss_NotifyInfo *info;
3846
3847         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3848         WERROR result = WERR_BADFID;
3849
3850         /* we always have a spoolss_NotifyInfo struct */
3851         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3852         if (!info) {
3853                 result = WERR_NOMEM;
3854                 goto done;
3855         }
3856
3857         *r->out.info = info;
3858
3859         if (!Printer) {
3860                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3861                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3862                 goto done;
3863         }
3864
3865         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3866
3867         /*
3868          *      We are now using the change value, and
3869          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3870          *      I don't have a global notification system, I'm sending back all the
3871          *      informations even when _NOTHING_ has changed.
3872          */
3873
3874         /* We need to keep track of the change value to send back in
3875            RRPCN replies otherwise our updates are ignored. */
3876
3877         Printer->notify.fnpcn = True;
3878
3879         if (Printer->notify.client_connected) {
3880                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3881                         "Saving change value in request [%x]\n",
3882                         r->in.change_low));
3883                 Printer->notify.change = r->in.change_low;
3884         }
3885
3886         /* just ignore the SPOOL_NOTIFY_OPTION */
3887
3888         switch (Printer->printer_type) {
3889                 case SPLHND_SERVER:
3890                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3891                         break;
3892
3893                 case SPLHND_PRINTER:
3894                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3895                         break;
3896         }
3897
3898         Printer->notify.fnpcn = False;
3899
3900 done:
3901         return result;
3902 }
3903
3904 /********************************************************************
3905  * construct_printer_info_0
3906  * fill a printer_info_0 struct
3907  ********************************************************************/
3908
3909 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3910 {
3911         char *chaine = NULL;
3912         int count;
3913         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3914         counter_printer_0 *session_counter;
3915         uint32 global_counter;
3916         struct tm *t;
3917         time_t setuptime;
3918         print_status_struct status;
3919         TALLOC_CTX *ctx = talloc_tos();
3920
3921         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3922                 return False;
3923
3924         init_unistr(&printer->printername, ntprinter->info_2->printername);
3925
3926         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3927         if (!chaine) {
3928                 free_a_printer(&ntprinter,2);
3929                 return false;
3930         }
3931
3932         count = print_queue_length(snum, &status);
3933
3934         /* check if we already have a counter for this printer */
3935         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3936                 if (session_counter->snum == snum)
3937                         break;
3938         }
3939
3940         init_unistr(&printer->servername, chaine);
3941
3942         /* it's the first time, add it to the list */
3943         if (session_counter==NULL) {
3944                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3945                         free_a_printer(&ntprinter, 2);
3946                         return False;
3947                 }
3948                 ZERO_STRUCTP(session_counter);
3949                 session_counter->snum=snum;
3950                 session_counter->counter=0;
3951                 DLIST_ADD(counter_list, session_counter);
3952         }
3953
3954         /* increment it */
3955         session_counter->counter++;
3956
3957         /* JFM:
3958          * the global_counter should be stored in a TDB as it's common to all the clients
3959          * and should be zeroed on samba startup
3960          */
3961         global_counter=session_counter->counter;
3962         printer->cjobs = count;
3963         printer->total_jobs = 0;
3964         printer->total_bytes = 0;
3965
3966         setuptime = (time_t)ntprinter->info_2->setuptime;
3967         t=gmtime(&setuptime);
3968
3969         printer->year = t->tm_year+1900;
3970         printer->month = t->tm_mon+1;
3971         printer->dayofweek = t->tm_wday;
3972         printer->day = t->tm_mday;
3973         printer->hour = t->tm_hour;
3974         printer->minute = t->tm_min;
3975         printer->second = t->tm_sec;
3976         printer->milliseconds = 0;
3977
3978         printer->global_counter = global_counter;
3979         printer->total_pages = 0;
3980
3981         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3982         printer->major_version = 0x0005;        /* NT 5 */
3983         printer->build_version = 0x0893;        /* build 2195 */
3984
3985         printer->unknown7 = 0x1;
3986         printer->unknown8 = 0x0;
3987         printer->unknown9 = 0x0;
3988         printer->session_counter = session_counter->counter;
3989         printer->unknown11 = 0x0;
3990         printer->printer_errors = 0x0;          /* number of print failure */
3991         printer->unknown13 = 0x0;
3992         printer->unknown14 = 0x1;
3993         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3994         printer->unknown16 =  0x0;
3995         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3996         printer->unknown18 =  0x0;
3997         printer->status = nt_printq_status(status.status);
3998         printer->unknown20 =  0x0;
3999         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4000         printer->unknown22 = 0x0;
4001         printer->unknown23 = 0x6;               /* 6  ???*/
4002         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4003         printer->unknown25 = 0;
4004         printer->unknown26 = 0;
4005         printer->unknown27 = 0;
4006         printer->unknown28 = 0;
4007         printer->unknown29 = 0;
4008
4009         free_a_printer(&ntprinter,2);
4010         return (True);
4011 }
4012
4013 /********************************************************************
4014  * construct_printer_info_1
4015  * fill a printer_info_1 struct
4016  ********************************************************************/
4017 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4018 {
4019         char *chaine = NULL;
4020         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4021         TALLOC_CTX *ctx = talloc_tos();
4022
4023         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4024                 return false;
4025
4026         printer->flags=flags;
4027
4028         if (*ntprinter->info_2->comment == '\0') {
4029                 init_unistr(&printer->comment, lp_comment(snum));
4030                 chaine = talloc_asprintf(ctx,
4031                                 "%s,%s,%s", ntprinter->info_2->printername,
4032                                 ntprinter->info_2->drivername, lp_comment(snum));
4033         }
4034         else {
4035                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4036                 chaine = talloc_asprintf(ctx,
4037                                 "%s,%s,%s", ntprinter->info_2->printername,
4038                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4039         }
4040
4041         if (!chaine) {
4042                 free_a_printer(&ntprinter,2);
4043                 return false;
4044         }
4045
4046         init_unistr(&printer->description, chaine);
4047         init_unistr(&printer->name, ntprinter->info_2->printername);
4048
4049         free_a_printer(&ntprinter,2);
4050
4051         return True;
4052 }
4053
4054 /****************************************************************************
4055  Free a DEVMODE struct.
4056 ****************************************************************************/
4057
4058 static void free_dev_mode(DEVICEMODE *dev)
4059 {
4060         if (dev == NULL)
4061                 return;
4062
4063         SAFE_FREE(dev->dev_private);
4064         SAFE_FREE(dev);
4065 }
4066
4067
4068 /****************************************************************************
4069  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4070  should be valid upon entry
4071 ****************************************************************************/
4072
4073 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4074 {
4075         if ( !devmode || !ntdevmode )
4076                 return False;
4077
4078         init_unistr(&devmode->devicename, ntdevmode->devicename);
4079
4080         init_unistr(&devmode->formname, ntdevmode->formname);
4081
4082         devmode->specversion      = ntdevmode->specversion;
4083         devmode->driverversion    = ntdevmode->driverversion;
4084         devmode->size             = ntdevmode->size;
4085         devmode->driverextra      = ntdevmode->driverextra;
4086         devmode->fields           = ntdevmode->fields;
4087
4088         devmode->orientation      = ntdevmode->orientation;
4089         devmode->papersize        = ntdevmode->papersize;
4090         devmode->paperlength      = ntdevmode->paperlength;
4091         devmode->paperwidth       = ntdevmode->paperwidth;
4092         devmode->scale            = ntdevmode->scale;
4093         devmode->copies           = ntdevmode->copies;
4094         devmode->defaultsource    = ntdevmode->defaultsource;
4095         devmode->printquality     = ntdevmode->printquality;
4096         devmode->color            = ntdevmode->color;
4097         devmode->duplex           = ntdevmode->duplex;
4098         devmode->yresolution      = ntdevmode->yresolution;
4099         devmode->ttoption         = ntdevmode->ttoption;
4100         devmode->collate          = ntdevmode->collate;
4101         devmode->icmmethod        = ntdevmode->icmmethod;
4102         devmode->icmintent        = ntdevmode->icmintent;
4103         devmode->mediatype        = ntdevmode->mediatype;
4104         devmode->dithertype       = ntdevmode->dithertype;
4105
4106         if (ntdevmode->nt_dev_private != NULL) {
4107                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4108                         return False;
4109         }
4110
4111         return True;
4112 }
4113
4114 /****************************************************************************
4115  Create a DEVMODE struct. Returns malloced memory.
4116 ****************************************************************************/
4117
4118 DEVICEMODE *construct_dev_mode(const char *servicename)
4119 {
4120         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4121         DEVICEMODE              *devmode = NULL;
4122
4123         DEBUG(7,("construct_dev_mode\n"));
4124
4125         DEBUGADD(8,("getting printer characteristics\n"));
4126
4127         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4128                 return NULL;
4129
4130         if ( !printer->info_2->devmode ) {
4131                 DEBUG(5, ("BONG! There was no device mode!\n"));
4132                 goto done;
4133         }
4134
4135         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4136                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4137                 goto done;
4138         }
4139
4140         ZERO_STRUCTP(devmode);
4141
4142         DEBUGADD(8,("loading DEVICEMODE\n"));
4143
4144         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4145                 free_dev_mode( devmode );
4146                 devmode = NULL;
4147         }
4148
4149 done:
4150         free_a_printer(&printer,2);
4151
4152         return devmode;
4153 }
4154
4155 /********************************************************************
4156  * construct_printer_info_2
4157  * fill a printer_info_2 struct
4158  ********************************************************************/
4159
4160 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4161 {
4162         int count;
4163         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4164
4165         print_status_struct status;
4166
4167         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4168                 return False;
4169
4170         count = print_queue_length(snum, &status);
4171
4172         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4173         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4174         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4175         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4176         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4177
4178         if (*ntprinter->info_2->comment == '\0')
4179                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4180         else
4181                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4182
4183         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4184         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4185         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4186         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4187         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4188
4189         printer->attributes = ntprinter->info_2->attributes;
4190
4191         printer->priority = ntprinter->info_2->priority;                                /* priority */
4192         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4193         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4194         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4195         printer->status = nt_printq_status(status.status);                      /* status */
4196         printer->cjobs = count;                                                 /* jobs */
4197         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4198
4199         if ( !(printer->devmode = construct_dev_mode(
4200                        lp_const_servicename(snum))) )
4201                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4202
4203         printer->secdesc = NULL;
4204
4205         if ( ntprinter->info_2->secdesc_buf
4206                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4207         {
4208                 /* don't use talloc_steal() here unless you do a deep steal of all
4209                    the SEC_DESC members */
4210
4211                 printer->secdesc = dup_sec_desc( talloc_tos(),
4212                         ntprinter->info_2->secdesc_buf->sd );
4213         }
4214
4215         free_a_printer(&ntprinter, 2);
4216
4217         return True;
4218 }
4219
4220 /********************************************************************
4221  * construct_printer_info_3
4222  * fill a printer_info_3 struct
4223  ********************************************************************/
4224
4225 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4226 {
4227         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4228         PRINTER_INFO_3 *printer = NULL;
4229
4230         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4231                 return False;
4232
4233         *pp_printer = NULL;
4234         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4235                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4236                 free_a_printer(&ntprinter, 2);
4237                 return False;
4238         }
4239
4240         ZERO_STRUCTP(printer);
4241
4242         /* These are the components of the SD we are returning. */
4243
4244         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4245                 /* don't use talloc_steal() here unless you do a deep steal of all
4246                    the SEC_DESC members */
4247
4248                 printer->secdesc = dup_sec_desc( talloc_tos(),
4249                         ntprinter->info_2->secdesc_buf->sd );
4250         }
4251
4252         free_a_printer(&ntprinter, 2);
4253
4254         *pp_printer = printer;
4255         return True;
4256 }
4257
4258 /********************************************************************
4259  * construct_printer_info_4
4260  * fill a printer_info_4 struct
4261  ********************************************************************/
4262
4263 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4264 {
4265         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4266
4267         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4268                 return False;
4269
4270         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4271         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4272         printer->attributes = ntprinter->info_2->attributes;
4273
4274         free_a_printer(&ntprinter, 2);
4275         return True;
4276 }
4277
4278 /********************************************************************
4279  * construct_printer_info_5
4280  * fill a printer_info_5 struct
4281  ********************************************************************/
4282
4283 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4284 {
4285         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4286
4287         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4288                 return False;
4289
4290         init_unistr(&printer->printername, ntprinter->info_2->printername);
4291         init_unistr(&printer->portname, ntprinter->info_2->portname);
4292         printer->attributes = ntprinter->info_2->attributes;
4293
4294         /* these two are not used by NT+ according to MSDN */
4295
4296         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4297         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4298
4299         free_a_printer(&ntprinter, 2);
4300
4301         return True;
4302 }
4303
4304 /********************************************************************
4305  * construct_printer_info_6
4306  * fill a printer_info_6 struct
4307  ********************************************************************/
4308
4309 static bool construct_printer_info_6(Printer_entry *print_hnd,
4310                                      PRINTER_INFO_6 *printer,
4311                                      int snum)
4312 {
4313         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4314         int count;
4315         print_status_struct status;
4316
4317         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4318                                          lp_const_servicename(snum))))
4319                 return False;
4320
4321         count = print_queue_length(snum, &status);
4322
4323         printer->status = nt_printq_status(status.status);
4324
4325         free_a_printer(&ntprinter, 2);
4326
4327         return True;
4328 }
4329
4330 /********************************************************************
4331  * construct_printer_info_7
4332  * fill a printer_info_7 struct
4333  ********************************************************************/
4334
4335 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4336 {
4337         char *guid_str = NULL;
4338         struct GUID guid;
4339
4340         if (is_printer_published(print_hnd, snum, &guid)) {
4341                 if (asprintf(&guid_str, "{%s}",
4342                              GUID_string(talloc_tos(), &guid)) == -1) {
4343                         return false;
4344                 }
4345                 strupper_m(guid_str);
4346                 init_unistr(&printer->guid, guid_str);
4347                 SAFE_FREE(guid_str);
4348                 printer->action = SPOOL_DS_PUBLISH;
4349         } else {
4350                 init_unistr(&printer->guid, "");
4351                 printer->action = SPOOL_DS_UNPUBLISH;
4352         }
4353
4354         return True;
4355 }
4356
4357 /********************************************************************
4358  Spoolss_enumprinters.
4359 ********************************************************************/
4360
4361 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4362 {
4363         int snum;
4364         int i;
4365         int n_services=lp_numservices();
4366         PRINTER_INFO_1 *printers=NULL;
4367         PRINTER_INFO_1 current_prt;
4368         WERROR result = WERR_OK;
4369
4370         DEBUG(4,("enum_all_printers_info_1\n"));
4371
4372         for (snum=0; snum<n_services; snum++) {
4373                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4374                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4375
4376                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4377                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4378                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4379                                         *returned=0;
4380                                         return WERR_NOMEM;
4381                                 }
4382                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4383
4384                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4385                                 (*returned)++;
4386                         }
4387                 }
4388         }
4389
4390         /* check the required size. */
4391         for (i=0; i<*returned; i++)
4392                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4393
4394         if (*needed > offered) {
4395                 result = WERR_INSUFFICIENT_BUFFER;
4396                 goto out;
4397         }
4398
4399         if (!rpcbuf_alloc_size(buffer, *needed)) {
4400                 result = WERR_NOMEM;
4401                 goto out;
4402         }
4403
4404         /* fill the buffer with the structures */
4405         for (i=0; i<*returned; i++)
4406                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4407
4408 out:
4409         /* clear memory */
4410
4411         SAFE_FREE(printers);
4412
4413         if ( !W_ERROR_IS_OK(result) )
4414                 *returned = 0;
4415
4416         return result;
4417 }
4418
4419 /********************************************************************
4420  enum_all_printers_info_1_local.
4421 *********************************************************************/
4422
4423 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4424 {
4425         DEBUG(4,("enum_all_printers_info_1_local\n"));
4426
4427         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4428 }
4429
4430 /********************************************************************
4431  enum_all_printers_info_1_name.
4432 *********************************************************************/
4433
4434 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4435 {
4436         char *s = name;
4437
4438         DEBUG(4,("enum_all_printers_info_1_name\n"));
4439
4440         if ((name[0] == '\\') && (name[1] == '\\'))
4441                 s = name + 2;
4442
4443         if (is_myname_or_ipaddr(s)) {
4444                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4445         }
4446         else
4447                 return WERR_INVALID_NAME;
4448 }
4449
4450 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4451 /********************************************************************
4452  enum_all_printers_info_1_remote.
4453 *********************************************************************/
4454
4455 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4456 {
4457         PRINTER_INFO_1 *printer;
4458         fstring printername;
4459         fstring desc;
4460         fstring comment;
4461         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4462         WERROR result = WERR_OK;
4463
4464         /* JFM: currently it's more a place holder than anything else.
4465          * In the spooler world there is a notion of server registration.
4466          * the print servers are registered on the PDC (in the same domain)
4467          *
4468          * We should have a TDB here. The registration is done thru an
4469          * undocumented RPC call.
4470          */
4471
4472         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4473                 return WERR_NOMEM;
4474
4475         *returned=1;
4476
4477         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4478         slprintf(desc, sizeof(desc)-1,"%s", name);
4479         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4480
4481         init_unistr(&printer->description, desc);
4482         init_unistr(&printer->name, printername);
4483         init_unistr(&printer->comment, comment);
4484         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4485
4486         /* check the required size. */
4487         *needed += spoolss_size_printer_info_1(printer);
4488
4489         if (*needed > offered) {
4490                 result = WERR_INSUFFICIENT_BUFFER;
4491                 goto out;
4492         }
4493
4494         if (!rpcbuf_alloc_size(buffer, *needed)) {
4495                 result = WERR_NOMEM;
4496                 goto out;
4497         }
4498
4499         /* fill the buffer with the structures */
4500         smb_io_printer_info_1("", buffer, printer, 0);
4501
4502 out:
4503         /* clear memory */
4504         SAFE_FREE(printer);
4505
4506         if ( !W_ERROR_IS_OK(result) )
4507                 *returned = 0;
4508
4509         return result;
4510 }
4511
4512 #endif
4513
4514 /********************************************************************
4515  enum_all_printers_info_1_network.
4516 *********************************************************************/
4517
4518 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4519 {
4520         char *s = name;
4521
4522         DEBUG(4,("enum_all_printers_info_1_network\n"));
4523
4524         /* If we respond to a enum_printers level 1 on our name with flags
4525            set to PRINTER_ENUM_REMOTE with a list of printers then these
4526            printers incorrectly appear in the APW browse list.
4527            Specifically the printers for the server appear at the workgroup
4528            level where all the other servers in the domain are
4529            listed. Windows responds to this call with a
4530            WERR_CAN_NOT_COMPLETE so we should do the same. */
4531
4532         if (name[0] == '\\' && name[1] == '\\')
4533                  s = name + 2;
4534
4535         if (is_myname_or_ipaddr(s))
4536                  return WERR_CAN_NOT_COMPLETE;
4537
4538         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4539 }
4540
4541 /********************************************************************
4542  * api_spoolss_enumprinters
4543  *
4544  * called from api_spoolss_enumprinters (see this to understand)
4545  ********************************************************************/
4546
4547 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4548 {
4549         int snum;
4550         int i;
4551         int n_services=lp_numservices();
4552         PRINTER_INFO_2 *printers=NULL;
4553         PRINTER_INFO_2 current_prt;
4554         WERROR result = WERR_OK;
4555
4556         *returned = 0;
4557
4558         for (snum=0; snum<n_services; snum++) {
4559                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4560                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4561
4562                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4563                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4564                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4565                                         *returned = 0;
4566                                         return WERR_NOMEM;
4567                                 }
4568
4569                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4570
4571                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4572
4573                                 (*returned)++;
4574                         }
4575                 }
4576         }
4577
4578         /* check the required size. */
4579         for (i=0; i<*returned; i++)
4580                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4581
4582         if (*needed > offered) {
4583                 result = WERR_INSUFFICIENT_BUFFER;
4584                 goto out;
4585         }
4586
4587         if (!rpcbuf_alloc_size(buffer, *needed)) {
4588                 result = WERR_NOMEM;
4589                 goto out;
4590         }
4591
4592         /* fill the buffer with the structures */
4593         for (i=0; i<*returned; i++)
4594                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4595
4596 out:
4597         /* clear memory */
4598
4599         for (i=0; i<*returned; i++)
4600                 free_devmode(printers[i].devmode);
4601
4602         SAFE_FREE(printers);
4603
4604         if ( !W_ERROR_IS_OK(result) )
4605                 *returned = 0;
4606
4607         return result;
4608 }
4609
4610 /********************************************************************
4611  * handle enumeration of printers at level 1
4612  ********************************************************************/
4613
4614 static WERROR enumprinters_level1( uint32 flags, fstring name,
4615                                  RPC_BUFFER *buffer, uint32 offered,
4616                                  uint32 *needed, uint32 *returned)
4617 {
4618         /* Not all the flags are equals */
4619
4620         if (flags & PRINTER_ENUM_LOCAL)
4621                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4622
4623         if (flags & PRINTER_ENUM_NAME)
4624                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4625
4626 #if 0   /* JERRY - disabled for now */
4627         if (flags & PRINTER_ENUM_REMOTE)
4628                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4629 #endif
4630
4631         if (flags & PRINTER_ENUM_NETWORK)
4632                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4633
4634         return WERR_OK; /* NT4sp5 does that */
4635 }
4636
4637 /********************************************************************
4638  * handle enumeration of printers at level 2
4639  ********************************************************************/
4640
4641 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4642                                  RPC_BUFFER *buffer, uint32 offered,
4643                                  uint32 *needed, uint32 *returned)
4644 {
4645         if (flags & PRINTER_ENUM_LOCAL) {
4646                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4647         }
4648
4649         if (flags & PRINTER_ENUM_NAME) {
4650                 if (is_myname_or_ipaddr(canon_servername(servername)))
4651                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4652                 else
4653                         return WERR_INVALID_NAME;
4654         }
4655
4656         if (flags & PRINTER_ENUM_REMOTE)
4657                 return WERR_UNKNOWN_LEVEL;
4658
4659         return WERR_OK;
4660 }
4661
4662 /********************************************************************
4663  * handle enumeration of printers at level 5
4664  ********************************************************************/
4665
4666 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4667                                  RPC_BUFFER *buffer, uint32 offered,
4668                                  uint32 *needed, uint32 *returned)
4669 {
4670 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4671         return WERR_OK;
4672 }
4673
4674 /********************************************************************
4675  * api_spoolss_enumprinters
4676  *
4677  * called from api_spoolss_enumprinters (see this to understand)
4678  ********************************************************************/
4679
4680 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4681 {
4682         uint32 flags = q_u->flags;
4683         UNISTR2 *servername = &q_u->servername;
4684         uint32 level = q_u->level;
4685         RPC_BUFFER *buffer = NULL;
4686         uint32 offered = q_u->offered;
4687         uint32 *needed = &r_u->needed;
4688         uint32 *returned = &r_u->returned;
4689
4690         fstring name;
4691
4692         /* that's an [in out] buffer */
4693
4694         if (!q_u->buffer && (offered!=0)) {
4695                 return WERR_INVALID_PARAM;
4696         }
4697
4698         if (offered > MAX_RPC_DATA_SIZE) {
4699                 return WERR_INVALID_PARAM;
4700         }
4701
4702         rpcbuf_move(q_u->buffer, &r_u->buffer);
4703         buffer = r_u->buffer;
4704
4705         DEBUG(4,("_spoolss_enumprinters\n"));
4706
4707         *needed=0;
4708         *returned=0;
4709
4710         /*
4711          * Level 1:
4712          *          flags==PRINTER_ENUM_NAME
4713          *           if name=="" then enumerates all printers
4714          *           if name!="" then enumerate the printer
4715          *          flags==PRINTER_ENUM_REMOTE
4716          *          name is NULL, enumerate printers
4717          * Level 2: name!="" enumerates printers, name can't be NULL
4718          * Level 3: doesn't exist
4719          * Level 4: does a local registry lookup
4720          * Level 5: same as Level 2
4721          */
4722
4723         unistr2_to_ascii(name, servername, sizeof(name));
4724         strupper_m(name);
4725
4726         switch (level) {
4727         case 1:
4728                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4729         case 2:
4730                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4731         case 5:
4732                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4733         case 3:
4734         case 4:
4735                 break;
4736         }
4737         return WERR_UNKNOWN_LEVEL;
4738 }
4739
4740 /****************************************************************************
4741 ****************************************************************************/
4742
4743 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4744 {
4745         PRINTER_INFO_0 *printer=NULL;
4746         WERROR result = WERR_OK;
4747
4748         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4749                 return WERR_NOMEM;
4750
4751         construct_printer_info_0(print_hnd, printer, snum);
4752
4753         /* check the required size. */
4754         *needed += spoolss_size_printer_info_0(printer);
4755
4756         if (*needed > offered) {
4757                 result = WERR_INSUFFICIENT_BUFFER;
4758                 goto out;
4759         }
4760
4761         if (!rpcbuf_alloc_size(buffer, *needed)) {
4762                 result = WERR_NOMEM;
4763                 goto out;
4764         }
4765
4766         /* fill the buffer with the structures */
4767         smb_io_printer_info_0("", buffer, printer, 0);
4768
4769 out:
4770         /* clear memory */
4771
4772         SAFE_FREE(printer);
4773
4774         return result;
4775 }
4776
4777 /****************************************************************************
4778 ****************************************************************************/
4779
4780 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4781 {
4782         PRINTER_INFO_1 *printer=NULL;
4783         WERROR result = WERR_OK;
4784
4785         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4786                 return WERR_NOMEM;
4787
4788         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4789
4790         /* check the required size. */
4791         *needed += spoolss_size_printer_info_1(printer);
4792
4793         if (*needed > offered) {
4794                 result = WERR_INSUFFICIENT_BUFFER;
4795                 goto out;
4796         }
4797
4798         if (!rpcbuf_alloc_size(buffer, *needed)) {
4799                 result = WERR_NOMEM;
4800                 goto out;
4801         }
4802
4803         /* fill the buffer with the structures */
4804         smb_io_printer_info_1("", buffer, printer, 0);
4805
4806 out:
4807         /* clear memory */
4808         SAFE_FREE(printer);
4809
4810         return result;
4811 }
4812
4813 /****************************************************************************
4814 ****************************************************************************/
4815
4816 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4817 {
4818         PRINTER_INFO_2 *printer=NULL;
4819         WERROR result = WERR_OK;
4820
4821         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4822                 return WERR_NOMEM;
4823
4824         construct_printer_info_2(print_hnd, printer, snum);
4825
4826         /* check the required size. */
4827         *needed += spoolss_size_printer_info_2(printer);
4828
4829         if (*needed > offered) {
4830                 result = WERR_INSUFFICIENT_BUFFER;
4831                 goto out;
4832         }
4833
4834         if (!rpcbuf_alloc_size(buffer, *needed)) {
4835                 result = WERR_NOMEM;
4836                 goto out;
4837         }
4838
4839         /* fill the buffer with the structures */
4840         if (!smb_io_printer_info_2("", buffer, printer, 0))
4841                 result = WERR_NOMEM;
4842
4843 out:
4844         /* clear memory */
4845         free_printer_info_2(printer);
4846
4847         return result;
4848 }
4849
4850 /****************************************************************************
4851 ****************************************************************************/
4852
4853 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4854 {
4855         PRINTER_INFO_3 *printer=NULL;
4856         WERROR result = WERR_OK;
4857
4858         if (!construct_printer_info_3(print_hnd, &printer, snum))
4859                 return WERR_NOMEM;
4860
4861         /* check the required size. */
4862         *needed += spoolss_size_printer_info_3(printer);
4863
4864         if (*needed > offered) {
4865                 result = WERR_INSUFFICIENT_BUFFER;
4866                 goto out;
4867         }
4868
4869         if (!rpcbuf_alloc_size(buffer, *needed)) {
4870                 result = WERR_NOMEM;
4871                 goto out;
4872         }
4873
4874         /* fill the buffer with the structures */
4875         smb_io_printer_info_3("", buffer, printer, 0);
4876
4877 out:
4878         /* clear memory */
4879         free_printer_info_3(printer);
4880
4881         return result;
4882 }
4883
4884 /****************************************************************************
4885 ****************************************************************************/
4886
4887 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4888 {
4889         PRINTER_INFO_4 *printer=NULL;
4890         WERROR result = WERR_OK;
4891
4892         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4893                 return WERR_NOMEM;
4894
4895         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4896                 SAFE_FREE(printer);
4897                 return WERR_NOMEM;
4898         }
4899
4900         /* check the required size. */
4901         *needed += spoolss_size_printer_info_4(printer);
4902
4903         if (*needed > offered) {
4904                 result = WERR_INSUFFICIENT_BUFFER;
4905                 goto out;
4906         }
4907
4908         if (!rpcbuf_alloc_size(buffer, *needed)) {
4909                 result = WERR_NOMEM;
4910                 goto out;
4911         }
4912
4913         /* fill the buffer with the structures */
4914         smb_io_printer_info_4("", buffer, printer, 0);
4915
4916 out:
4917         /* clear memory */
4918         free_printer_info_4(printer);
4919
4920         return result;
4921 }
4922
4923 /****************************************************************************
4924 ****************************************************************************/
4925
4926 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4927 {
4928         PRINTER_INFO_5 *printer=NULL;
4929         WERROR result = WERR_OK;
4930
4931         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4932                 return WERR_NOMEM;
4933
4934         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4935                 free_printer_info_5(printer);
4936                 return WERR_NOMEM;
4937         }
4938
4939         /* check the required size. */
4940         *needed += spoolss_size_printer_info_5(printer);
4941
4942         if (*needed > offered) {
4943                 result = WERR_INSUFFICIENT_BUFFER;
4944                 goto out;
4945         }
4946
4947         if (!rpcbuf_alloc_size(buffer, *needed)) {
4948                 result = WERR_NOMEM;
4949                 goto out;
4950         }
4951
4952         /* fill the buffer with the structures */
4953         smb_io_printer_info_5("", buffer, printer, 0);
4954
4955 out:
4956         /* clear memory */
4957         free_printer_info_5(printer);
4958
4959         return result;
4960 }
4961
4962 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4963                                  int snum,
4964                                  RPC_BUFFER *buffer, uint32 offered,
4965                                  uint32 *needed)
4966 {
4967         PRINTER_INFO_6 *printer;
4968         WERROR result = WERR_OK;
4969
4970         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4971                 return WERR_NOMEM;
4972         }
4973
4974         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4975                 free_printer_info_6(printer);
4976                 return WERR_NOMEM;
4977         }
4978
4979         /* check the required size. */
4980         *needed += spoolss_size_printer_info_6(printer);
4981
4982         if (*needed > offered) {
4983                 result = WERR_INSUFFICIENT_BUFFER;
4984                 goto out;
4985         }
4986
4987         if (!rpcbuf_alloc_size(buffer, *needed)) {
4988                 result = WERR_NOMEM;
4989                 goto out;
4990         }
4991
4992         /* fill the buffer with the structures */
4993         smb_io_printer_info_6("", buffer, printer, 0);
4994
4995 out:
4996         /* clear memory */
4997         free_printer_info_6(printer);
4998
4999         return result;
5000 }
5001
5002 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5003 {
5004         PRINTER_INFO_7 *printer=NULL;
5005         WERROR result = WERR_OK;
5006
5007         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5008                 return WERR_NOMEM;
5009
5010         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5011                 result = WERR_NOMEM;
5012                 goto out;
5013         }
5014
5015         /* check the required size. */
5016         *needed += spoolss_size_printer_info_7(printer);
5017
5018         if (*needed > offered) {
5019                 result = WERR_INSUFFICIENT_BUFFER;
5020                 goto out;
5021         }
5022
5023         if (!rpcbuf_alloc_size(buffer, *needed)) {
5024                 result = WERR_NOMEM;
5025                 goto out;
5026
5027         }
5028
5029         /* fill the buffer with the structures */
5030         smb_io_printer_info_7("", buffer, printer, 0);
5031
5032 out:
5033         /* clear memory */
5034         free_printer_info_7(printer);
5035
5036         return result;
5037 }
5038
5039 /****************************************************************************
5040 ****************************************************************************/
5041
5042 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5043 {
5044         POLICY_HND *handle = &q_u->handle;
5045         uint32 level = q_u->level;
5046         RPC_BUFFER *buffer = NULL;
5047         uint32 offered = q_u->offered;
5048         uint32 *needed = &r_u->needed;
5049         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5050
5051         int snum;
5052
5053         /* that's an [in out] buffer */
5054
5055         if (!q_u->buffer && (offered!=0)) {
5056                 return WERR_INVALID_PARAM;
5057         }
5058
5059         if (offered > MAX_RPC_DATA_SIZE) {
5060                 return WERR_INVALID_PARAM;
5061         }
5062
5063         rpcbuf_move(q_u->buffer, &r_u->buffer);
5064         buffer = r_u->buffer;
5065
5066         *needed=0;
5067
5068         if (!get_printer_snum(p, handle, &snum, NULL))
5069                 return WERR_BADFID;
5070
5071         switch (level) {
5072         case 0:
5073                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5074         case 1:
5075                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5076         case 2:
5077                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5078         case 3:
5079                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5080         case 4:
5081                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5082         case 5:
5083                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5084         case 6:
5085                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5086         case 7:
5087                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5088         }
5089         return WERR_UNKNOWN_LEVEL;
5090 }
5091
5092 /********************************************************************
5093  * fill a DRIVER_INFO_1 struct
5094  ********************************************************************/
5095
5096 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5097 {
5098         init_unistr( &info->name, driver.info_3->name);
5099 }
5100
5101 /********************************************************************
5102  * construct_printer_driver_info_1
5103  ********************************************************************/
5104
5105 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5106 {
5107         NT_PRINTER_INFO_LEVEL *printer = NULL;
5108         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5109
5110         ZERO_STRUCT(driver);
5111
5112         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5113                 return WERR_INVALID_PRINTER_NAME;
5114
5115         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5116                 free_a_printer(&printer, 2);
5117                 return WERR_UNKNOWN_PRINTER_DRIVER;
5118         }
5119
5120         fill_printer_driver_info_1(info, driver, servername, architecture);
5121
5122         free_a_printer(&printer,2);
5123
5124         return WERR_OK;
5125 }
5126
5127 /********************************************************************
5128  * construct_printer_driver_info_2
5129  * fill a printer_info_2 struct
5130  ********************************************************************/
5131
5132 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5133 {
5134         TALLOC_CTX *ctx = talloc_tos();
5135         char *temp = NULL;
5136         const char *cservername = canon_servername(servername);
5137
5138         info->version=driver.info_3->cversion;
5139
5140         init_unistr( &info->name, driver.info_3->name );
5141         init_unistr( &info->architecture, driver.info_3->environment );
5142
5143         if (strlen(driver.info_3->driverpath)) {
5144                 temp = talloc_asprintf(ctx,
5145                                 "\\\\%s%s",
5146                                 cservername,
5147                                 driver.info_3->driverpath);
5148                 init_unistr( &info->driverpath, temp );
5149         } else {
5150                 init_unistr( &info->driverpath, "" );
5151         }
5152
5153         TALLOC_FREE(temp);
5154         if (strlen(driver.info_3->datafile)) {
5155                 temp = talloc_asprintf(ctx,
5156                                 "\\\\%s%s",
5157                                 cservername,
5158                                 driver.info_3->datafile);
5159                 init_unistr( &info->datafile, temp );
5160         } else
5161                 init_unistr( &info->datafile, "" );
5162
5163         TALLOC_FREE(temp);
5164         if (strlen(driver.info_3->configfile)) {
5165                 temp = talloc_asprintf(ctx,
5166                                 "\\\\%s%s",
5167                                 cservername,
5168                                 driver.info_3->configfile);
5169                 init_unistr( &info->configfile, temp );
5170         } else
5171                 init_unistr( &info->configfile, "" );
5172 }
5173
5174 /********************************************************************
5175  * construct_printer_driver_info_2
5176  * fill a printer_info_2 struct
5177  ********************************************************************/
5178
5179 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5180 {
5181         NT_PRINTER_INFO_LEVEL *printer = NULL;
5182         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5183
5184         ZERO_STRUCT(printer);
5185         ZERO_STRUCT(driver);
5186
5187         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5188                 return WERR_INVALID_PRINTER_NAME;
5189
5190         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5191                 free_a_printer(&printer, 2);
5192                 return WERR_UNKNOWN_PRINTER_DRIVER;
5193         }
5194
5195         fill_printer_driver_info_2(info, driver, servername);
5196
5197         free_a_printer(&printer,2);
5198
5199         return WERR_OK;
5200 }
5201
5202 /********************************************************************
5203  * copy a strings array and convert to UNICODE
5204  *
5205  * convert an array of ascii string to a UNICODE string
5206  ********************************************************************/
5207
5208 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5209 {
5210         int i=0;
5211         int j=0;
5212         const char *v;
5213         char *line = NULL;
5214         TALLOC_CTX *ctx = talloc_tos();
5215
5216         DEBUG(6,("init_unistr_array\n"));
5217         *uni_array=NULL;
5218
5219         while (true) {
5220                 if ( !char_array ) {
5221                         v = "";
5222                 } else {
5223                         v = char_array[i];
5224                         if (!v)
5225                                 v = ""; /* hack to handle null lists */
5226                 }
5227
5228                 /* hack to allow this to be used in places other than when generating
5229                    the list of dependent files */
5230
5231                 TALLOC_FREE(line);
5232                 if ( servername ) {
5233                         line = talloc_asprintf(ctx,
5234                                         "\\\\%s%s",
5235                                         canon_servername(servername),
5236                                         v);
5237                 } else {
5238                         line = talloc_strdup(ctx, v);
5239                 }
5240
5241                 if (!line) {
5242                         SAFE_FREE(*uni_array);
5243                         return 0;
5244                 }
5245                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5246
5247                 /* add one extra unit16 for the second terminating NULL */
5248
5249                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5250                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5251                         return 0;
5252                 }
5253
5254                 if ( !strlen(v) )
5255                         break;
5256
5257                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5258                 i++;
5259         }
5260
5261         if (*uni_array) {
5262                 /* special case for ""; we need to add both NULL's here */
5263                 if (!j)
5264                         (*uni_array)[j++]=0x0000;
5265                 (*uni_array)[j]=0x0000;
5266         }
5267
5268         DEBUGADD(6,("last one:done\n"));
5269
5270         /* return size of array in uint16's */
5271
5272         return j+1;
5273 }
5274
5275 /********************************************************************
5276  * construct_printer_info_3
5277  * fill a printer_info_3 struct
5278  ********************************************************************/
5279
5280 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5281 {
5282         char *temp = NULL;
5283         TALLOC_CTX *ctx = talloc_tos();
5284         const char *cservername = canon_servername(servername);
5285
5286         ZERO_STRUCTP(info);
5287
5288         info->version=driver.info_3->cversion;
5289
5290         init_unistr( &info->name, driver.info_3->name );
5291         init_unistr( &info->architecture, driver.info_3->environment );
5292
5293         if (strlen(driver.info_3->driverpath)) {
5294                 temp = talloc_asprintf(ctx,
5295                                 "\\\\%s%s",
5296                                 cservername,
5297                                 driver.info_3->driverpath);
5298                 init_unistr( &info->driverpath, temp );
5299         } else
5300                 init_unistr( &info->driverpath, "" );
5301
5302         TALLOC_FREE(temp);
5303         if (strlen(driver.info_3->datafile)) {
5304                 temp = talloc_asprintf(ctx,
5305                                 "\\\\%s%s",
5306                                 cservername,
5307                                 driver.info_3->datafile);
5308                 init_unistr( &info->datafile, temp );
5309         } else
5310                 init_unistr( &info->datafile, "" );
5311
5312         TALLOC_FREE(temp);
5313         if (strlen(driver.info_3->configfile)) {
5314                 temp = talloc_asprintf(ctx,
5315                                 "\\\\%s%s",
5316                                 cservername,
5317                                 driver.info_3->configfile);
5318                 init_unistr( &info->configfile, temp );
5319         } else
5320                 init_unistr( &info->configfile, "" );
5321
5322         TALLOC_FREE(temp);
5323         if (strlen(driver.info_3->helpfile)) {
5324                 temp = talloc_asprintf(ctx,
5325                                 "\\\\%s%s",
5326                                 cservername,
5327                                 driver.info_3->helpfile);
5328                 init_unistr( &info->helpfile, temp );
5329         } else
5330                 init_unistr( &info->helpfile, "" );
5331
5332         TALLOC_FREE(temp);
5333         init_unistr( &info->monitorname, driver.info_3->monitorname );
5334         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5335
5336         info->dependentfiles=NULL;
5337         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5338 }
5339
5340 /********************************************************************
5341  * construct_printer_info_3
5342  * fill a printer_info_3 struct
5343  ********************************************************************/
5344
5345 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5346 {
5347         NT_PRINTER_INFO_LEVEL *printer = NULL;
5348         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5349         WERROR status;
5350         ZERO_STRUCT(driver);
5351
5352         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5354         if (!W_ERROR_IS_OK(status))
5355                 return WERR_INVALID_PRINTER_NAME;
5356
5357         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5359
5360 #if 0   /* JERRY */
5361
5362         /*
5363          * I put this code in during testing.  Helpful when commenting out the
5364          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5365          * as win2k always queries the driver using an infor level of 6.
5366          * I've left it in (but ifdef'd out) because I'll probably
5367          * use it in experimentation again in the future.   --jerry 22/01/2002
5368          */
5369
5370         if (!W_ERROR_IS_OK(status)) {
5371                 /*
5372                  * Is this a W2k client ?
5373                  */
5374                 if (version == 3) {
5375                         /* Yes - try again with a WinNT driver. */
5376                         version = 2;
5377                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5378                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5379                 }
5380 #endif
5381
5382                 if (!W_ERROR_IS_OK(status)) {
5383                         free_a_printer(&printer,2);
5384                         return WERR_UNKNOWN_PRINTER_DRIVER;
5385                 }
5386
5387 #if 0   /* JERRY */
5388         }
5389 #endif
5390
5391
5392         fill_printer_driver_info_3(info, driver, servername);
5393
5394         free_a_printer(&printer,2);
5395
5396         return WERR_OK;
5397 }
5398
5399 /********************************************************************
5400  * construct_printer_info_6
5401  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5402  ********************************************************************/
5403
5404 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5405 {
5406         char *temp = NULL;
5407         fstring nullstr;
5408         TALLOC_CTX *ctx = talloc_tos();
5409         const char *cservername = canon_servername(servername);
5410
5411         ZERO_STRUCTP(info);
5412         memset(&nullstr, '\0', sizeof(fstring));
5413
5414         info->version=driver.info_3->cversion;
5415
5416         init_unistr( &info->name, driver.info_3->name );
5417         init_unistr( &info->architecture, driver.info_3->environment );
5418
5419         if (strlen(driver.info_3->driverpath)) {
5420                 temp = talloc_asprintf(ctx,
5421                                 "\\\\%s%s",
5422                                 cservername,
5423                                 driver.info_3->driverpath);
5424                 init_unistr( &info->driverpath, temp );
5425         } else
5426                 init_unistr( &info->driverpath, "" );
5427
5428         TALLOC_FREE(temp);
5429         if (strlen(driver.info_3->datafile)) {
5430                 temp = talloc_asprintf(ctx,
5431                                 "\\\\%s%s",
5432                                 cservername,
5433                                 driver.info_3->datafile);
5434                 init_unistr( &info->datafile, temp );
5435         } else
5436                 init_unistr( &info->datafile, "" );
5437
5438         TALLOC_FREE(temp);
5439         if (strlen(driver.info_3->configfile)) {
5440                 temp = talloc_asprintf(ctx,
5441                                 "\\\\%s%s",
5442                                 cservername,
5443                                 driver.info_3->configfile);
5444                 init_unistr( &info->configfile, temp );
5445         } else
5446                 init_unistr( &info->configfile, "" );
5447
5448         TALLOC_FREE(temp);
5449         if (strlen(driver.info_3->helpfile)) {
5450                 temp = talloc_asprintf(ctx,
5451                                 "\\\\%s%s",
5452                                 cservername,
5453                                 driver.info_3->helpfile);
5454                 init_unistr( &info->helpfile, temp );
5455         } else
5456                 init_unistr( &info->helpfile, "" );
5457
5458         TALLOC_FREE(temp);
5459         init_unistr( &info->monitorname, driver.info_3->monitorname );
5460         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5461
5462         info->dependentfiles = NULL;
5463         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5464
5465         info->previousdrivernames=NULL;
5466         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5467
5468         info->driver_date=0;
5469
5470         info->padding=0;
5471         info->driver_version_low=0;
5472         info->driver_version_high=0;
5473
5474         init_unistr( &info->mfgname, "");
5475         init_unistr( &info->oem_url, "");
5476         init_unistr( &info->hardware_id, "");
5477         init_unistr( &info->provider, "");
5478 }
5479
5480 /********************************************************************
5481  * construct_printer_info_6
5482  * fill a printer_info_6 struct
5483  ********************************************************************/
5484
5485 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5486               const char *servername, fstring architecture, uint32 version)
5487 {
5488         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5489         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5490         WERROR                          status;
5491
5492         ZERO_STRUCT(driver);
5493
5494         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5495
5496         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5497
5498         if (!W_ERROR_IS_OK(status))
5499                 return WERR_INVALID_PRINTER_NAME;
5500
5501         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5502
5503         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5504
5505         if (!W_ERROR_IS_OK(status))
5506         {
5507                 /*
5508                  * Is this a W2k client ?
5509                  */
5510
5511                 if (version < 3) {
5512                         free_a_printer(&printer,2);
5513                         return WERR_UNKNOWN_PRINTER_DRIVER;
5514                 }
5515
5516                 /* Yes - try again with a WinNT driver. */
5517                 version = 2;
5518                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5519                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5520                 if (!W_ERROR_IS_OK(status)) {
5521                         free_a_printer(&printer,2);
5522                         return WERR_UNKNOWN_PRINTER_DRIVER;
5523                 }
5524         }
5525
5526         fill_printer_driver_info_6(info, driver, servername);
5527
5528         free_a_printer(&printer,2);
5529         free_a_printer_driver(driver, 3);
5530
5531         return WERR_OK;
5532 }
5533
5534 /****************************************************************************
5535 ****************************************************************************/
5536
5537 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5538 {
5539         SAFE_FREE(info->dependentfiles);
5540 }
5541
5542 /****************************************************************************
5543 ****************************************************************************/
5544
5545 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5546 {
5547         SAFE_FREE(info->dependentfiles);
5548 }
5549
5550 /****************************************************************************
5551 ****************************************************************************/
5552
5553 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5554 {
5555         DRIVER_INFO_1 *info=NULL;
5556         WERROR result;
5557
5558         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5559                 return WERR_NOMEM;
5560
5561         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5562         if (!W_ERROR_IS_OK(result))
5563                 goto out;
5564
5565         /* check the required size. */
5566         *needed += spoolss_size_printer_driver_info_1(info);
5567
5568         if (*needed > offered) {
5569                 result = WERR_INSUFFICIENT_BUFFER;
5570                 goto out;
5571         }
5572
5573         if (!rpcbuf_alloc_size(buffer, *needed)) {
5574                 result = WERR_NOMEM;
5575                 goto out;
5576         }
5577
5578         /* fill the buffer with the structures */
5579         smb_io_printer_driver_info_1("", buffer, info, 0);
5580
5581 out:
5582         /* clear memory */
5583         SAFE_FREE(info);
5584
5585         return result;
5586 }
5587
5588 /****************************************************************************
5589 ****************************************************************************/
5590
5591 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5592 {
5593         DRIVER_INFO_2 *info=NULL;
5594         WERROR result;
5595
5596         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5597                 return WERR_NOMEM;
5598
5599         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5600         if (!W_ERROR_IS_OK(result))
5601                 goto out;
5602
5603         /* check the required size. */
5604         *needed += spoolss_size_printer_driver_info_2(info);
5605
5606         if (*needed > offered) {
5607                 result = WERR_INSUFFICIENT_BUFFER;
5608                 goto out;
5609         }
5610
5611         if (!rpcbuf_alloc_size(buffer, *needed)) {
5612                 result = WERR_NOMEM;
5613                 goto out;
5614         }
5615
5616         /* fill the buffer with the structures */
5617         smb_io_printer_driver_info_2("", buffer, info, 0);
5618
5619 out:
5620         /* clear memory */
5621         SAFE_FREE(info);
5622
5623         return result;
5624 }
5625
5626 /****************************************************************************
5627 ****************************************************************************/
5628
5629 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5630 {
5631         DRIVER_INFO_3 info;
5632         WERROR result;
5633
5634         ZERO_STRUCT(info);
5635
5636         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5637         if (!W_ERROR_IS_OK(result))
5638                 goto out;
5639
5640         /* check the required size. */
5641         *needed += spoolss_size_printer_driver_info_3(&info);
5642
5643         if (*needed > offered) {
5644                 result = WERR_INSUFFICIENT_BUFFER;
5645                 goto out;
5646         }
5647
5648         if (!rpcbuf_alloc_size(buffer, *needed)) {
5649                 result = WERR_NOMEM;
5650                 goto out;
5651         }
5652
5653         /* fill the buffer with the structures */
5654         smb_io_printer_driver_info_3("", buffer, &info, 0);
5655
5656 out:
5657         free_printer_driver_info_3(&info);
5658
5659         return result;
5660 }
5661
5662 /****************************************************************************
5663 ****************************************************************************/
5664
5665 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5666 {
5667         DRIVER_INFO_6 info;
5668         WERROR result;
5669
5670         ZERO_STRUCT(info);
5671
5672         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5673         if (!W_ERROR_IS_OK(result))
5674                 goto out;
5675
5676         /* check the required size. */
5677         *needed += spoolss_size_printer_driver_info_6(&info);
5678
5679         if (*needed > offered) {
5680                 result = WERR_INSUFFICIENT_BUFFER;
5681                 goto out;
5682         }
5683
5684         if (!rpcbuf_alloc_size(buffer, *needed)) {
5685                 result = WERR_NOMEM;
5686                 goto out;
5687         }
5688
5689         /* fill the buffer with the structures */
5690         smb_io_printer_driver_info_6("", buffer, &info, 0);
5691
5692 out:
5693         free_printer_driver_info_6(&info);
5694
5695         return result;
5696 }
5697
5698 /****************************************************************************
5699 ****************************************************************************/
5700
5701 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5702 {
5703         POLICY_HND *handle = &q_u->handle;
5704         UNISTR2 *uni_arch = &q_u->architecture;
5705         uint32 level = q_u->level;
5706         uint32 clientmajorversion = q_u->clientmajorversion;
5707         RPC_BUFFER *buffer = NULL;
5708         uint32 offered = q_u->offered;
5709         uint32 *needed = &r_u->needed;
5710         uint32 *servermajorversion = &r_u->servermajorversion;
5711         uint32 *serverminorversion = &r_u->serverminorversion;
5712         Printer_entry *printer;
5713
5714         fstring servername;
5715         fstring architecture;
5716         int snum;
5717
5718         /* that's an [in out] buffer */
5719
5720         if (!q_u->buffer && (offered!=0)) {
5721                 return WERR_INVALID_PARAM;
5722         }
5723
5724         if (offered > MAX_RPC_DATA_SIZE) {
5725                 return WERR_INVALID_PARAM;
5726         }
5727
5728         rpcbuf_move(q_u->buffer, &r_u->buffer);
5729         buffer = r_u->buffer;
5730
5731         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5732
5733         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5734                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5735                 return WERR_INVALID_PRINTER_NAME;
5736         }
5737
5738         *needed = 0;
5739         *servermajorversion = 0;
5740         *serverminorversion = 0;
5741
5742         fstrcpy(servername, get_server_name( printer ));
5743         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5744
5745         if (!get_printer_snum(p, handle, &snum, NULL))
5746                 return WERR_BADFID;
5747
5748         switch (level) {
5749         case 1:
5750                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5751         case 2:
5752                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5753         case 3:
5754                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5755         case 6:
5756                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5757 #if 0   /* JERRY */
5758         case 101:
5759                 /* apparently this call is the equivalent of
5760                    EnumPrinterDataEx() for the DsDriver key */
5761                 break;
5762 #endif
5763         }
5764
5765         return WERR_UNKNOWN_LEVEL;
5766 }
5767
5768
5769 /****************************************************************
5770  _spoolss_StartPagePrinter
5771 ****************************************************************/
5772
5773 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5774                                  struct spoolss_StartPagePrinter *r)
5775 {
5776         POLICY_HND *handle = r->in.handle;
5777
5778         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5779
5780         if (!Printer) {
5781                 DEBUG(3,("_spoolss_StartPagePrinter: "
5782                         "Error in startpageprinter printer handle\n"));
5783                 return WERR_BADFID;
5784         }
5785
5786         Printer->page_started=True;
5787         return WERR_OK;
5788 }
5789
5790 /****************************************************************
5791  _spoolss_EndPagePrinter
5792 ****************************************************************/
5793
5794 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5795                                struct spoolss_EndPagePrinter *r)
5796 {
5797         POLICY_HND *handle = r->in.handle;
5798         int snum;
5799
5800         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801
5802         if (!Printer) {
5803                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5804                         OUR_HANDLE(handle)));
5805                 return WERR_BADFID;
5806         }
5807
5808         if (!get_printer_snum(p, handle, &snum, NULL))
5809                 return WERR_BADFID;
5810
5811         Printer->page_started=False;
5812         print_job_endpage(snum, Printer->jobid);
5813
5814         return WERR_OK;
5815 }
5816
5817 /****************************************************************
5818  _spoolss_StartDocPrinter
5819 ****************************************************************/
5820
5821 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5822                                 struct spoolss_StartDocPrinter *r)
5823 {
5824         POLICY_HND *handle = r->in.handle;
5825         uint32_t *jobid = r->out.job_id;
5826         struct spoolss_DocumentInfo1 *info_1;
5827         int snum;
5828         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5829
5830         if (!Printer) {
5831                 DEBUG(2,("_spoolss_StartDocPrinter: "
5832                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5833                 return WERR_BADFID;
5834         }
5835
5836         if (r->in.level != 1) {
5837                 return WERR_UNKNOWN_LEVEL;
5838         }
5839
5840         info_1 = r->in.info.info1;
5841
5842         /*
5843          * a nice thing with NT is it doesn't listen to what you tell it.
5844          * when asked to send _only_ RAW datas, it tries to send datas
5845          * in EMF format.
5846          *
5847          * So I add checks like in NT Server ...
5848          */
5849
5850         if (info_1->datatype) {
5851                 if (strcmp(info_1->datatype, "RAW") != 0) {
5852                         (*jobid)=0;
5853                         return WERR_INVALID_DATATYPE;
5854                 }
5855         }
5856
5857         /* get the share number of the printer */
5858         if (!get_printer_snum(p, handle, &snum, NULL)) {
5859                 return WERR_BADFID;
5860         }
5861
5862         Printer->jobid = print_job_start(p->server_info, snum,
5863                                          CONST_DISCARD(char *,info_1->document_name),
5864                                          Printer->nt_devmode);
5865
5866         /* An error occured in print_job_start() so return an appropriate
5867            NT error code. */
5868
5869         if (Printer->jobid == -1) {
5870                 return map_werror_from_unix(errno);
5871         }
5872
5873         Printer->document_started=True;
5874         (*jobid) = Printer->jobid;
5875
5876         return WERR_OK;
5877 }
5878
5879 /****************************************************************
5880  _spoolss_EndDocPrinter
5881 ****************************************************************/
5882
5883 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5884                               struct spoolss_EndDocPrinter *r)
5885 {
5886         POLICY_HND *handle = r->in.handle;
5887
5888         return _spoolss_enddocprinter_internal(p, handle);
5889 }
5890
5891 /****************************************************************
5892  _spoolss_WritePrinter
5893 ****************************************************************/
5894
5895 WERROR _spoolss_WritePrinter(pipes_struct *p,
5896                              struct spoolss_WritePrinter *r)
5897 {
5898         POLICY_HND *handle = r->in.handle;
5899         uint32 buffer_size = r->in._data_size;
5900         uint8 *buffer = r->in.data.data;
5901         uint32 *buffer_written = &r->in._data_size;
5902         int snum;
5903         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5904
5905         if (!Printer) {
5906                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5907                         OUR_HANDLE(handle)));
5908                 *r->out.num_written = r->in._data_size;
5909                 return WERR_BADFID;
5910         }
5911
5912         if (!get_printer_snum(p, handle, &snum, NULL))
5913                 return WERR_BADFID;
5914
5915         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5916                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5917         if (*buffer_written == (uint32)-1) {
5918                 *r->out.num_written = 0;
5919                 if (errno == ENOSPC)
5920                         return WERR_NO_SPOOL_SPACE;
5921                 else
5922                         return WERR_ACCESS_DENIED;
5923         }
5924
5925         *r->out.num_written = r->in._data_size;
5926
5927         return WERR_OK;
5928 }
5929
5930 /********************************************************************
5931  * api_spoolss_getprinter
5932  * called from the spoolss dispatcher
5933  *
5934  ********************************************************************/
5935
5936 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5937                               pipes_struct *p)
5938 {
5939         int snum;
5940         WERROR errcode = WERR_BADFUNC;
5941         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5942
5943         if (!Printer) {
5944                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5945                 return WERR_BADFID;
5946         }
5947
5948         if (!get_printer_snum(p, handle, &snum, NULL))
5949                 return WERR_BADFID;
5950
5951         switch (command) {
5952         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5953                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5954                         errcode = WERR_OK;
5955                 }
5956                 break;
5957         case SPOOLSS_PRINTER_CONTROL_RESUME:
5958         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5959                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5960                         errcode = WERR_OK;
5961                 }
5962                 break;
5963         case SPOOLSS_PRINTER_CONTROL_PURGE:
5964                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5965                         errcode = WERR_OK;
5966                 }
5967                 break;
5968         default:
5969                 return WERR_UNKNOWN_LEVEL;
5970         }
5971
5972         return errcode;
5973 }
5974
5975
5976 /****************************************************************
5977  _spoolss_AbortPrinter
5978  * From MSDN: "Deletes printer's spool file if printer is configured
5979  * for spooling"
5980 ****************************************************************/
5981
5982 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5983                              struct spoolss_AbortPrinter *r)
5984 {
5985         POLICY_HND      *handle = r->in.handle;
5986         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5987         int             snum;
5988         WERROR          errcode = WERR_OK;
5989
5990         if (!Printer) {
5991                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5992                         OUR_HANDLE(handle)));
5993                 return WERR_BADFID;
5994         }
5995
5996         if (!get_printer_snum(p, handle, &snum, NULL))
5997                 return WERR_BADFID;
5998
5999         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6000
6001         return errcode;
6002 }
6003
6004 /********************************************************************
6005  * called by spoolss_api_setprinter
6006  * when updating a printer description
6007  ********************************************************************/
6008
6009 static WERROR update_printer_sec(POLICY_HND *handle,
6010                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6011 {
6012         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6013         WERROR result;
6014         int snum;
6015
6016         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6017
6018         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6019                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6020                          OUR_HANDLE(handle)));
6021
6022                 result = WERR_BADFID;
6023                 goto done;
6024         }
6025
6026         if (!secdesc_ctr) {
6027                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6028                 result = WERR_INVALID_PARAM;
6029                 goto done;
6030         }
6031
6032         /* Check the user has permissions to change the security
6033            descriptor.  By experimentation with two NT machines, the user
6034            requires Full Access to the printer to change security
6035            information. */
6036
6037         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6038                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6039                 result = WERR_ACCESS_DENIED;
6040                 goto done;
6041         }
6042
6043         /* NT seems to like setting the security descriptor even though
6044            nothing may have actually changed. */
6045
6046         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6047                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6048                 result = WERR_BADFID;
6049                 goto done;
6050         }
6051
6052         if (DEBUGLEVEL >= 10) {
6053                 SEC_ACL *the_acl;
6054                 int i;
6055
6056                 the_acl = old_secdesc_ctr->sd->dacl;
6057                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6058                            PRINTERNAME(snum), the_acl->num_aces));
6059
6060                 for (i = 0; i < the_acl->num_aces; i++) {
6061                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6062                                            &the_acl->aces[i].trustee),
6063                                   the_acl->aces[i].access_mask));
6064                 }
6065
6066                 the_acl = secdesc_ctr->sd->dacl;
6067
6068                 if (the_acl) {
6069                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6070                                    PRINTERNAME(snum), the_acl->num_aces));
6071
6072                         for (i = 0; i < the_acl->num_aces; i++) {
6073                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6074                                                    &the_acl->aces[i].trustee),
6075                                            the_acl->aces[i].access_mask));
6076                         }
6077                 } else {
6078                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6079                 }
6080         }
6081
6082         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6083         if (!new_secdesc_ctr) {
6084                 result = WERR_NOMEM;
6085                 goto done;
6086         }
6087
6088         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6089                 result = WERR_OK;
6090                 goto done;
6091         }
6092
6093         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6094
6095  done:
6096
6097         return result;
6098 }
6099
6100 /********************************************************************
6101  Canonicalize printer info from a client
6102
6103  ATTN: It does not matter what we set the servername to hear
6104  since we do the necessary work in get_a_printer() to set it to
6105  the correct value based on what the client sent in the
6106  _spoolss_open_printer_ex().
6107  ********************************************************************/
6108
6109 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6110 {
6111         fstring printername;
6112         const char *p;
6113
6114         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6115                 "portname=%s drivername=%s comment=%s location=%s\n",
6116                 info->servername, info->printername, info->sharename,
6117                 info->portname, info->drivername, info->comment, info->location));
6118
6119         /* we force some elements to "correct" values */
6120         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6121         fstrcpy(info->sharename, lp_servicename(snum));
6122
6123         /* check to see if we allow printername != sharename */
6124
6125         if ( lp_force_printername(snum) ) {
6126                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6127                         global_myname(), info->sharename );
6128         } else {
6129
6130                 /* make sure printername is in \\server\printername format */
6131
6132                 fstrcpy( printername, info->printername );
6133                 p = printername;
6134                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6135                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6136                                 p++;
6137                 }
6138
6139                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6140                          global_myname(), p );
6141         }
6142
6143         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6144         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6145
6146
6147
6148         return True;
6149 }
6150
6151 /****************************************************************************
6152 ****************************************************************************/
6153
6154 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6155 {
6156         char *cmd = lp_addport_cmd();
6157         char *command = NULL;
6158         int ret;
6159         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6160         bool is_print_op = False;
6161
6162         if ( !*cmd ) {
6163                 return WERR_ACCESS_DENIED;
6164         }
6165
6166         command = talloc_asprintf(ctx,
6167                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6168         if (!command) {
6169                 return WERR_NOMEM;
6170         }
6171
6172         if ( token )
6173                 is_print_op = user_has_privileges( token, &se_printop );
6174
6175         DEBUG(10,("Running [%s]\n", command));
6176
6177         /********* BEGIN SePrintOperatorPrivilege **********/
6178
6179         if ( is_print_op )
6180                 become_root();
6181
6182         ret = smbrun(command, NULL);
6183
6184         if ( is_print_op )
6185                 unbecome_root();
6186
6187         /********* END SePrintOperatorPrivilege **********/
6188
6189         DEBUGADD(10,("returned [%d]\n", ret));
6190
6191         TALLOC_FREE(command);
6192
6193         if ( ret != 0 ) {
6194                 return WERR_ACCESS_DENIED;
6195         }
6196
6197         return WERR_OK;
6198 }
6199
6200 /****************************************************************************
6201 ****************************************************************************/
6202
6203 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6204 {
6205         char *cmd = lp_addprinter_cmd();
6206         char **qlines;
6207         char *command = NULL;
6208         int numlines;
6209         int ret;
6210         int fd;
6211         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6212         bool is_print_op = False;
6213         char *remote_machine = talloc_strdup(ctx, "%m");
6214
6215         if (!remote_machine) {
6216                 return false;
6217         }
6218         remote_machine = talloc_sub_basic(ctx,
6219                                 current_user_info.smb_name,
6220                                 current_user_info.domain,
6221                                 remote_machine);
6222         if (!remote_machine) {
6223                 return false;
6224         }
6225
6226         command = talloc_asprintf(ctx,
6227                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6228                         cmd, printer->info_2->printername, printer->info_2->sharename,
6229                         printer->info_2->portname, printer->info_2->drivername,
6230                         printer->info_2->location, printer->info_2->comment, remote_machine);
6231         if (!command) {
6232                 return false;
6233         }
6234
6235         if ( token )
6236                 is_print_op = user_has_privileges( token, &se_printop );
6237
6238         DEBUG(10,("Running [%s]\n", command));
6239
6240         /********* BEGIN SePrintOperatorPrivilege **********/
6241
6242         if ( is_print_op )
6243                 become_root();
6244
6245         if ( (ret = smbrun(command, &fd)) == 0 ) {
6246                 /* Tell everyone we updated smb.conf. */
6247                 message_send_all(smbd_messaging_context(),
6248                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6249         }
6250
6251         if ( is_print_op )
6252                 unbecome_root();
6253
6254         /********* END SePrintOperatorPrivilege **********/
6255
6256         DEBUGADD(10,("returned [%d]\n", ret));
6257
6258         TALLOC_FREE(command);
6259         TALLOC_FREE(remote_machine);
6260
6261         if ( ret != 0 ) {
6262                 if (fd != -1)
6263                         close(fd);
6264                 return False;
6265         }
6266
6267         /* reload our services immediately */
6268         reload_services( False );
6269
6270         numlines = 0;
6271         /* Get lines and convert them back to dos-codepage */
6272         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6273         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6274         close(fd);
6275
6276         /* Set the portname to what the script says the portname should be. */
6277         /* but don't require anything to be return from the script exit a good error code */
6278
6279         if (numlines) {
6280                 /* Set the portname to what the script says the portname should be. */
6281                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6282                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6283         }
6284
6285         TALLOC_FREE(qlines);
6286         return True;
6287 }
6288
6289
6290 /********************************************************************
6291  * Called by spoolss_api_setprinter
6292  * when updating a printer description.
6293  ********************************************************************/
6294
6295 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6296                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6297                              struct spoolss_DeviceMode *devmode)
6298 {
6299         int snum;
6300         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6301         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6302         WERROR result;
6303         UNISTR2 buffer;
6304         fstring asc_buffer;
6305
6306         DEBUG(8,("update_printer\n"));
6307
6308         result = WERR_OK;
6309
6310         if (!Printer) {
6311                 result = WERR_BADFID;
6312                 goto done;
6313         }
6314
6315         if (!get_printer_snum(p, handle, &snum, NULL)) {
6316                 result = WERR_BADFID;
6317                 goto done;
6318         }
6319
6320         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6321             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6322                 result = WERR_BADFID;
6323                 goto done;
6324         }
6325
6326         DEBUGADD(8,("Converting info_2 struct\n"));
6327
6328         /*
6329          * convert_printer_info converts the incoming
6330          * info from the client and overwrites the info
6331          * just read from the tdb in the pointer 'printer'.
6332          */
6333
6334         if (!convert_printer_info_new(info_ctr, printer)) {
6335                 result =  WERR_NOMEM;
6336                 goto done;
6337         }
6338
6339         if (devmode) {
6340                 /* we have a valid devmode
6341                    convert it and link it*/
6342
6343                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6344                 if (!convert_devicemode_new(printer->info_2->printername,
6345                                             devmode,
6346                                             &printer->info_2->devmode)) {
6347                         result =  WERR_NOMEM;
6348                         goto done;
6349                 }
6350         }
6351
6352         /* Do sanity check on the requested changes for Samba */
6353
6354         if (!check_printer_ok(printer->info_2, snum)) {
6355                 result = WERR_INVALID_PARAM;
6356                 goto done;
6357         }
6358
6359         /* FIXME!!! If the driver has changed we really should verify that
6360            it is installed before doing much else   --jerry */
6361
6362         /* Check calling user has permission to update printer description */
6363
6364         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6365                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6366                 result = WERR_ACCESS_DENIED;
6367                 goto done;
6368         }
6369
6370         /* Call addprinter hook */
6371         /* Check changes to see if this is really needed */
6372
6373         if ( *lp_addprinter_cmd()
6374                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6375                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6376                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6377                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6378         {
6379                 /* add_printer_hook() will call reload_services() */
6380
6381                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6382                                        printer) ) {
6383                         result = WERR_ACCESS_DENIED;
6384                         goto done;
6385                 }
6386         }
6387
6388         /*
6389          * When a *new* driver is bound to a printer, the drivername is used to
6390          * lookup previously saved driver initialization info, which is then
6391          * bound to the printer, simulating what happens in the Windows arch.
6392          */
6393         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6394         {
6395                 if (!set_driver_init(printer, 2))
6396                 {
6397                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6398                                 printer->info_2->drivername));
6399                 }
6400
6401                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6402                         printer->info_2->drivername));
6403
6404                 notify_printer_driver(snum, printer->info_2->drivername);
6405         }
6406
6407         /*
6408          * flag which changes actually occured.  This is a small subset of
6409          * all the possible changes.  We also have to update things in the
6410          * DsSpooler key.
6411          */
6412
6413         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6414                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6415                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6416                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6417
6418                 notify_printer_comment(snum, printer->info_2->comment);
6419         }
6420
6421         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6422                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6423                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6424                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6425
6426                 notify_printer_sharename(snum, printer->info_2->sharename);
6427         }
6428
6429         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6430                 char *pname;
6431
6432                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6433                         pname++;
6434                 else
6435                         pname = printer->info_2->printername;
6436
6437
6438                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6439                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6440                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6441
6442                 notify_printer_printername( snum, pname );
6443         }
6444
6445         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6446                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6447                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6448                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6449
6450                 notify_printer_port(snum, printer->info_2->portname);
6451         }
6452
6453         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6454                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6455                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6456                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6457
6458                 notify_printer_location(snum, printer->info_2->location);
6459         }
6460
6461         /* here we need to update some more DsSpooler keys */
6462         /* uNCName, serverName, shortServerName */
6463
6464         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6465         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6466                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6467         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6468                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6469
6470         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6471                  global_myname(), printer->info_2->sharename );
6472         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6473         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6474                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475
6476         /* Update printer info */
6477         result = mod_a_printer(printer, 2);
6478
6479 done:
6480         free_a_printer(&printer, 2);
6481         free_a_printer(&old_printer, 2);
6482
6483
6484         return result;
6485 }
6486
6487 /****************************************************************************
6488 ****************************************************************************/
6489 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6490                                            struct spoolss_SetPrinterInfo7 *info7)
6491 {
6492 #ifdef HAVE_ADS
6493         int snum;
6494         Printer_entry *Printer;
6495
6496         if ( lp_security() != SEC_ADS ) {
6497                 return WERR_UNKNOWN_LEVEL;
6498         }
6499
6500         Printer = find_printer_index_by_hnd(p, handle);
6501
6502         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6503
6504         if (!Printer)
6505                 return WERR_BADFID;
6506
6507         if (!get_printer_snum(p, handle, &snum, NULL))
6508                 return WERR_BADFID;
6509
6510         nt_printer_publish(Printer, snum, info7->action);
6511
6512         return WERR_OK;
6513 #else
6514         return WERR_UNKNOWN_LEVEL;
6515 #endif
6516 }
6517
6518 /****************************************************************
6519  _spoolss_SetPrinter
6520 ****************************************************************/
6521
6522 WERROR _spoolss_SetPrinter(pipes_struct *p,
6523                            struct spoolss_SetPrinter *r)
6524 {
6525         POLICY_HND *handle = r->in.handle;
6526         WERROR result;
6527
6528         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6529
6530         if (!Printer) {
6531                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6532                         OUR_HANDLE(handle)));
6533                 return WERR_BADFID;
6534         }
6535
6536         /* check the level */
6537         switch (r->in.info_ctr->level) {
6538                 case 0:
6539                         return control_printer(handle, r->in.command, p);
6540                 case 2:
6541                         result = update_printer(p, handle,
6542                                                 r->in.info_ctr,
6543                                                 r->in.devmode_ctr->devmode);
6544                         if (!W_ERROR_IS_OK(result))
6545                                 return result;
6546                         if (r->in.secdesc_ctr->sd)
6547                                 result = update_printer_sec(handle, p,
6548                                                             r->in.secdesc_ctr);
6549                         return result;
6550                 case 3:
6551                         return update_printer_sec(handle, p,
6552                                                   r->in.secdesc_ctr);
6553                 case 7:
6554                         return publish_or_unpublish_printer(p, handle,
6555                                                             r->in.info_ctr->info.info7);
6556                 default:
6557                         return WERR_UNKNOWN_LEVEL;
6558         }
6559 }
6560
6561 /****************************************************************
6562  _spoolss_FindClosePrinterNotify
6563 ****************************************************************/
6564
6565 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6566                                        struct spoolss_FindClosePrinterNotify *r)
6567 {
6568         POLICY_HND *handle = r->in.handle;
6569         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6570
6571         if (!Printer) {
6572                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6573                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6574                 return WERR_BADFID;
6575         }
6576
6577         if (Printer->notify.client_connected==True) {
6578                 int snum = -1;
6579
6580                 if ( Printer->printer_type == SPLHND_SERVER)
6581                         snum = -1;
6582                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6583                                 !get_printer_snum(p, handle, &snum, NULL) )
6584                         return WERR_BADFID;
6585
6586                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6587         }
6588
6589         Printer->notify.flags=0;
6590         Printer->notify.options=0;
6591         Printer->notify.localmachine[0]='\0';
6592         Printer->notify.printerlocal=0;
6593         if (Printer->notify.option)
6594                 free_spool_notify_option(&Printer->notify.option);
6595         Printer->notify.client_connected=False;
6596
6597         return WERR_OK;
6598 }
6599
6600 /****************************************************************
6601  _spoolss_AddJob
6602 ****************************************************************/
6603
6604 WERROR _spoolss_AddJob(pipes_struct *p,
6605                        struct spoolss_AddJob *r)
6606 {
6607         if (!r->in.buffer && (r->in.offered != 0)) {
6608                 return WERR_INVALID_PARAM;
6609         }
6610
6611         /* this is what a NT server returns for AddJob. AddJob must fail on
6612          * non-local printers */
6613
6614         return WERR_INVALID_PARAM;
6615 }
6616
6617 /****************************************************************************
6618 ****************************************************************************/
6619
6620 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6621                             int position, int snum,
6622                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6623 {
6624         struct tm *t;
6625
6626         t=gmtime(&queue->time);
6627
6628         job_info->jobid=queue->job;
6629         init_unistr(&job_info->printername, lp_servicename(snum));
6630         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6631         init_unistr(&job_info->username, queue->fs_user);
6632         init_unistr(&job_info->document, queue->fs_file);
6633         init_unistr(&job_info->datatype, "RAW");
6634         init_unistr(&job_info->text_status, "");
6635         job_info->status=nt_printj_status(queue->status);
6636         job_info->priority=queue->priority;
6637         job_info->position=position;
6638         job_info->totalpages=queue->page_count;
6639         job_info->pagesprinted=0;
6640
6641         make_systemtime(&job_info->submitted, t);
6642 }
6643
6644 /****************************************************************************
6645 ****************************************************************************/
6646
6647 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6648                             int position, int snum,
6649                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6650                             DEVICEMODE *devmode)
6651 {
6652         struct tm *t;
6653
6654         t=gmtime(&queue->time);
6655
6656         job_info->jobid=queue->job;
6657
6658         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6659
6660         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6661         init_unistr(&job_info->username, queue->fs_user);
6662         init_unistr(&job_info->document, queue->fs_file);
6663         init_unistr(&job_info->notifyname, queue->fs_user);
6664         init_unistr(&job_info->datatype, "RAW");
6665         init_unistr(&job_info->printprocessor, "winprint");
6666         init_unistr(&job_info->parameters, "");
6667         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6668         init_unistr(&job_info->text_status, "");
6669
6670 /* and here the security descriptor */
6671
6672         job_info->status=nt_printj_status(queue->status);
6673         job_info->priority=queue->priority;
6674         job_info->position=position;
6675         job_info->starttime=0;
6676         job_info->untiltime=0;
6677         job_info->totalpages=queue->page_count;
6678         job_info->size=queue->size;
6679         make_systemtime(&(job_info->submitted), t);
6680         job_info->timeelapsed=0;
6681         job_info->pagesprinted=0;
6682
6683         job_info->devmode = devmode;
6684
6685         return (True);
6686 }
6687
6688 /****************************************************************************
6689  Enumjobs at level 1.
6690 ****************************************************************************/
6691
6692 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6693                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6694                               RPC_BUFFER *buffer, uint32 offered,
6695                               uint32 *needed, uint32 *returned)
6696 {
6697         JOB_INFO_1 *info;
6698         int i;
6699         WERROR result = WERR_OK;
6700
6701         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6702         if (info==NULL) {
6703                 *returned=0;
6704                 return WERR_NOMEM;
6705         }
6706
6707         for (i=0; i<*returned; i++)
6708                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6709
6710         /* check the required size. */
6711         for (i=0; i<*returned; i++)
6712                 (*needed) += spoolss_size_job_info_1(&info[i]);
6713
6714         if (*needed > offered) {
6715                 result = WERR_INSUFFICIENT_BUFFER;
6716                 goto out;
6717         }
6718
6719         if (!rpcbuf_alloc_size(buffer, *needed)) {
6720                 result = WERR_NOMEM;
6721                 goto out;
6722         }
6723
6724         /* fill the buffer with the structures */
6725         for (i=0; i<*returned; i++)
6726                 smb_io_job_info_1("", buffer, &info[i], 0);
6727
6728 out:
6729         /* clear memory */
6730         SAFE_FREE(info);
6731
6732         if ( !W_ERROR_IS_OK(result) )
6733                 *returned = 0;
6734
6735         return result;
6736 }
6737
6738 /****************************************************************************
6739  Enumjobs at level 2.
6740 ****************************************************************************/
6741
6742 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6743                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6744                               RPC_BUFFER *buffer, uint32 offered,
6745                               uint32 *needed, uint32 *returned)
6746 {
6747         JOB_INFO_2 *info = NULL;
6748         int i;
6749         WERROR result = WERR_OK;
6750         DEVICEMODE *devmode = NULL;
6751
6752         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6753                 *returned=0;
6754                 return WERR_NOMEM;
6755         }
6756
6757         /* this should not be a failure condition if the devmode is NULL */
6758
6759         devmode = construct_dev_mode(lp_const_servicename(snum));
6760
6761         for (i=0; i<*returned; i++)
6762                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6763
6764         /* check the required size. */
6765         for (i=0; i<*returned; i++)
6766                 (*needed) += spoolss_size_job_info_2(&info[i]);
6767
6768         if (*needed > offered) {
6769                 result = WERR_INSUFFICIENT_BUFFER;
6770                 goto out;
6771         }
6772
6773         if (!rpcbuf_alloc_size(buffer, *needed)) {
6774                 result = WERR_NOMEM;
6775                 goto out;
6776         }
6777
6778         /* fill the buffer with the structures */
6779         for (i=0; i<*returned; i++)
6780                 smb_io_job_info_2("", buffer, &info[i], 0);
6781
6782 out:
6783         free_devmode(devmode);
6784         SAFE_FREE(info);
6785
6786         if ( !W_ERROR_IS_OK(result) )
6787                 *returned = 0;
6788
6789         return result;
6790
6791 }
6792
6793 /****************************************************************************
6794  Enumjobs.
6795 ****************************************************************************/
6796
6797 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6798 {
6799         POLICY_HND *handle = &q_u->handle;
6800         uint32 level = q_u->level;
6801         RPC_BUFFER *buffer = NULL;
6802         uint32 offered = q_u->offered;
6803         uint32 *needed = &r_u->needed;
6804         uint32 *returned = &r_u->returned;
6805         WERROR wret;
6806         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6807         int snum;
6808         print_status_struct prt_status;
6809         print_queue_struct *queue=NULL;
6810
6811         /* that's an [in out] buffer */
6812
6813         if (!q_u->buffer && (offered!=0)) {
6814                 return WERR_INVALID_PARAM;
6815         }
6816
6817         if (offered > MAX_RPC_DATA_SIZE) {
6818                 return WERR_INVALID_PARAM;
6819         }
6820
6821         rpcbuf_move(q_u->buffer, &r_u->buffer);
6822         buffer = r_u->buffer;
6823
6824         DEBUG(4,("_spoolss_enumjobs\n"));
6825
6826         *needed=0;
6827         *returned=0;
6828
6829         /* lookup the printer snum and tdb entry */
6830
6831         if (!get_printer_snum(p, handle, &snum, NULL))
6832                 return WERR_BADFID;
6833
6834         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6835         if ( !W_ERROR_IS_OK(wret) )
6836                 return wret;
6837
6838         *returned = print_queue_status(snum, &queue, &prt_status);
6839         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6840
6841         if (*returned == 0) {
6842                 SAFE_FREE(queue);
6843                 free_a_printer(&ntprinter, 2);
6844                 return WERR_OK;
6845         }
6846
6847         switch (level) {
6848         case 1:
6849                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6850                 break;
6851         case 2:
6852                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6853                 break;
6854         default:
6855                 *returned=0;
6856                 wret = WERR_UNKNOWN_LEVEL;
6857                 break;
6858         }
6859
6860         SAFE_FREE(queue);
6861         free_a_printer( &ntprinter, 2 );
6862         return wret;
6863 }
6864
6865 /****************************************************************
6866  _spoolss_ScheduleJob
6867 ****************************************************************/
6868
6869 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6870                             struct spoolss_ScheduleJob *r)
6871 {
6872         return WERR_OK;
6873 }
6874
6875 /****************************************************************
6876  _spoolss_SetJob
6877 ****************************************************************/
6878
6879 WERROR _spoolss_SetJob(pipes_struct *p,
6880                        struct spoolss_SetJob *r)
6881 {
6882         POLICY_HND *handle = r->in.handle;
6883         uint32 jobid = r->in.job_id;
6884         uint32 command = r->in.command;
6885
6886         int snum;
6887         WERROR errcode = WERR_BADFUNC;
6888
6889         if (!get_printer_snum(p, handle, &snum, NULL)) {
6890                 return WERR_BADFID;
6891         }
6892
6893         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6894                 return WERR_INVALID_PRINTER_NAME;
6895         }
6896
6897         switch (command) {
6898         case SPOOLSS_JOB_CONTROL_CANCEL:
6899         case SPOOLSS_JOB_CONTROL_DELETE:
6900                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6901                         errcode = WERR_OK;
6902                 }
6903                 break;
6904         case SPOOLSS_JOB_CONTROL_PAUSE:
6905                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6906                         errcode = WERR_OK;
6907                 }
6908                 break;
6909         case SPOOLSS_JOB_CONTROL_RESTART:
6910         case SPOOLSS_JOB_CONTROL_RESUME:
6911                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6912                         errcode = WERR_OK;
6913                 }
6914                 break;
6915         default:
6916                 return WERR_UNKNOWN_LEVEL;
6917         }
6918
6919         return errcode;
6920 }
6921
6922 /****************************************************************************
6923  Enumerates all printer drivers at level 1.
6924 ****************************************************************************/
6925
6926 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6927 {
6928         int i;
6929         int ndrivers;
6930         uint32 version;
6931         fstring *list = NULL;
6932         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6933         DRIVER_INFO_1 *driver_info_1=NULL;
6934         WERROR result = WERR_OK;
6935
6936         *returned=0;
6937
6938         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6939                 list=NULL;
6940                 ndrivers=get_ntdrivers(&list, architecture, version);
6941                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6942
6943                 if(ndrivers == -1) {
6944                         SAFE_FREE(driver_info_1);
6945                         return WERR_NOMEM;
6946                 }
6947
6948                 if(ndrivers != 0) {
6949                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6950                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6951                                 SAFE_FREE(list);
6952                                 return WERR_NOMEM;
6953                         }
6954                 }
6955
6956                 for (i=0; i<ndrivers; i++) {
6957                         WERROR status;
6958                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6959                         ZERO_STRUCT(driver);
6960                         status = get_a_printer_driver(&driver, 3, list[i],
6961                                                       architecture, version);
6962                         if (!W_ERROR_IS_OK(status)) {
6963                                 SAFE_FREE(list);
6964                                 SAFE_FREE(driver_info_1);
6965                                 return status;
6966                         }
6967                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6968                         free_a_printer_driver(driver, 3);
6969                 }
6970
6971                 *returned+=ndrivers;
6972                 SAFE_FREE(list);
6973         }
6974
6975         /* check the required size. */
6976         for (i=0; i<*returned; i++) {
6977                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6978                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6979         }
6980
6981         if (*needed > offered) {
6982                 result = WERR_INSUFFICIENT_BUFFER;
6983                 goto out;
6984         }
6985
6986         if (!rpcbuf_alloc_size(buffer, *needed)) {
6987                 result = WERR_NOMEM;
6988                 goto out;
6989         }
6990
6991         /* fill the buffer with the driver structures */
6992         for (i=0; i<*returned; i++) {
6993                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6994                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6995         }
6996
6997 out:
6998         SAFE_FREE(driver_info_1);
6999
7000         if ( !W_ERROR_IS_OK(result) )
7001                 *returned = 0;
7002
7003         return result;
7004 }
7005
7006 /****************************************************************************
7007  Enumerates all printer drivers at level 2.
7008 ****************************************************************************/
7009
7010 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7011 {
7012         int i;
7013         int ndrivers;
7014         uint32 version;
7015         fstring *list = NULL;
7016         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7017         DRIVER_INFO_2 *driver_info_2=NULL;
7018         WERROR result = WERR_OK;
7019
7020         *returned=0;
7021
7022         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7023                 list=NULL;
7024                 ndrivers=get_ntdrivers(&list, architecture, version);
7025                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7026
7027                 if(ndrivers == -1) {
7028                         SAFE_FREE(driver_info_2);
7029                         return WERR_NOMEM;
7030                 }
7031
7032                 if(ndrivers != 0) {
7033                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7034                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7035                                 SAFE_FREE(list);
7036                                 return WERR_NOMEM;
7037                         }
7038                 }
7039
7040                 for (i=0; i<ndrivers; i++) {
7041                         WERROR status;
7042
7043                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7044                         ZERO_STRUCT(driver);
7045                         status = get_a_printer_driver(&driver, 3, list[i],
7046                                                       architecture, version);
7047                         if (!W_ERROR_IS_OK(status)) {
7048                                 SAFE_FREE(list);
7049                                 SAFE_FREE(driver_info_2);
7050                                 return status;
7051                         }
7052                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7053                         free_a_printer_driver(driver, 3);
7054                 }
7055
7056                 *returned+=ndrivers;
7057                 SAFE_FREE(list);
7058         }
7059
7060         /* check the required size. */
7061         for (i=0; i<*returned; i++) {
7062                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7063                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7064         }
7065
7066         if (*needed > offered) {
7067                 result = WERR_INSUFFICIENT_BUFFER;
7068                 goto out;
7069         }
7070
7071         if (!rpcbuf_alloc_size(buffer, *needed)) {
7072                 result = WERR_NOMEM;
7073                 goto out;
7074         }
7075
7076         /* fill the buffer with the form structures */
7077         for (i=0; i<*returned; i++) {
7078                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7079                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7080         }
7081
7082 out:
7083         SAFE_FREE(driver_info_2);
7084
7085         if ( !W_ERROR_IS_OK(result) )
7086                 *returned = 0;
7087
7088         return result;
7089 }
7090
7091 /****************************************************************************
7092  Enumerates all printer drivers at level 3.
7093 ****************************************************************************/
7094
7095 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7096 {
7097         int i;
7098         int ndrivers;
7099         uint32 version;
7100         fstring *list = NULL;
7101         DRIVER_INFO_3 *driver_info_3=NULL;
7102         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7103         WERROR result = WERR_OK;
7104
7105         *returned=0;
7106
7107         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7108                 list=NULL;
7109                 ndrivers=get_ntdrivers(&list, architecture, version);
7110                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7111
7112                 if(ndrivers == -1) {
7113                         SAFE_FREE(driver_info_3);
7114                         return WERR_NOMEM;
7115                 }
7116
7117                 if(ndrivers != 0) {
7118                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7119                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7120                                 SAFE_FREE(list);
7121                                 return WERR_NOMEM;
7122                         }
7123                 }
7124
7125                 for (i=0; i<ndrivers; i++) {
7126                         WERROR status;
7127
7128                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7129                         ZERO_STRUCT(driver);
7130                         status = get_a_printer_driver(&driver, 3, list[i],
7131                                                       architecture, version);
7132                         if (!W_ERROR_IS_OK(status)) {
7133                                 SAFE_FREE(list);
7134                                 SAFE_FREE(driver_info_3);
7135                                 return status;
7136                         }
7137                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7138                         free_a_printer_driver(driver, 3);
7139                 }
7140
7141                 *returned+=ndrivers;
7142                 SAFE_FREE(list);
7143         }
7144
7145         /* check the required size. */
7146         for (i=0; i<*returned; i++) {
7147                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7148                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7149         }
7150
7151         if (*needed > offered) {
7152                 result = WERR_INSUFFICIENT_BUFFER;
7153                 goto out;
7154         }
7155
7156         if (!rpcbuf_alloc_size(buffer, *needed)) {
7157                 result = WERR_NOMEM;
7158                 goto out;
7159         }
7160
7161         /* fill the buffer with the driver structures */
7162         for (i=0; i<*returned; i++) {
7163                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7164                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7165         }
7166
7167 out:
7168         for (i=0; i<*returned; i++) {
7169                 SAFE_FREE(driver_info_3[i].dependentfiles);
7170         }
7171
7172         SAFE_FREE(driver_info_3);
7173
7174         if ( !W_ERROR_IS_OK(result) )
7175                 *returned = 0;
7176
7177         return result;
7178 }
7179
7180 /****************************************************************************
7181  Enumerates all printer drivers.
7182 ****************************************************************************/
7183
7184 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7185 {
7186         uint32 level = q_u->level;
7187         RPC_BUFFER *buffer = NULL;
7188         uint32 offered = q_u->offered;
7189         uint32 *needed = &r_u->needed;
7190         uint32 *returned = &r_u->returned;
7191         const char *cservername;
7192         fstring servername;
7193         fstring architecture;
7194
7195         /* that's an [in out] buffer */
7196
7197         if (!q_u->buffer && (offered!=0)) {
7198                 return WERR_INVALID_PARAM;
7199         }
7200
7201         if (offered > MAX_RPC_DATA_SIZE) {
7202                 return WERR_INVALID_PARAM;
7203         }
7204
7205         rpcbuf_move(q_u->buffer, &r_u->buffer);
7206         buffer = r_u->buffer;
7207
7208         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7209
7210         *needed   = 0;
7211         *returned = 0;
7212
7213         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7214         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7215
7216         cservername = canon_servername(servername);
7217
7218         if (!is_myname_or_ipaddr(cservername))
7219                 return WERR_UNKNOWN_PRINTER_DRIVER;
7220
7221         switch (level) {
7222         case 1:
7223                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7224         case 2:
7225                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7226         case 3:
7227                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7228         default:
7229                 return WERR_UNKNOWN_LEVEL;
7230         }
7231 }
7232
7233 /****************************************************************************
7234 ****************************************************************************/
7235
7236 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7237 {
7238         form->flag=list->flag;
7239         init_unistr(&form->name, list->name);
7240         form->width=list->width;
7241         form->length=list->length;
7242         form->left=list->left;
7243         form->top=list->top;
7244         form->right=list->right;
7245         form->bottom=list->bottom;
7246 }
7247
7248 /****************************************************************************
7249 ****************************************************************************/
7250
7251 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7252                                struct spoolss_FormInfo1 *form,
7253                                nt_forms_struct *list)
7254 {
7255         form->form_name         = talloc_strdup(mem_ctx, list->name);
7256         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7257
7258         form->flags             = list->flag;
7259         form->size.width        = list->width;
7260         form->size.height       = list->length;
7261         form->area.left         = list->left;
7262         form->area.top          = list->top;
7263         form->area.right        = list->right;
7264         form->area.bottom       = list->bottom;
7265
7266         return WERR_OK;
7267 }
7268
7269 /****************************************************************************
7270 ****************************************************************************/
7271
7272 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7273 {
7274         uint32 level = q_u->level;
7275         RPC_BUFFER *buffer = NULL;
7276         uint32 offered = q_u->offered;
7277         uint32 *needed = &r_u->needed;
7278         uint32 *numofforms = &r_u->numofforms;
7279         uint32 numbuiltinforms;
7280
7281         nt_forms_struct *list=NULL;
7282         nt_forms_struct *builtinlist=NULL;
7283         FORM_1 *forms_1;
7284         int buffer_size=0;
7285         int i;
7286
7287         /* that's an [in out] buffer */
7288
7289         if (!q_u->buffer && (offered!=0) ) {
7290                 return WERR_INVALID_PARAM;
7291         }
7292
7293         if (offered > MAX_RPC_DATA_SIZE) {
7294                 return WERR_INVALID_PARAM;
7295         }
7296
7297         rpcbuf_move(q_u->buffer, &r_u->buffer);
7298         buffer = r_u->buffer;
7299
7300         DEBUG(4,("_spoolss_enumforms\n"));
7301         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7302         DEBUGADD(5,("Info level [%d]\n",          level));
7303
7304         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7305         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7306         *numofforms = get_ntforms(&list);
7307         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7308         *numofforms += numbuiltinforms;
7309
7310         if (*numofforms == 0) {
7311                 SAFE_FREE(builtinlist);
7312                 SAFE_FREE(list);
7313                 return WERR_NO_MORE_ITEMS;
7314         }
7315
7316         switch (level) {
7317         case 1:
7318                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7319                         SAFE_FREE(builtinlist);
7320                         SAFE_FREE(list);
7321                         *numofforms=0;
7322                         return WERR_NOMEM;
7323                 }
7324
7325                 /* construct the list of form structures */
7326                 for (i=0; i<numbuiltinforms; i++) {
7327                         DEBUGADD(6,("Filling form number [%d]\n",i));
7328                         fill_form_1(&forms_1[i], &builtinlist[i]);
7329                 }
7330
7331                 SAFE_FREE(builtinlist);
7332
7333                 for (; i<*numofforms; i++) {
7334                         DEBUGADD(6,("Filling form number [%d]\n",i));
7335                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7336                 }
7337
7338                 SAFE_FREE(list);
7339
7340                 /* check the required size. */
7341                 for (i=0; i<numbuiltinforms; i++) {
7342                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7343                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7344                 }
7345                 for (; i<*numofforms; i++) {
7346                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7347                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7348                 }
7349
7350                 *needed=buffer_size;
7351
7352                 if (*needed > offered) {
7353                         SAFE_FREE(forms_1);
7354                         *numofforms=0;
7355                         return WERR_INSUFFICIENT_BUFFER;
7356                 }
7357
7358                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7359                         SAFE_FREE(forms_1);
7360                         *numofforms=0;
7361                         return WERR_NOMEM;
7362                 }
7363
7364                 /* fill the buffer with the form structures */
7365                 for (i=0; i<numbuiltinforms; i++) {
7366                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7367                         smb_io_form_1("", buffer, &forms_1[i], 0);
7368                 }
7369                 for (; i<*numofforms; i++) {
7370                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7371                         smb_io_form_1("", buffer, &forms_1[i], 0);
7372                 }
7373
7374                 SAFE_FREE(forms_1);
7375
7376                 return WERR_OK;
7377
7378         default:
7379                 SAFE_FREE(list);
7380                 SAFE_FREE(builtinlist);
7381                 return WERR_UNKNOWN_LEVEL;
7382         }
7383 }
7384
7385 /****************************************************************
7386  _spoolss_GetForm
7387 ****************************************************************/
7388
7389 WERROR _spoolss_GetForm(pipes_struct *p,
7390                         struct spoolss_GetForm *r)
7391 {
7392         uint32 level = r->in.level;
7393         uint32 offered = r->in.offered;
7394         uint32 *needed = r->out.needed;
7395
7396         nt_forms_struct *list=NULL;
7397         nt_forms_struct builtin_form;
7398         bool foundBuiltin;
7399         union spoolss_FormInfo info;
7400         struct spoolss_FormInfo1 form_1;
7401         int numofforms=0, i=0;
7402
7403         /* that's an [in out] buffer */
7404
7405         if (!r->in.buffer && (offered!=0)) {
7406                 return WERR_INVALID_PARAM;
7407         }
7408
7409         DEBUG(4,("_spoolss_GetForm\n"));
7410         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7411         DEBUGADD(5,("Info level [%d]\n",          level));
7412
7413         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7414         if (!foundBuiltin) {
7415                 numofforms = get_ntforms(&list);
7416                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7417
7418                 if (numofforms == 0)
7419                         return WERR_BADFID;
7420         }
7421
7422         ZERO_STRUCT(form_1);
7423
7424         switch (level) {
7425         case 1:
7426                 if (foundBuiltin) {
7427                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7428                 } else {
7429
7430                         /* Check if the requested name is in the list of form structures */
7431                         for (i=0; i<numofforms; i++) {
7432
7433                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7434                                         list[i].name, r->in.form_name));
7435
7436                                 if (strequal(r->in.form_name, list[i].name)) {
7437                                         DEBUGADD(6,("Found form %s number [%d]\n",
7438                                                 r->in.form_name, i));
7439                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7440                                         break;
7441                                 }
7442                         }
7443
7444                         SAFE_FREE(list);
7445                         if (i == numofforms) {
7446                                 return WERR_BADFID;
7447                         }
7448                 }
7449                 /* check the required size. */
7450
7451                 info.info1 = form_1;
7452
7453                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7454
7455                 if (*needed > offered) {
7456                         r->out.info = NULL;
7457                         return WERR_INSUFFICIENT_BUFFER;
7458                 }
7459
7460                 r->out.info->info1 = form_1;
7461
7462                 /* fill the buffer with the form structures */
7463                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7464                         r->in.form_name, i));
7465
7466                 return WERR_OK;
7467
7468         default:
7469                 SAFE_FREE(list);
7470                 return WERR_UNKNOWN_LEVEL;
7471         }
7472 }
7473
7474 /****************************************************************************
7475 ****************************************************************************/
7476
7477 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7478 {
7479         init_unistr(&port->port_name, name);
7480 }
7481
7482 /****************************************************************************
7483  TODO: This probably needs distinguish between TCP/IP and Local ports
7484  somehow.
7485 ****************************************************************************/
7486
7487 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7488 {
7489         init_unistr(&port->port_name, name);
7490         init_unistr(&port->monitor_name, "Local Monitor");
7491         init_unistr(&port->description, SPL_LOCAL_PORT );
7492         port->port_type=PORT_TYPE_WRITE;
7493         port->reserved=0x0;
7494 }
7495
7496
7497 /****************************************************************************
7498  wrapper around the enumer ports command
7499 ****************************************************************************/
7500
7501 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7502 {
7503         char *cmd = lp_enumports_cmd();
7504         char **qlines = NULL;
7505         char *command = NULL;
7506         int numlines;
7507         int ret;
7508         int fd;
7509
7510         *count = 0;
7511         *lines = NULL;
7512
7513         /* if no hook then just fill in the default port */
7514
7515         if ( !*cmd ) {
7516                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7517                         return WERR_NOMEM;
7518                 }
7519                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7520                         TALLOC_FREE(qlines);
7521                         return WERR_NOMEM;
7522                 }
7523                 qlines[1] = NULL;
7524                 numlines = 1;
7525         }
7526         else {
7527                 /* we have a valid enumport command */
7528
7529                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7530                 if (!command) {
7531                         return WERR_NOMEM;
7532                 }
7533
7534                 DEBUG(10,("Running [%s]\n", command));
7535                 ret = smbrun(command, &fd);
7536                 DEBUG(10,("Returned [%d]\n", ret));
7537                 TALLOC_FREE(command);
7538                 if (ret != 0) {
7539                         if (fd != -1) {
7540                                 close(fd);
7541                         }
7542                         return WERR_ACCESS_DENIED;
7543                 }
7544
7545                 numlines = 0;
7546                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7547                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7548                 close(fd);
7549         }
7550
7551         *count = numlines;
7552         *lines = qlines;
7553
7554         return WERR_OK;
7555 }
7556
7557 /****************************************************************************
7558  enumports level 1.
7559 ****************************************************************************/
7560
7561 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7562 {
7563         PORT_INFO_1 *ports=NULL;
7564         int i=0;
7565         WERROR result = WERR_OK;
7566         char **qlines = NULL;
7567         int numlines = 0;
7568
7569         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7570         if (!W_ERROR_IS_OK(result)) {
7571                 TALLOC_FREE(qlines);
7572                 return result;
7573         }
7574
7575         if(numlines) {
7576                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7577                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7578                                   win_errstr(WERR_NOMEM)));
7579                         TALLOC_FREE(qlines);
7580                         return WERR_NOMEM;
7581                 }
7582
7583                 for (i=0; i<numlines; i++) {
7584                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7585                         fill_port_1(&ports[i], qlines[i]);
7586                 }
7587         }
7588         TALLOC_FREE(qlines);
7589
7590         *returned = numlines;
7591
7592         /* check the required size. */
7593         for (i=0; i<*returned; i++) {
7594                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7595                 *needed += spoolss_size_port_info_1(&ports[i]);
7596         }
7597
7598         if (*needed > offered) {
7599                 result = WERR_INSUFFICIENT_BUFFER;
7600                 goto out;
7601         }
7602
7603         if (!rpcbuf_alloc_size(buffer, *needed)) {
7604                 result = WERR_NOMEM;
7605                 goto out;
7606         }
7607
7608         /* fill the buffer with the ports structures */
7609         for (i=0; i<*returned; i++) {
7610                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7611                 smb_io_port_1("", buffer, &ports[i], 0);
7612         }
7613
7614 out:
7615         SAFE_FREE(ports);
7616
7617         if ( !W_ERROR_IS_OK(result) )
7618                 *returned = 0;
7619
7620         return result;
7621 }
7622
7623 /****************************************************************************
7624  enumports level 2.
7625 ****************************************************************************/
7626
7627 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7628 {
7629         PORT_INFO_2 *ports=NULL;
7630         int i=0;
7631         WERROR result = WERR_OK;
7632         char **qlines = NULL;
7633         int numlines = 0;
7634
7635         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7636         if ( !W_ERROR_IS_OK(result)) {
7637                 TALLOC_FREE(qlines);
7638                 return result;
7639         }
7640
7641         if(numlines) {
7642                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7643                         TALLOC_FREE(qlines);
7644                         return WERR_NOMEM;
7645                 }
7646
7647                 for (i=0; i<numlines; i++) {
7648                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7649                         fill_port_2(&(ports[i]), qlines[i]);
7650                 }
7651         }
7652
7653         TALLOC_FREE(qlines);
7654
7655         *returned = numlines;
7656
7657         /* check the required size. */
7658         for (i=0; i<*returned; i++) {
7659                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7660                 *needed += spoolss_size_port_info_2(&ports[i]);
7661         }
7662
7663         if (*needed > offered) {
7664                 result = WERR_INSUFFICIENT_BUFFER;
7665                 goto out;
7666         }
7667
7668         if (!rpcbuf_alloc_size(buffer, *needed)) {
7669                 result = WERR_NOMEM;
7670                 goto out;
7671         }
7672
7673         /* fill the buffer with the ports structures */
7674         for (i=0; i<*returned; i++) {
7675                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7676                 smb_io_port_2("", buffer, &ports[i], 0);
7677         }
7678
7679 out:
7680         SAFE_FREE(ports);
7681
7682         if ( !W_ERROR_IS_OK(result) )
7683                 *returned = 0;
7684
7685         return result;
7686 }
7687
7688 /****************************************************************************
7689  enumports.
7690 ****************************************************************************/
7691
7692 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7693 {
7694         uint32 level = q_u->level;
7695         RPC_BUFFER *buffer = NULL;
7696         uint32 offered = q_u->offered;
7697         uint32 *needed = &r_u->needed;
7698         uint32 *returned = &r_u->returned;
7699
7700         /* that's an [in out] buffer */
7701
7702         if (!q_u->buffer && (offered!=0)) {
7703                 return WERR_INVALID_PARAM;
7704         }
7705
7706         if (offered > MAX_RPC_DATA_SIZE) {
7707                 return WERR_INVALID_PARAM;
7708         }
7709
7710         rpcbuf_move(q_u->buffer, &r_u->buffer);
7711         buffer = r_u->buffer;
7712
7713         DEBUG(4,("_spoolss_enumports\n"));
7714
7715         *returned=0;
7716         *needed=0;
7717
7718         switch (level) {
7719         case 1:
7720                 return enumports_level_1(buffer, offered, needed, returned);
7721         case 2:
7722                 return enumports_level_2(buffer, offered, needed, returned);
7723         default:
7724                 return WERR_UNKNOWN_LEVEL;
7725         }
7726 }
7727
7728 /****************************************************************************
7729 ****************************************************************************/
7730
7731 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7732                                            const char *server,
7733                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7734                                            struct spoolss_DeviceMode *devmode,
7735                                            struct security_descriptor *sec_desc,
7736                                            struct spoolss_UserLevelCtr *user_ctr,
7737                                            POLICY_HND *handle)
7738 {
7739         NT_PRINTER_INFO_LEVEL *printer = NULL;
7740         fstring name;
7741         int     snum;
7742         WERROR err = WERR_OK;
7743
7744         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7745                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7746                 return WERR_NOMEM;
7747         }
7748
7749         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7750         if (!convert_printer_info_new(info_ctr, printer)) {
7751                 free_a_printer(&printer, 2);
7752                 return WERR_NOMEM;
7753         }
7754
7755         /* check to see if the printer already exists */
7756
7757         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7758                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7759                         printer->info_2->sharename));
7760                 free_a_printer(&printer, 2);
7761                 return WERR_PRINTER_ALREADY_EXISTS;
7762         }
7763
7764         /* FIXME!!!  smbd should check to see if the driver is installed before
7765            trying to add a printer like this  --jerry */
7766
7767         if (*lp_addprinter_cmd() ) {
7768                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7769                                        printer) ) {
7770                         free_a_printer(&printer,2);
7771                         return WERR_ACCESS_DENIED;
7772                 }
7773         } else {
7774                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7775                         "smb.conf parameter \"addprinter command\" is defined. This"
7776                         "parameter must exist for this call to succeed\n",
7777                         printer->info_2->sharename ));
7778         }
7779
7780         /* use our primary netbios name since get_a_printer() will convert
7781            it to what the client expects on a case by case basis */
7782
7783         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7784              printer->info_2->sharename);
7785
7786
7787         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7788                 free_a_printer(&printer,2);
7789                 return WERR_ACCESS_DENIED;
7790         }
7791
7792         /* you must be a printer admin to add a new printer */
7793         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7794                 free_a_printer(&printer,2);
7795                 return WERR_ACCESS_DENIED;
7796         }
7797
7798         /*
7799          * Do sanity check on the requested changes for Samba.
7800          */
7801
7802         if (!check_printer_ok(printer->info_2, snum)) {
7803                 free_a_printer(&printer,2);
7804                 return WERR_INVALID_PARAM;
7805         }
7806
7807         /*
7808          * When a printer is created, the drivername bound to the printer is used
7809          * to lookup previously saved driver initialization info, which is then
7810          * bound to the new printer, simulating what happens in the Windows arch.
7811          */
7812
7813         if (!devmode)
7814         {
7815                 set_driver_init(printer, 2);
7816         }
7817         else
7818         {
7819                 /* A valid devmode was included, convert and link it
7820                 */
7821                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7822
7823                 if (!convert_devicemode_new(printer->info_2->printername,
7824                                             devmode,
7825                                             &printer->info_2->devmode))
7826                         return  WERR_NOMEM;
7827         }
7828
7829         /* write the ASCII on disk */
7830         err = mod_a_printer(printer, 2);
7831         if (!W_ERROR_IS_OK(err)) {
7832                 free_a_printer(&printer,2);
7833                 return err;
7834         }
7835
7836         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7837                 /* Handle open failed - remove addition. */
7838                 del_a_printer(printer->info_2->sharename);
7839                 free_a_printer(&printer,2);
7840                 ZERO_STRUCTP(handle);
7841                 return WERR_ACCESS_DENIED;
7842         }
7843
7844         update_c_setprinter(False);
7845         free_a_printer(&printer,2);
7846
7847         return WERR_OK;
7848 }
7849
7850 /****************************************************************
7851  _spoolss_AddPrinterEx
7852 ****************************************************************/
7853
7854 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7855                              struct spoolss_AddPrinterEx *r)
7856 {
7857         switch (r->in.info_ctr->level) {
7858         case 1:
7859                 /* we don't handle yet */
7860                 /* but I know what to do ... */
7861                 return WERR_UNKNOWN_LEVEL;
7862         case 2:
7863                 return spoolss_addprinterex_level_2(p, r->in.server,
7864                                                     r->in.info_ctr,
7865                                                     r->in.devmode_ctr->devmode,
7866                                                     r->in.secdesc_ctr->sd,
7867                                                     r->in.userlevel_ctr,
7868                                                     r->out.handle);
7869         default:
7870                 return WERR_UNKNOWN_LEVEL;
7871         }
7872 }
7873
7874 /****************************************************************
7875  _spoolss_AddPrinterDriver
7876 ****************************************************************/
7877
7878 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7879                                  struct spoolss_AddPrinterDriver *r)
7880 {
7881         uint32_t level = r->in.info_ctr->level;
7882         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7883         WERROR err = WERR_OK;
7884         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7885         fstring driver_name;
7886         uint32 version;
7887         const char *fn;
7888
7889         switch (p->hdr_req.opnum) {
7890                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7891                         fn = "_spoolss_AddPrinterDriver";
7892                         break;
7893                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7894                         fn = "_spoolss_AddPrinterDriverEx";
7895                         break;
7896                 default:
7897                         return WERR_INVALID_PARAM;
7898         }
7899
7900
7901         /* FIXME */
7902         if (level != 3 && level != 6) {
7903                 /* Clever hack from Martin Zielinski <mz@seh.de>
7904                  * to allow downgrade from level 8 (Vista).
7905                  */
7906                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7907                 return WERR_UNKNOWN_LEVEL;
7908         }
7909
7910         ZERO_STRUCT(driver);
7911
7912         if (!convert_printer_driver_info(info, &driver, level)) {
7913                 err = WERR_NOMEM;
7914                 goto done;
7915         }
7916
7917         DEBUG(5,("Cleaning driver's information\n"));
7918         err = clean_up_driver_struct(p, driver, level);
7919         if (!W_ERROR_IS_OK(err))
7920                 goto done;
7921
7922         DEBUG(5,("Moving driver to final destination\n"));
7923         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7924                                                               &err)) ) {
7925                 goto done;
7926         }
7927
7928         if (add_a_printer_driver(driver, level)!=0) {
7929                 err = WERR_ACCESS_DENIED;
7930                 goto done;
7931         }
7932
7933         switch(level) {
7934         case 3:
7935                 fstrcpy(driver_name,
7936                         driver.info_3->name ? driver.info_3->name : "");
7937                 break;
7938         case 6:
7939                 fstrcpy(driver_name,
7940                         driver.info_6->name ?  driver.info_6->name : "");
7941                 break;
7942         }
7943
7944         /*
7945          * I think this is where he DrvUpgradePrinter() hook would be
7946          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7947          * server.  Right now, we just need to send ourselves a message
7948          * to update each printer bound to this driver.   --jerry
7949          */
7950
7951         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7952                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7953                         fn, driver_name));
7954         }
7955
7956         /*
7957          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7958          * decide if the driver init data should be deleted. The rules are:
7959          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7960          *  2) delete init data only if there is no 2k/Xp driver
7961          *  3) always delete init data
7962          * The generalized rule is always use init data from the highest order driver.
7963          * It is necessary to follow the driver install by an initialization step to
7964          * finish off this process.
7965         */
7966         if (level == 3)
7967                 version = driver.info_3->cversion;
7968         else if (level == 6)
7969                 version = driver.info_6->version;
7970         else
7971                 version = -1;
7972         switch (version) {
7973                 /*
7974                  * 9x printer driver - never delete init data
7975                 */
7976                 case 0:
7977                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7978                                 fn, driver_name));
7979                         break;
7980
7981                 /*
7982                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7983                  * there is no 2k/Xp driver init data for this driver name.
7984                 */
7985                 case 2:
7986                 {
7987                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7988
7989                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7990                                 /*
7991                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7992                                 */
7993                                 if (!del_driver_init(driver_name))
7994                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7995                                                 fn, driver_name));
7996                         } else {
7997                                 /*
7998                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7999                                 */
8000                                 free_a_printer_driver(driver1,3);
8001                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
8002                                         fn, driver_name));
8003                         }
8004                 }
8005                 break;
8006
8007                 /*
8008                  * 2k or Xp printer driver - always delete init data
8009                 */
8010                 case 3:
8011                         if (!del_driver_init(driver_name))
8012                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8013                                         fn, driver_name));
8014                         break;
8015
8016                 default:
8017                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8018                         break;
8019         }
8020
8021
8022 done:
8023         free_a_printer_driver(driver, level);
8024         return err;
8025 }
8026
8027 /****************************************************************
8028  _spoolss_AddPrinterDriverEx
8029 ****************************************************************/
8030
8031 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8032                                    struct spoolss_AddPrinterDriverEx *r)
8033 {
8034         struct spoolss_AddPrinterDriver a;
8035
8036         /*
8037          * we only support the semantics of AddPrinterDriver()
8038          * i.e. only copy files that are newer than existing ones
8039          */
8040
8041         if (r->in.flags != APD_COPY_NEW_FILES) {
8042                 return WERR_ACCESS_DENIED;
8043         }
8044
8045         a.in.servername         = r->in.servername;
8046         a.in.info_ctr           = r->in.info_ctr;
8047
8048         return _spoolss_AddPrinterDriver(p, &a);
8049 }
8050
8051 /****************************************************************************
8052 ****************************************************************************/
8053
8054 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8055                                           const char *servername,
8056                                           const char *environment,
8057                                           struct spoolss_DriverDirectoryInfo1 *info1,
8058                                           uint32_t offered,
8059                                           uint32_t *needed)
8060 {
8061         char *path = NULL;
8062         const char *pservername = NULL;
8063         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8064         const char *short_archi;
8065
8066         if (environment) {
8067                 long_archi = environment;
8068         }
8069
8070         pservername = canon_servername(servername);
8071
8072         if ( !is_myname_or_ipaddr(pservername))
8073                 return WERR_INVALID_PARAM;
8074
8075         if (!(short_archi = get_short_archi(long_archi)))
8076                 return WERR_INVALID_ENVIRONMENT;
8077
8078         path = talloc_asprintf(mem_ctx,
8079                         "\\\\%s\\print$\\%s", pservername, short_archi);
8080         if (!path) {
8081                 return WERR_NOMEM;
8082         }
8083
8084         DEBUG(4,("printer driver directory: [%s]\n", path));
8085
8086         info1->directory_name = path;
8087
8088         *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
8089
8090         if (*needed > offered) {
8091                 talloc_free(path);
8092                 ZERO_STRUCTP(info1);
8093                 return WERR_INSUFFICIENT_BUFFER;
8094         }
8095
8096         return WERR_OK;
8097 }
8098
8099 /****************************************************************
8100  _spoolss_GetPrinterDriverDirectory
8101 ****************************************************************/
8102
8103 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8104                                           struct spoolss_GetPrinterDriverDirectory *r)
8105 {
8106         WERROR werror;
8107
8108         /* that's an [in out] buffer */
8109
8110         if (!r->in.buffer && (r->in.offered != 0)) {
8111                 return WERR_INVALID_PARAM;
8112         }
8113
8114         if (r->in.offered > MAX_RPC_DATA_SIZE) {
8115                 return WERR_INVALID_PARAM;
8116         }
8117
8118         DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
8119
8120         *r->out.needed = 0;
8121
8122         switch (r->in.level) {
8123         case 1:
8124                 werror = getprinterdriverdir_level_1(p->mem_ctx,
8125                                                      r->in.server,
8126                                                      r->in.environment,
8127                                                      &r->out.info->info1,
8128                                                      r->in.offered,
8129                                                      r->out.needed);
8130                 if (!W_ERROR_IS_OK(werror)) {
8131                         TALLOC_FREE(r->out.info);
8132                 }
8133                 break;
8134         default:
8135                 return WERR_UNKNOWN_LEVEL;
8136         }
8137
8138         return werror;
8139 }
8140
8141 /****************************************************************************
8142 ****************************************************************************/
8143
8144 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8145 {
8146         POLICY_HND *handle = &q_u->handle;
8147         uint32 idx               = q_u->index;
8148         uint32 in_value_len      = q_u->valuesize;
8149         uint32 in_data_len       = q_u->datasize;
8150         uint32 *out_max_value_len = &r_u->valuesize;
8151         uint16 **out_value       = &r_u->value;
8152         uint32 *out_value_len    = &r_u->realvaluesize;
8153         uint32 *out_type         = &r_u->type;
8154         uint32 *out_max_data_len = &r_u->datasize;
8155         uint8  **data_out        = &r_u->data;
8156         uint32 *out_data_len     = &r_u->realdatasize;
8157
8158         NT_PRINTER_INFO_LEVEL *printer = NULL;
8159
8160         uint32          biggest_valuesize;
8161         uint32          biggest_datasize;
8162         uint32          data_len;
8163         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8164         int             snum;
8165         WERROR          result;
8166         REGISTRY_VALUE  *val = NULL;
8167         NT_PRINTER_DATA *p_data;
8168         int             i, key_index, num_values;
8169         int             name_length;
8170
8171         *out_type = 0;
8172
8173         *out_max_data_len = 0;
8174         *data_out         = NULL;
8175         *out_data_len     = 0;
8176
8177         DEBUG(5,("spoolss_enumprinterdata\n"));
8178
8179         if (!Printer) {
8180                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8181                 return WERR_BADFID;
8182         }
8183
8184         if (!get_printer_snum(p,handle, &snum, NULL))
8185                 return WERR_BADFID;
8186
8187         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8188         if (!W_ERROR_IS_OK(result))
8189                 return result;
8190
8191         p_data = printer->info_2->data;
8192         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8193
8194         result = WERR_OK;
8195
8196         /*
8197          * The NT machine wants to know the biggest size of value and data
8198          *
8199          * cf: MSDN EnumPrinterData remark section
8200          */
8201
8202         if ( !in_value_len && !in_data_len && (key_index != -1) )
8203         {
8204                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8205
8206                 biggest_valuesize = 0;
8207                 biggest_datasize  = 0;
8208
8209                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8210
8211                 for ( i=0; i<num_values; i++ )
8212                 {
8213                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8214
8215                         name_length = strlen(val->valuename);
8216                         if ( strlen(val->valuename) > biggest_valuesize )
8217                                 biggest_valuesize = name_length;
8218
8219                         if ( val->size > biggest_datasize )
8220                                 biggest_datasize = val->size;
8221
8222                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8223                                 biggest_datasize));
8224                 }
8225
8226                 /* the value is an UNICODE string but real_value_size is the length
8227                    in bytes including the trailing 0 */
8228
8229                 *out_value_len = 2 * (1+biggest_valuesize);
8230                 *out_data_len  = biggest_datasize;
8231
8232                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8233
8234                 goto done;
8235         }
8236
8237         /*
8238          * the value len is wrong in NT sp3
8239          * that's the number of bytes not the number of unicode chars
8240          */
8241
8242         if ( key_index != -1 )
8243                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8244
8245         if ( !val )
8246         {
8247
8248                 /* out_value should default to "" or else NT4 has
8249                    problems unmarshalling the response */
8250
8251                 *out_max_value_len=(in_value_len/sizeof(uint16));
8252
8253                 if (in_value_len) {
8254                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8255                         {
8256                                 result = WERR_NOMEM;
8257                                 goto done;
8258                         }
8259                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8260                 } else {
8261                         *out_value=NULL;
8262                         *out_value_len = 0;
8263                 }
8264
8265                 /* the data is counted in bytes */
8266
8267                 *out_max_data_len = in_data_len;
8268                 *out_data_len     = in_data_len;
8269
8270                 /* only allocate when given a non-zero data_len */
8271
8272                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8273                 {
8274                         result = WERR_NOMEM;
8275                         goto done;
8276                 }
8277
8278                 result = WERR_NO_MORE_ITEMS;
8279         }
8280         else
8281         {
8282                 /*
8283                  * the value is:
8284                  * - counted in bytes in the request
8285                  * - counted in UNICODE chars in the max reply
8286                  * - counted in bytes in the real size
8287                  *
8288                  * take a pause *before* coding not *during* coding
8289                  */
8290
8291                 /* name */
8292                 *out_max_value_len=(in_value_len/sizeof(uint16));
8293                 if (in_value_len) {
8294                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8295                         {
8296                                 result = WERR_NOMEM;
8297                                 goto done;
8298                         }
8299
8300                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8301                 } else {
8302                         *out_value = NULL;
8303                         *out_value_len = 0;
8304                 }
8305
8306                 /* type */
8307
8308                 *out_type = regval_type( val );
8309
8310                 /* data - counted in bytes */
8311
8312                 *out_max_data_len = in_data_len;
8313                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8314                 {
8315                         result = WERR_NOMEM;
8316                         goto done;
8317                 }
8318                 data_len = regval_size(val);
8319                 if ( *data_out && data_len )
8320                         memcpy( *data_out, regval_data_p(val), data_len );
8321                 *out_data_len = data_len;
8322         }
8323
8324 done:
8325         free_a_printer(&printer, 2);
8326         return result;
8327 }
8328
8329 /****************************************************************************
8330 ****************************************************************************/
8331
8332 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8333 {
8334         POLICY_HND              *handle = &q_u->handle;
8335         UNISTR2                 *value = &q_u->value;
8336         uint32                  type = q_u->type;
8337         uint8                   *data = q_u->data;
8338         uint32                  real_len = q_u->real_len;
8339
8340         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8341         int                     snum=0;
8342         WERROR                  status = WERR_OK;
8343         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8344         fstring                 valuename;
8345
8346         DEBUG(5,("spoolss_setprinterdata\n"));
8347
8348         if (!Printer) {
8349                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8350                 return WERR_BADFID;
8351         }
8352
8353         if ( Printer->printer_type == SPLHND_SERVER ) {
8354                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8355                 return WERR_INVALID_PARAM;
8356         }
8357
8358         if (!get_printer_snum(p,handle, &snum, NULL))
8359                 return WERR_BADFID;
8360
8361         /*
8362          * Access check : NT returns "access denied" if you make a
8363          * SetPrinterData call without the necessary privildge.
8364          * we were originally returning OK if nothing changed
8365          * which made Win2k issue **a lot** of SetPrinterData
8366          * when connecting to a printer  --jerry
8367          */
8368
8369         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8370         {
8371                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8372                 status = WERR_ACCESS_DENIED;
8373                 goto done;
8374         }
8375
8376         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8377         if (!W_ERROR_IS_OK(status))
8378                 return status;
8379
8380         unistr2_to_ascii(valuename, value, sizeof(valuename));
8381
8382         /*
8383          * When client side code sets a magic printer data key, detect it and save
8384          * the current printer data and the magic key's data (its the DEVMODE) for
8385          * future printer/driver initializations.
8386          */
8387         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8388         {
8389                 /* Set devmode and printer initialization info */
8390                 status = save_driver_init( printer, 2, data, real_len );
8391
8392                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8393         }
8394         else
8395         {
8396         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8397                                         type, data, real_len );
8398                 if ( W_ERROR_IS_OK(status) )
8399                         status = mod_a_printer(printer, 2);
8400         }
8401
8402 done:
8403         free_a_printer(&printer, 2);
8404
8405         return status;
8406 }
8407
8408 /****************************************************************
8409  _spoolss_ResetPrinter
8410 ****************************************************************/
8411
8412 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8413                              struct spoolss_ResetPrinter *r)
8414 {
8415         POLICY_HND      *handle = r->in.handle;
8416         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8417         int             snum;
8418
8419         DEBUG(5,("_spoolss_ResetPrinter\n"));
8420
8421         /*
8422          * All we do is to check to see if the handle and queue is valid.
8423          * This call really doesn't mean anything to us because we only
8424          * support RAW printing.   --jerry
8425          */
8426
8427         if (!Printer) {
8428                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8429                         OUR_HANDLE(handle)));
8430                 return WERR_BADFID;
8431         }
8432
8433         if (!get_printer_snum(p,handle, &snum, NULL))
8434                 return WERR_BADFID;
8435
8436
8437         /* blindly return success */
8438         return WERR_OK;
8439 }
8440
8441 /****************************************************************
8442  _spoolss_DeletePrinterData
8443 ****************************************************************/
8444
8445 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8446                                   struct spoolss_DeletePrinterData *r)
8447 {
8448         POLICY_HND      *handle = r->in.handle;
8449         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8450         int             snum=0;
8451         WERROR          status = WERR_OK;
8452         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8453
8454         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8455
8456         if (!Printer) {
8457                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8458                         OUR_HANDLE(handle)));
8459                 return WERR_BADFID;
8460         }
8461
8462         if (!get_printer_snum(p, handle, &snum, NULL))
8463                 return WERR_BADFID;
8464
8465         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8466                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8467                         "printer properties change denied by handle\n"));
8468                 return WERR_ACCESS_DENIED;
8469         }
8470
8471         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8472         if (!W_ERROR_IS_OK(status))
8473                 return status;
8474
8475         if (!r->in.value_name) {
8476                 free_a_printer(&printer, 2);
8477                 return WERR_NOMEM;
8478         }
8479
8480         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8481                                         r->in.value_name );
8482
8483         if ( W_ERROR_IS_OK(status) )
8484                 mod_a_printer( printer, 2 );
8485
8486         free_a_printer(&printer, 2);
8487
8488         return status;
8489 }
8490
8491 /****************************************************************
8492  _spoolss_AddForm
8493 ****************************************************************/
8494
8495 WERROR _spoolss_AddForm(pipes_struct *p,
8496                         struct spoolss_AddForm *r)
8497 {
8498         POLICY_HND *handle = r->in.handle;
8499         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8500         nt_forms_struct tmpForm;
8501         int snum;
8502         WERROR status = WERR_OK;
8503         NT_PRINTER_INFO_LEVEL *printer = NULL;
8504
8505         int count=0;
8506         nt_forms_struct *list=NULL;
8507         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8508
8509         DEBUG(5,("_spoolss_AddForm\n"));
8510
8511         if (!Printer) {
8512                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8513                         OUR_HANDLE(handle)));
8514                 return WERR_BADFID;
8515         }
8516
8517
8518         /* forms can be added on printer of on the print server handle */
8519
8520         if ( Printer->printer_type == SPLHND_PRINTER )
8521         {
8522                 if (!get_printer_snum(p,handle, &snum, NULL))
8523                         return WERR_BADFID;
8524
8525                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8526                 if (!W_ERROR_IS_OK(status))
8527                         goto done;
8528         }
8529
8530         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8531                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8532                 status = WERR_ACCESS_DENIED;
8533                 goto done;
8534         }
8535
8536         /* can't add if builtin */
8537
8538         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8539                 status = WERR_FILE_EXISTS;
8540                 goto done;
8541         }
8542
8543         count = get_ntforms(&list);
8544
8545         if(!add_a_form(&list, form, &count)) {
8546                 status =  WERR_NOMEM;
8547                 goto done;
8548         }
8549
8550         write_ntforms(&list, count);
8551
8552         /*
8553          * ChangeID must always be set if this is a printer
8554          */
8555
8556         if ( Printer->printer_type == SPLHND_PRINTER )
8557                 status = mod_a_printer(printer, 2);
8558
8559 done:
8560         if ( printer )
8561                 free_a_printer(&printer, 2);
8562         SAFE_FREE(list);
8563
8564         return status;
8565 }
8566
8567 /****************************************************************
8568  _spoolss_DeleteForm
8569 ****************************************************************/
8570
8571 WERROR _spoolss_DeleteForm(pipes_struct *p,
8572                            struct spoolss_DeleteForm *r)
8573 {
8574         POLICY_HND *handle = r->in.handle;
8575         const char *form_name = r->in.form_name;
8576         nt_forms_struct tmpForm;
8577         int count=0;
8578         nt_forms_struct *list=NULL;
8579         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8580         int snum;
8581         WERROR status = WERR_OK;
8582         NT_PRINTER_INFO_LEVEL *printer = NULL;
8583
8584         DEBUG(5,("_spoolss_DeleteForm\n"));
8585
8586         if (!Printer) {
8587                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8588                         OUR_HANDLE(handle)));
8589                 return WERR_BADFID;
8590         }
8591
8592         /* forms can be deleted on printer of on the print server handle */
8593
8594         if ( Printer->printer_type == SPLHND_PRINTER )
8595         {
8596                 if (!get_printer_snum(p,handle, &snum, NULL))
8597                         return WERR_BADFID;
8598
8599                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8600                 if (!W_ERROR_IS_OK(status))
8601                         goto done;
8602         }
8603
8604         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8605                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8606                 status = WERR_ACCESS_DENIED;
8607                 goto done;
8608         }
8609
8610         /* can't delete if builtin */
8611
8612         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8613                 status = WERR_INVALID_PARAM;
8614                 goto done;
8615         }
8616
8617         count = get_ntforms(&list);
8618
8619         if ( !delete_a_form(&list, form_name, &count, &status ))
8620                 goto done;
8621
8622         /*
8623          * ChangeID must always be set if this is a printer
8624          */
8625
8626         if ( Printer->printer_type == SPLHND_PRINTER )
8627                 status = mod_a_printer(printer, 2);
8628
8629 done:
8630         if ( printer )
8631                 free_a_printer(&printer, 2);
8632         SAFE_FREE(list);
8633
8634         return status;
8635 }
8636
8637 /****************************************************************
8638  _spoolss_SetForm
8639 ****************************************************************/
8640
8641 WERROR _spoolss_SetForm(pipes_struct *p,
8642                         struct spoolss_SetForm *r)
8643 {
8644         POLICY_HND *handle = r->in.handle;
8645         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8646         nt_forms_struct tmpForm;
8647         int snum;
8648         WERROR status = WERR_OK;
8649         NT_PRINTER_INFO_LEVEL *printer = NULL;
8650
8651         int count=0;
8652         nt_forms_struct *list=NULL;
8653         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8654
8655         DEBUG(5,("_spoolss_SetForm\n"));
8656
8657         if (!Printer) {
8658                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8659                         OUR_HANDLE(handle)));
8660                 return WERR_BADFID;
8661         }
8662
8663         /* forms can be modified on printer of on the print server handle */
8664
8665         if ( Printer->printer_type == SPLHND_PRINTER )
8666         {
8667                 if (!get_printer_snum(p,handle, &snum, NULL))
8668                         return WERR_BADFID;
8669
8670                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8671                 if (!W_ERROR_IS_OK(status))
8672                         goto done;
8673         }
8674
8675         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8676                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8677                 status = WERR_ACCESS_DENIED;
8678                 goto done;
8679         }
8680
8681         /* can't set if builtin */
8682         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8683                 status = WERR_INVALID_PARAM;
8684                 goto done;
8685         }
8686
8687         count = get_ntforms(&list);
8688         update_a_form(&list, form, count);
8689         write_ntforms(&list, count);
8690
8691         /*
8692          * ChangeID must always be set if this is a printer
8693          */
8694
8695         if ( Printer->printer_type == SPLHND_PRINTER )
8696                 status = mod_a_printer(printer, 2);
8697
8698
8699 done:
8700         if ( printer )
8701                 free_a_printer(&printer, 2);
8702         SAFE_FREE(list);
8703
8704         return status;
8705 }
8706
8707 /****************************************************************************
8708  enumprintprocessors level 1.
8709 ****************************************************************************/
8710
8711 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8712 {
8713         PRINTPROCESSOR_1 *info_1=NULL;
8714         WERROR result = WERR_OK;
8715
8716         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8717                 return WERR_NOMEM;
8718
8719         (*returned) = 0x1;
8720
8721         init_unistr(&info_1->name, "winprint");
8722
8723         *needed += spoolss_size_printprocessor_info_1(info_1);
8724
8725         if (*needed > offered) {
8726                 result = WERR_INSUFFICIENT_BUFFER;
8727                 goto out;
8728         }
8729
8730         if (!rpcbuf_alloc_size(buffer, *needed)) {
8731                 result = WERR_NOMEM;
8732                 goto out;
8733         }
8734
8735         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8736
8737 out:
8738         SAFE_FREE(info_1);
8739
8740         if ( !W_ERROR_IS_OK(result) )
8741                 *returned = 0;
8742
8743         return result;
8744 }
8745
8746 /****************************************************************************
8747 ****************************************************************************/
8748
8749 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8750 {
8751         uint32 level = q_u->level;
8752         RPC_BUFFER *buffer = NULL;
8753         uint32 offered = q_u->offered;
8754         uint32 *needed = &r_u->needed;
8755         uint32 *returned = &r_u->returned;
8756
8757         /* that's an [in out] buffer */
8758
8759         if (!q_u->buffer && (offered!=0)) {
8760                 return WERR_INVALID_PARAM;
8761         }
8762
8763         if (offered > MAX_RPC_DATA_SIZE) {
8764                 return WERR_INVALID_PARAM;
8765         }
8766
8767         rpcbuf_move(q_u->buffer, &r_u->buffer);
8768         buffer = r_u->buffer;
8769
8770         DEBUG(5,("spoolss_enumprintprocessors\n"));
8771
8772         /*
8773          * Enumerate the print processors ...
8774          *
8775          * Just reply with "winprint", to keep NT happy
8776          * and I can use my nice printer checker.
8777          */
8778
8779         *returned=0;
8780         *needed=0;
8781
8782         switch (level) {
8783         case 1:
8784                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8785         default:
8786                 return WERR_UNKNOWN_LEVEL;
8787         }
8788 }
8789
8790 /****************************************************************************
8791  enumprintprocdatatypes level 1.
8792 ****************************************************************************/
8793
8794 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8795 {
8796         PRINTPROCDATATYPE_1 *info_1=NULL;
8797         WERROR result = WERR_OK;
8798
8799         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8800                 return WERR_NOMEM;
8801
8802         (*returned) = 0x1;
8803
8804         init_unistr(&info_1->name, "RAW");
8805
8806         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8807
8808         if (*needed > offered) {
8809                 result = WERR_INSUFFICIENT_BUFFER;
8810                 goto out;
8811         }
8812
8813         if (!rpcbuf_alloc_size(buffer, *needed)) {
8814                 result = WERR_NOMEM;
8815                 goto out;
8816         }
8817
8818         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8819
8820 out:
8821         SAFE_FREE(info_1);
8822
8823         if ( !W_ERROR_IS_OK(result) )
8824                 *returned = 0;
8825
8826         return result;
8827 }
8828
8829 /****************************************************************************
8830 ****************************************************************************/
8831
8832 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8833 {
8834         uint32 level = q_u->level;
8835         RPC_BUFFER *buffer = NULL;
8836         uint32 offered = q_u->offered;
8837         uint32 *needed = &r_u->needed;
8838         uint32 *returned = &r_u->returned;
8839
8840         /* that's an [in out] buffer */
8841
8842         if (!q_u->buffer && (offered!=0)) {
8843                 return WERR_INVALID_PARAM;
8844         }
8845
8846         if (offered > MAX_RPC_DATA_SIZE) {
8847                 return WERR_INVALID_PARAM;
8848         }
8849
8850         rpcbuf_move(q_u->buffer, &r_u->buffer);
8851         buffer = r_u->buffer;
8852
8853         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8854
8855         *returned=0;
8856         *needed=0;
8857
8858         switch (level) {
8859         case 1:
8860                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8861         default:
8862                 return WERR_UNKNOWN_LEVEL;
8863         }
8864 }
8865
8866 /****************************************************************************
8867  enumprintmonitors level 1.
8868 ****************************************************************************/
8869
8870 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8871 {
8872         PRINTMONITOR_1 *info_1;
8873         WERROR result = WERR_OK;
8874         int i;
8875
8876         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8877                 return WERR_NOMEM;
8878
8879         *returned = 2;
8880
8881         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8882         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8883
8884         for ( i=0; i<*returned; i++ ) {
8885                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8886         }
8887
8888         if (*needed > offered) {
8889                 result = WERR_INSUFFICIENT_BUFFER;
8890                 goto out;
8891         }
8892
8893         if (!rpcbuf_alloc_size(buffer, *needed)) {
8894                 result = WERR_NOMEM;
8895                 goto out;
8896         }
8897
8898         for ( i=0; i<*returned; i++ ) {
8899                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8900         }
8901
8902 out:
8903         SAFE_FREE(info_1);
8904
8905         if ( !W_ERROR_IS_OK(result) )
8906                 *returned = 0;
8907
8908         return result;
8909 }
8910
8911 /****************************************************************************
8912  enumprintmonitors level 2.
8913 ****************************************************************************/
8914
8915 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8916 {
8917         PRINTMONITOR_2 *info_2;
8918         WERROR result = WERR_OK;
8919         int i;
8920
8921         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8922                 return WERR_NOMEM;
8923
8924         *returned = 2;
8925
8926         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8927         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8928         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8929
8930         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8931         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8932         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8933
8934         for ( i=0; i<*returned; i++ ) {
8935                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8936         }
8937
8938         if (*needed > offered) {
8939                 result = WERR_INSUFFICIENT_BUFFER;
8940                 goto out;
8941         }
8942
8943         if (!rpcbuf_alloc_size(buffer, *needed)) {
8944                 result = WERR_NOMEM;
8945                 goto out;
8946         }
8947
8948         for ( i=0; i<*returned; i++ ) {
8949                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8950         }
8951
8952 out:
8953         SAFE_FREE(info_2);
8954
8955         if ( !W_ERROR_IS_OK(result) )
8956                 *returned = 0;
8957
8958         return result;
8959 }
8960
8961 /****************************************************************************
8962 ****************************************************************************/
8963
8964 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8965 {
8966         uint32 level = q_u->level;
8967         RPC_BUFFER *buffer = NULL;
8968         uint32 offered = q_u->offered;
8969         uint32 *needed = &r_u->needed;
8970         uint32 *returned = &r_u->returned;
8971
8972         /* that's an [in out] buffer */
8973
8974         if (!q_u->buffer && (offered!=0)) {
8975                 return WERR_INVALID_PARAM;
8976         }
8977
8978         if (offered > MAX_RPC_DATA_SIZE) {
8979                 return WERR_INVALID_PARAM;
8980         }
8981
8982         rpcbuf_move(q_u->buffer, &r_u->buffer);
8983         buffer = r_u->buffer;
8984
8985         DEBUG(5,("spoolss_enumprintmonitors\n"));
8986
8987         /*
8988          * Enumerate the print monitors ...
8989          *
8990          * Just reply with "Local Port", to keep NT happy
8991          * and I can use my nice printer checker.
8992          */
8993
8994         *returned=0;
8995         *needed=0;
8996
8997         switch (level) {
8998         case 1:
8999                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9000         case 2:
9001                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9002         default:
9003                 return WERR_UNKNOWN_LEVEL;
9004         }
9005 }
9006
9007 /****************************************************************************
9008 ****************************************************************************/
9009
9010 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9011                              NT_PRINTER_INFO_LEVEL *ntprinter,
9012                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9013                              uint32 *needed)
9014 {
9015         int i=0;
9016         bool found=False;
9017         JOB_INFO_1 *info_1=NULL;
9018         WERROR result = WERR_OK;
9019
9020         info_1=SMB_MALLOC_P(JOB_INFO_1);
9021
9022         if (info_1 == NULL) {
9023                 return WERR_NOMEM;
9024         }
9025
9026         for (i=0; i<count && found==False; i++) {
9027                 if ((*queue)[i].job==(int)jobid)
9028                         found=True;
9029         }
9030
9031         if (found==False) {
9032                 SAFE_FREE(info_1);
9033                 /* NT treats not found as bad param... yet another bad choice */
9034                 return WERR_INVALID_PARAM;
9035         }
9036
9037         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9038
9039         *needed += spoolss_size_job_info_1(info_1);
9040
9041         if (*needed > offered) {
9042                 result = WERR_INSUFFICIENT_BUFFER;
9043                 goto out;
9044         }
9045
9046         if (!rpcbuf_alloc_size(buffer, *needed)) {
9047                 result = WERR_NOMEM;
9048                 goto out;
9049         }
9050
9051         smb_io_job_info_1("", buffer, info_1, 0);
9052
9053 out:
9054         SAFE_FREE(info_1);
9055
9056         return result;
9057 }
9058
9059 /****************************************************************************
9060 ****************************************************************************/
9061
9062 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9063                              NT_PRINTER_INFO_LEVEL *ntprinter,
9064                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9065                              uint32 *needed)
9066 {
9067         int             i = 0;
9068         bool            found = False;
9069         JOB_INFO_2      *info_2;
9070         WERROR          result;
9071         DEVICEMODE      *devmode = NULL;
9072         NT_DEVICEMODE   *nt_devmode = NULL;
9073
9074         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9075                 return WERR_NOMEM;
9076
9077         ZERO_STRUCTP(info_2);
9078
9079         for ( i=0; i<count && found==False; i++ )
9080         {
9081                 if ((*queue)[i].job == (int)jobid)
9082                         found = True;
9083         }
9084
9085         if ( !found ) {
9086                 /* NT treats not found as bad param... yet another bad
9087                    choice */
9088                 result = WERR_INVALID_PARAM;
9089                 goto done;
9090         }
9091
9092         /*
9093          * if the print job does not have a DEVMODE associated with it,
9094          * just use the one for the printer. A NULL devicemode is not
9095          *  a failure condition
9096          */
9097
9098         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9099                 devmode = construct_dev_mode(lp_const_servicename(snum));
9100         else {
9101                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9102                         ZERO_STRUCTP( devmode );
9103                         convert_nt_devicemode( devmode, nt_devmode );
9104                 }
9105         }
9106
9107         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9108
9109         *needed += spoolss_size_job_info_2(info_2);
9110
9111         if (*needed > offered) {
9112                 result = WERR_INSUFFICIENT_BUFFER;
9113                 goto done;
9114         }
9115
9116         if (!rpcbuf_alloc_size(buffer, *needed)) {
9117                 result = WERR_NOMEM;
9118                 goto done;
9119         }
9120
9121         smb_io_job_info_2("", buffer, info_2, 0);
9122
9123         result = WERR_OK;
9124
9125  done:
9126         /* Cleanup allocated memory */
9127
9128         free_job_info_2(info_2);        /* Also frees devmode */
9129         SAFE_FREE(info_2);
9130
9131         return result;
9132 }
9133
9134 /****************************************************************************
9135 ****************************************************************************/
9136
9137 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9138 {
9139         POLICY_HND *handle = &q_u->handle;
9140         uint32 jobid = q_u->jobid;
9141         uint32 level = q_u->level;
9142         RPC_BUFFER *buffer = NULL;
9143         uint32 offered = q_u->offered;
9144         uint32 *needed = &r_u->needed;
9145         WERROR          wstatus = WERR_OK;
9146         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9147         int snum;
9148         int count;
9149         print_queue_struct      *queue = NULL;
9150         print_status_struct prt_status;
9151
9152         /* that's an [in out] buffer */
9153
9154         if (!q_u->buffer && (offered!=0)) {
9155                 return WERR_INVALID_PARAM;
9156         }
9157
9158         if (offered > MAX_RPC_DATA_SIZE) {
9159                 return WERR_INVALID_PARAM;
9160         }
9161
9162         rpcbuf_move(q_u->buffer, &r_u->buffer);
9163         buffer = r_u->buffer;
9164
9165         DEBUG(5,("spoolss_getjob\n"));
9166
9167         *needed = 0;
9168
9169         if (!get_printer_snum(p, handle, &snum, NULL))
9170                 return WERR_BADFID;
9171
9172         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9173         if ( !W_ERROR_IS_OK(wstatus) )
9174                 return wstatus;
9175
9176         count = print_queue_status(snum, &queue, &prt_status);
9177
9178         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9179                      count, prt_status.status, prt_status.message));
9180
9181         switch ( level ) {
9182         case 1:
9183                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9184                                 buffer, offered, needed);
9185                         break;
9186         case 2:
9187                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9188                                 buffer, offered, needed);
9189                         break;
9190         default:
9191                         wstatus = WERR_UNKNOWN_LEVEL;
9192                         break;
9193         }
9194
9195         SAFE_FREE(queue);
9196         free_a_printer( &ntprinter, 2 );
9197
9198         return wstatus;
9199 }
9200
9201 /****************************************************************
9202  _spoolss_GetPrinterDataEx
9203
9204  From MSDN documentation of GetPrinterDataEx: pass request
9205  to GetPrinterData if key is "PrinterDriverData".
9206 ****************************************************************/
9207
9208 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9209                                  struct spoolss_GetPrinterDataEx *r)
9210 {
9211         POLICY_HND      *handle = r->in.handle;
9212         uint8           *data = NULL;
9213         const char      *keyname = r->in.key_name;
9214         const char      *valuename = r->in.value_name;
9215
9216         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9217
9218         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9219         int                     snum = 0;
9220         WERROR                  status = WERR_OK;
9221
9222         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9223
9224         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9225                 keyname, valuename));
9226
9227         /* in case of problem, return some default values */
9228
9229         *r->out.needed  = 0;
9230         *r->out.type    = 0;
9231
9232         if (!Printer) {
9233                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9234                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9235                 status = WERR_BADFID;
9236                 goto done;
9237         }
9238
9239         /* Is the handle to a printer or to the server? */
9240
9241         if (Printer->printer_type == SPLHND_SERVER) {
9242                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9243                         "Not implemented for server handles yet\n"));
9244                 status = WERR_INVALID_PARAM;
9245                 goto done;
9246         }
9247
9248         if ( !get_printer_snum(p,handle, &snum, NULL) )
9249                 return WERR_BADFID;
9250
9251         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9252         if ( !W_ERROR_IS_OK(status) )
9253                 goto done;
9254
9255         /* check to see if the keyname is valid */
9256         if ( !strlen(keyname) ) {
9257                 status = WERR_INVALID_PARAM;
9258                 goto done;
9259         }
9260
9261         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9262                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9263                         "Invalid keyname [%s]\n", keyname ));
9264                 free_a_printer( &printer, 2 );
9265                 status = WERR_BADFILE;
9266                 goto done;
9267         }
9268
9269         /* When given a new keyname, we should just create it */
9270
9271         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9272                                      r->out.type, &data, r->out.needed,
9273                                      r->in.offered );
9274
9275         if (*r->out.needed > r->in.offered) {
9276                 status = WERR_MORE_DATA;
9277         }
9278
9279         if (W_ERROR_IS_OK(status)) {
9280                 memcpy(r->out.buffer, data, r->in.offered);
9281         }
9282
9283 done:
9284         if ( printer )
9285         free_a_printer( &printer, 2 );
9286
9287         return status;
9288 }
9289
9290 /****************************************************************
9291  _spoolss_SetPrinterDataEx
9292 ****************************************************************/
9293
9294 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9295                                  struct spoolss_SetPrinterDataEx *r)
9296 {
9297         POLICY_HND              *handle = r->in.handle;
9298         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9299         int                     snum = 0;
9300         WERROR                  status = WERR_OK;
9301         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9302         char                    *oid_string;
9303
9304         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9305
9306         /* From MSDN documentation of SetPrinterDataEx: pass request to
9307            SetPrinterData if key is "PrinterDriverData" */
9308
9309         if (!Printer) {
9310                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9311                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9312                 return WERR_BADFID;
9313         }
9314
9315         if ( Printer->printer_type == SPLHND_SERVER ) {
9316                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9317                         "Not implemented for server handles yet\n"));
9318                 return WERR_INVALID_PARAM;
9319         }
9320
9321         if ( !get_printer_snum(p,handle, &snum, NULL) )
9322                 return WERR_BADFID;
9323
9324         /*
9325          * Access check : NT returns "access denied" if you make a
9326          * SetPrinterData call without the necessary privildge.
9327          * we were originally returning OK if nothing changed
9328          * which made Win2k issue **a lot** of SetPrinterData
9329          * when connecting to a printer  --jerry
9330          */
9331
9332         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9333         {
9334                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9335                         "change denied by handle access permissions\n"));
9336                 return WERR_ACCESS_DENIED;
9337         }
9338
9339         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9340         if (!W_ERROR_IS_OK(status))
9341                 return status;
9342
9343         /* check for OID in valuename */
9344
9345         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9346         {
9347                 *oid_string = '\0';
9348                 oid_string++;
9349         }
9350
9351         /* save the registry data */
9352
9353         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9354                                      r->in.type, r->in.buffer, r->in.offered );
9355
9356         if ( W_ERROR_IS_OK(status) )
9357         {
9358                 /* save the OID if one was specified */
9359                 if ( oid_string ) {
9360                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9361                                 r->in.key_name, SPOOL_OID_KEY);
9362                         if (!str) {
9363                                 return WERR_NOMEM;
9364                         }
9365
9366                         /*
9367                          * I'm not checking the status here on purpose.  Don't know
9368                          * if this is right, but I'm returning the status from the
9369                          * previous set_printer_dataex() call.  I have no idea if
9370                          * this is right.    --jerry
9371                          */
9372
9373                         set_printer_dataex( printer, str, r->in.value_name,
9374                                             REG_SZ, (uint8 *)oid_string,
9375                                             strlen(oid_string)+1 );
9376                 }
9377
9378                 status = mod_a_printer(printer, 2);
9379         }
9380
9381         free_a_printer(&printer, 2);
9382
9383         return status;
9384 }
9385
9386 /****************************************************************
9387  _spoolss_DeletePrinterDataEx
9388 ****************************************************************/
9389
9390 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9391                                     struct spoolss_DeletePrinterDataEx *r)
9392 {
9393         POLICY_HND      *handle = r->in.handle;
9394         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9395         int             snum=0;
9396         WERROR          status = WERR_OK;
9397         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9398
9399         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9400
9401         if (!Printer) {
9402                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9403                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9404                 return WERR_BADFID;
9405         }
9406
9407         if (!get_printer_snum(p, handle, &snum, NULL))
9408                 return WERR_BADFID;
9409
9410         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9411                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9412                         "printer properties change denied by handle\n"));
9413                 return WERR_ACCESS_DENIED;
9414         }
9415
9416         if (!r->in.value_name || !r->in.key_name) {
9417                 return WERR_NOMEM;
9418         }
9419
9420         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9421         if (!W_ERROR_IS_OK(status))
9422                 return status;
9423
9424         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9425
9426         if ( W_ERROR_IS_OK(status) )
9427                 mod_a_printer( printer, 2 );
9428
9429         free_a_printer(&printer, 2);
9430
9431         return status;
9432 }
9433
9434 /********************************************************************
9435  * spoolss_enumprinterkey
9436  ********************************************************************/
9437
9438
9439 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9440 {
9441         fstring         key;
9442         fstring         *keynames = NULL;
9443         uint16          *enumkeys = NULL;
9444         int             num_keys;
9445         int             printerkey_len;
9446         POLICY_HND      *handle = &q_u->handle;
9447         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9448         NT_PRINTER_DATA *data;
9449         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9450         int             snum = 0;
9451         WERROR          status = WERR_BADFILE;
9452
9453
9454         DEBUG(4,("_spoolss_enumprinterkey\n"));
9455
9456         if (!Printer) {
9457                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9458                 return WERR_BADFID;
9459         }
9460
9461         if ( !get_printer_snum(p,handle, &snum, NULL) )
9462                 return WERR_BADFID;
9463
9464         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9465         if (!W_ERROR_IS_OK(status))
9466                 return status;
9467
9468         /* get the list of subkey names */
9469
9470         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9471         data = printer->info_2->data;
9472
9473         num_keys = get_printer_subkeys( data, key, &keynames );
9474
9475         if ( num_keys == -1 ) {
9476                 status = WERR_BADFILE;
9477                 goto done;
9478         }
9479
9480         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9481
9482         r_u->needed = printerkey_len*2;
9483
9484         if ( q_u->size < r_u->needed ) {
9485                 status = WERR_MORE_DATA;
9486                 goto done;
9487         }
9488
9489         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9490                 status = WERR_NOMEM;
9491                 goto done;
9492         }
9493
9494         status = WERR_OK;
9495
9496         if ( q_u->size < r_u->needed )
9497                 status = WERR_MORE_DATA;
9498
9499 done:
9500         free_a_printer( &printer, 2 );
9501         SAFE_FREE( keynames );
9502
9503         return status;
9504 }
9505
9506 /****************************************************************
9507  _spoolss_DeletePrinterKey
9508 ****************************************************************/
9509
9510 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9511                                  struct spoolss_DeletePrinterKey *r)
9512 {
9513         POLICY_HND              *handle = r->in.handle;
9514         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9515         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9516         int                     snum=0;
9517         WERROR                  status;
9518
9519         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9520
9521         if (!Printer) {
9522                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9523                         OUR_HANDLE(handle)));
9524                 return WERR_BADFID;
9525         }
9526
9527         /* if keyname == NULL, return error */
9528
9529         if ( !r->in.key_name )
9530                 return WERR_INVALID_PARAM;
9531
9532         if (!get_printer_snum(p, handle, &snum, NULL))
9533                 return WERR_BADFID;
9534
9535         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9536                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9537                         "printer properties change denied by handle\n"));
9538                 return WERR_ACCESS_DENIED;
9539         }
9540
9541         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9542         if (!W_ERROR_IS_OK(status))
9543                 return status;
9544
9545         /* delete the key and all subneys */
9546
9547         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9548
9549         if ( W_ERROR_IS_OK(status) )
9550                 status = mod_a_printer(printer, 2);
9551
9552         free_a_printer( &printer, 2 );
9553
9554         return status;
9555 }
9556
9557
9558 /********************************************************************
9559  * spoolss_enumprinterdataex
9560  ********************************************************************/
9561
9562 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9563 {
9564         POLICY_HND      *handle = &q_u->handle;
9565         uint32          in_size = q_u->size;
9566         uint32          num_entries,
9567                         needed;
9568         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9569         PRINTER_ENUM_VALUES     *enum_values = NULL;
9570         NT_PRINTER_DATA         *p_data;
9571         fstring         key;
9572         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9573         int             snum;
9574         WERROR          result;
9575         int             key_index;
9576         int             i;
9577         REGISTRY_VALUE  *val;
9578         char            *value_name;
9579         uint32          data_len;
9580
9581
9582         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9583
9584         if (!Printer) {
9585                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9586                 return WERR_BADFID;
9587         }
9588
9589         /*
9590          * first check for a keyname of NULL or "".  Win2k seems to send
9591          * this a lot and we should send back WERR_INVALID_PARAM
9592          * no need to spend time looking up the printer in this case.
9593          * --jerry
9594          */
9595
9596         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9597         if ( !strlen(key) ) {
9598                 result = WERR_INVALID_PARAM;
9599                 goto done;
9600         }
9601
9602         /* get the printer off of disk */
9603
9604         if (!get_printer_snum(p,handle, &snum, NULL))
9605                 return WERR_BADFID;
9606
9607         ZERO_STRUCT(printer);
9608         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9609         if (!W_ERROR_IS_OK(result))
9610                 return result;
9611
9612         /* now look for a match on the key name */
9613
9614         p_data = printer->info_2->data;
9615
9616         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9617         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9618         {
9619                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9620                 result = WERR_INVALID_PARAM;
9621                 goto done;
9622         }
9623
9624         result = WERR_OK;
9625         needed = 0;
9626
9627         /* allocate the memory for the array of pointers -- if necessary */
9628
9629         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9630         if ( num_entries )
9631         {
9632                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9633                 {
9634                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9635                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9636                         result = WERR_NOMEM;
9637                         goto done;
9638                 }
9639
9640                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9641         }
9642
9643         /*
9644          * loop through all params and build the array to pass
9645          * back to the  client
9646          */
9647
9648         for ( i=0; i<num_entries; i++ )
9649         {
9650                 /* lookup the registry value */
9651
9652                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9653                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9654
9655                 /* copy the data */
9656
9657                 value_name = regval_name( val );
9658                 init_unistr( &enum_values[i].valuename, value_name );
9659                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9660                 enum_values[i].type      = regval_type( val );
9661
9662                 data_len = regval_size( val );
9663                 if ( data_len ) {
9664                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9665                         {
9666                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9667                                         data_len ));
9668                                 result = WERR_NOMEM;
9669                                 goto done;
9670                         }
9671                 }
9672                 enum_values[i].data_len = data_len;
9673
9674                 /* keep track of the size of the array in bytes */
9675
9676                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9677         }
9678
9679         /* housekeeping information in the reply */
9680
9681         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9682          * the hand marshalled container size is a multiple
9683          * of 4 bytes for RPC alignment.
9684          */
9685
9686         if (needed % 4) {
9687                 needed += 4-(needed % 4);
9688         }
9689
9690         r_u->needed     = needed;
9691         r_u->returned   = num_entries;
9692
9693         if (needed > in_size) {
9694                 result = WERR_MORE_DATA;
9695                 goto done;
9696         }
9697
9698         /* copy data into the reply */
9699
9700         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9701            response buffer size is != the offered buffer size
9702
9703                 r_u->ctr.size           = r_u->needed;
9704         */
9705         r_u->ctr.size           = in_size;
9706
9707         r_u->ctr.size_of_array  = r_u->returned;
9708         r_u->ctr.values         = enum_values;
9709
9710 done:
9711         if ( printer )
9712         free_a_printer(&printer, 2);
9713
9714         return result;
9715 }
9716
9717 /****************************************************************************
9718 ****************************************************************************/
9719
9720 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9721                                                  const char *servername,
9722                                                  const char *environment,
9723                                                  struct spoolss_PrintProcessorDirectoryInfo1 *info1,
9724                                                  uint32_t offered,
9725                                                  uint32_t *needed)
9726 {
9727         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
9728         const char *short_archi;
9729
9730         if (environment) {
9731                 long_archi = environment;
9732         }
9733
9734         short_archi = get_short_archi(long_archi);
9735         if (!short_archi) {
9736                 return WERR_INVALID_ENVIRONMENT;
9737         }
9738
9739         /* I think this should look like this - gd
9740         info1->directory_name = talloc_asprintf(mem_ctx,
9741                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\%s", short_archi);
9742         */
9743         info1->directory_name = talloc_strdup(mem_ctx,
9744                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9745
9746         if (!info1->directory_name) {
9747                 return WERR_NOMEM;
9748         }
9749
9750         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(info1, NULL, 0);
9751
9752         if (*needed > offered) {
9753                 return WERR_INSUFFICIENT_BUFFER;
9754         }
9755
9756         return WERR_OK;
9757 }
9758
9759 /****************************************************************
9760  _spoolss_GetPrintProcessorDirectory
9761 ****************************************************************/
9762
9763 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9764                                            struct spoolss_GetPrintProcessorDirectory *r)
9765 {
9766         WERROR result;
9767
9768         /* that's an [in out] buffer */
9769
9770         if (!r->in.buffer && (r->in.offered != 0)) {
9771                 return WERR_INVALID_PARAM;
9772         }
9773
9774         if (r->in.offered > MAX_RPC_DATA_SIZE) {
9775                 return WERR_INVALID_PARAM;
9776         }
9777
9778         DEBUG(5,("_spoolss_GetPrintProcessorDirectory\n"));
9779
9780         *r->out.needed = 0;
9781
9782         switch (r->in.level) {
9783         case 1:
9784                 result = getprintprocessordirectory_level_1(p->mem_ctx,
9785                                                             r->in.server,
9786                                                             r->in.environment,
9787                                                             &r->out.info->info1,
9788                                                             r->in.offered,
9789                                                             r->out.needed);
9790                 if (!W_ERROR_IS_OK(result)) {
9791                         TALLOC_FREE(r->out.info);
9792                 }
9793                 break;
9794         default:
9795                 result = WERR_UNKNOWN_LEVEL;
9796         }
9797
9798         return result;
9799 }
9800
9801 /*******************************************************************
9802  ********************************************************************/
9803
9804 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9805                                const char *dllname)
9806 {
9807         enum ndr_err_code ndr_err;
9808         struct spoolss_MonitorUi ui;
9809
9810         ui.dll_name = dllname;
9811
9812         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9813                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9814         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9815                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9816         }
9817         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9818 }
9819
9820 /*******************************************************************
9821  Streams the monitor UI DLL name in UNICODE
9822 *******************************************************************/
9823
9824 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9825                                NT_USER_TOKEN *token, DATA_BLOB *in,
9826                                DATA_BLOB *out, uint32_t *needed)
9827 {
9828         const char *dllname = "tcpmonui.dll";
9829
9830         *needed = (strlen(dllname)+1) * 2;
9831
9832         if (out->length < *needed) {
9833                 return WERR_INSUFFICIENT_BUFFER;
9834         }
9835
9836         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9837                 return WERR_NOMEM;
9838         }
9839
9840         return WERR_OK;
9841 }
9842
9843 /*******************************************************************
9844  ********************************************************************/
9845
9846 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9847                              struct spoolss_PortData1 *port1,
9848                              const DATA_BLOB *buf)
9849 {
9850         enum ndr_err_code ndr_err;
9851         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9852                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9853         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9854                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9855         }
9856         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9857 }
9858
9859 /*******************************************************************
9860  ********************************************************************/
9861
9862 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9863                              struct spoolss_PortData2 *port2,
9864                              const DATA_BLOB *buf)
9865 {
9866         enum ndr_err_code ndr_err;
9867         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9868                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9869         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9870                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9871         }
9872         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9873 }
9874
9875 /*******************************************************************
9876  Create a new TCP/IP port
9877 *******************************************************************/
9878
9879 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9880                              NT_USER_TOKEN *token, DATA_BLOB *in,
9881                              DATA_BLOB *out, uint32_t *needed)
9882 {
9883         struct spoolss_PortData1 port1;
9884         struct spoolss_PortData2 port2;
9885         char *device_uri = NULL;
9886         uint32_t version;
9887
9888         const char *portname;
9889         const char *hostaddress;
9890         const char *queue;
9891         uint32_t port_number;
9892         uint32_t protocol;
9893
9894         /* peek for spoolss_PortData version */
9895
9896         if (!in || (in->length < (128 + 4))) {
9897                 return WERR_GENERAL_FAILURE;
9898         }
9899
9900         version = IVAL(in->data, 128);
9901
9902         switch (version) {
9903                 case 1:
9904                         ZERO_STRUCT(port1);
9905
9906                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9907                                 return WERR_NOMEM;
9908                         }
9909
9910                         portname        = port1.portname;
9911                         hostaddress     = port1.hostaddress;
9912                         queue           = port1.queue;
9913                         protocol        = port1.protocol;
9914                         port_number     = port1.port_number;
9915
9916                         break;
9917                 case 2:
9918                         ZERO_STRUCT(port2);
9919
9920                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9921                                 return WERR_NOMEM;
9922                         }
9923
9924                         portname        = port2.portname;
9925                         hostaddress     = port2.hostaddress;
9926                         queue           = port2.queue;
9927                         protocol        = port2.protocol;
9928                         port_number     = port2.port_number;
9929
9930                         break;
9931                 default:
9932                         DEBUG(1,("xcvtcp_addport: "
9933                                 "unknown version of port_data: %d\n", version));
9934                         return WERR_UNKNOWN_PORT;
9935         }
9936
9937         /* create the device URI and call the add_port_hook() */
9938
9939         switch (protocol) {
9940         case PROTOCOL_RAWTCP_TYPE:
9941                 device_uri = talloc_asprintf(mem_ctx,
9942                                 "socket://%s:%d/", hostaddress,
9943                                 port_number);
9944                 break;
9945
9946         case PROTOCOL_LPR_TYPE:
9947                 device_uri = talloc_asprintf(mem_ctx,
9948                         "lpr://%s/%s", hostaddress, queue );
9949                 break;
9950
9951         default:
9952                 return WERR_UNKNOWN_PORT;
9953         }
9954
9955         if (!device_uri) {
9956                 return WERR_NOMEM;
9957         }
9958
9959         return add_port_hook(mem_ctx, token, portname, device_uri);
9960 }
9961
9962 /*******************************************************************
9963 *******************************************************************/
9964
9965 struct xcv_api_table xcvtcp_cmds[] = {
9966         { "MonitorUI",  xcvtcp_monitorui },
9967         { "AddPort",    xcvtcp_addport},
9968         { NULL,         NULL }
9969 };
9970
9971 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9972                                      NT_USER_TOKEN *token, const char *command,
9973                                      DATA_BLOB *inbuf,
9974                                      DATA_BLOB *outbuf,
9975                                      uint32_t *needed )
9976 {
9977         int i;
9978
9979         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9980
9981         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9982                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9983                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9984         }
9985
9986         return WERR_BADFUNC;
9987 }
9988
9989 /*******************************************************************
9990 *******************************************************************/
9991 #if 0   /* don't support management using the "Local Port" monitor */
9992
9993 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9994                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9995                                  DATA_BLOB *out, uint32_t *needed)
9996 {
9997         const char *dllname = "localui.dll";
9998
9999         *needed = (strlen(dllname)+1) * 2;
10000
10001         if (out->length < *needed) {
10002                 return WERR_INSUFFICIENT_BUFFER;
10003         }
10004
10005         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10006                 return WERR_NOMEM;
10007         }
10008
10009         return WERR_OK;
10010 }
10011
10012 /*******************************************************************
10013 *******************************************************************/
10014
10015 struct xcv_api_table xcvlocal_cmds[] = {
10016         { "MonitorUI",  xcvlocal_monitorui },
10017         { NULL,         NULL }
10018 };
10019 #else
10020 struct xcv_api_table xcvlocal_cmds[] = {
10021         { NULL,         NULL }
10022 };
10023 #endif
10024
10025
10026
10027 /*******************************************************************
10028 *******************************************************************/
10029
10030 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10031                                        NT_USER_TOKEN *token, const char *command,
10032                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10033                                        uint32_t *needed)
10034 {
10035         int i;
10036
10037         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10038
10039         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10040                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10041                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10042         }
10043         return WERR_BADFUNC;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_XcvData
10048 ****************************************************************/
10049
10050 WERROR _spoolss_XcvData(pipes_struct *p,
10051                         struct spoolss_XcvData *r)
10052 {
10053         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10054         DATA_BLOB out_data;
10055         WERROR werror;
10056
10057         if (!Printer) {
10058                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10059                         OUR_HANDLE(r->in.handle)));
10060                 return WERR_BADFID;
10061         }
10062
10063         /* Has to be a handle to the TCP/IP port monitor */
10064
10065         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10066                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10067                 return WERR_BADFID;
10068         }
10069
10070         /* requires administrative access to the server */
10071
10072         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10073                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10074                 return WERR_ACCESS_DENIED;
10075         }
10076
10077         /* Allocate the outgoing buffer */
10078
10079         if (r->in.out_data_size) {
10080                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10081                 if (out_data.data == NULL) {
10082                         return WERR_NOMEM;
10083                 }
10084         }
10085
10086         switch ( Printer->printer_type ) {
10087         case SPLHND_PORTMON_TCP:
10088                 werror = process_xcvtcp_command(p->mem_ctx,
10089                                                 p->server_info->ptok,
10090                                                 r->in.function_name,
10091                                                 &r->in.in_data, &out_data,
10092                                                 r->out.needed);
10093                 break;
10094         case SPLHND_PORTMON_LOCAL:
10095                 werror = process_xcvlocal_command(p->mem_ctx,
10096                                                   p->server_info->ptok,
10097                                                   r->in.function_name,
10098                                                   &r->in.in_data, &out_data,
10099                                                   r->out.needed);
10100                 break;
10101         default:
10102                 werror = WERR_INVALID_PRINT_MONITOR;
10103         }
10104
10105         if (!W_ERROR_IS_OK(werror)) {
10106                 return werror;
10107         }
10108
10109         *r->out.status_code = 0;
10110
10111         memcpy(r->out.out_data, out_data.data, out_data.length);
10112
10113         return WERR_OK;
10114 }
10115
10116 /****************************************************************
10117  _spoolss_AddPrintProcessor
10118 ****************************************************************/
10119
10120 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10121                                   struct spoolss_AddPrintProcessor *r)
10122 {
10123         /* for now, just indicate success and ignore the add.  We'll
10124            automatically set the winprint processor for printer
10125            entries later.  Used to debug the LexMark Optra S 1855 PCL
10126            driver --jerry */
10127
10128         return WERR_OK;
10129 }
10130
10131 /****************************************************************
10132  _spoolss_EnumPrinters
10133 ****************************************************************/
10134
10135 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10136                              struct spoolss_EnumPrinters *r)
10137 {
10138         p->rng_fault_state = true;
10139         return WERR_NOT_SUPPORTED;
10140 }
10141
10142 /****************************************************************
10143  _spoolss_GetJob
10144 ****************************************************************/
10145
10146 WERROR _spoolss_GetJob(pipes_struct *p,
10147                        struct spoolss_GetJob *r)
10148 {
10149         p->rng_fault_state = true;
10150         return WERR_NOT_SUPPORTED;
10151 }
10152
10153 /****************************************************************
10154  _spoolss_EnumJobs
10155 ****************************************************************/
10156
10157 WERROR _spoolss_EnumJobs(pipes_struct *p,
10158                          struct spoolss_EnumJobs *r)
10159 {
10160         p->rng_fault_state = true;
10161         return WERR_NOT_SUPPORTED;
10162 }
10163
10164 /****************************************************************
10165  _spoolss_AddPrinter
10166 ****************************************************************/
10167
10168 WERROR _spoolss_AddPrinter(pipes_struct *p,
10169                            struct spoolss_AddPrinter *r)
10170 {
10171         p->rng_fault_state = true;
10172         return WERR_NOT_SUPPORTED;
10173 }
10174
10175 /****************************************************************
10176  _spoolss_GetPrinter
10177 ****************************************************************/
10178
10179 WERROR _spoolss_GetPrinter(pipes_struct *p,
10180                            struct spoolss_GetPrinter *r)
10181 {
10182         p->rng_fault_state = true;
10183         return WERR_NOT_SUPPORTED;
10184 }
10185
10186 /****************************************************************
10187  _spoolss_EnumPrinterDrivers
10188 ****************************************************************/
10189
10190 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10191                                    struct spoolss_EnumPrinterDrivers *r)
10192 {
10193         p->rng_fault_state = true;
10194         return WERR_NOT_SUPPORTED;
10195 }
10196
10197 /****************************************************************
10198  _spoolss_GetPrinterDriver
10199 ****************************************************************/
10200
10201 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10202                                  struct spoolss_GetPrinterDriver *r)
10203 {
10204         p->rng_fault_state = true;
10205         return WERR_NOT_SUPPORTED;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_EnumPrintProcessors
10210 ****************************************************************/
10211
10212 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10213                                     struct spoolss_EnumPrintProcessors *r)
10214 {
10215         p->rng_fault_state = true;
10216         return WERR_NOT_SUPPORTED;
10217 }
10218
10219 /****************************************************************
10220  _spoolss_ReadPrinter
10221 ****************************************************************/
10222
10223 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10224                             struct spoolss_ReadPrinter *r)
10225 {
10226         p->rng_fault_state = true;
10227         return WERR_NOT_SUPPORTED;
10228 }
10229
10230 /****************************************************************
10231  _spoolss_GetPrinterData
10232 ****************************************************************/
10233
10234 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10235                                struct spoolss_GetPrinterData *r)
10236 {
10237         p->rng_fault_state = true;
10238         return WERR_NOT_SUPPORTED;
10239 }
10240
10241 /****************************************************************
10242  _spoolss_SetPrinterData
10243 ****************************************************************/
10244
10245 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10246                                struct spoolss_SetPrinterData *r)
10247 {
10248         p->rng_fault_state = true;
10249         return WERR_NOT_SUPPORTED;
10250 }
10251
10252 /****************************************************************
10253  _spoolss_WaitForPrinterChange
10254 ****************************************************************/
10255
10256 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10257                                      struct spoolss_WaitForPrinterChange *r)
10258 {
10259         p->rng_fault_state = true;
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_EnumForms
10265 ****************************************************************/
10266
10267 WERROR _spoolss_EnumForms(pipes_struct *p,
10268                           struct spoolss_EnumForms *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_EnumPorts
10276 ****************************************************************/
10277
10278 WERROR _spoolss_EnumPorts(pipes_struct *p,
10279                           struct spoolss_EnumPorts *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_EnumMonitors
10287 ****************************************************************/
10288
10289 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10290                              struct spoolss_EnumMonitors *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_AddPort
10298 ****************************************************************/
10299
10300 WERROR _spoolss_AddPort(pipes_struct *p,
10301                         struct spoolss_AddPort *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_ConfigurePort
10309 ****************************************************************/
10310
10311 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10312                               struct spoolss_ConfigurePort *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_DeletePort
10320 ****************************************************************/
10321
10322 WERROR _spoolss_DeletePort(pipes_struct *p,
10323                            struct spoolss_DeletePort *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }
10328
10329 /****************************************************************
10330  _spoolss_CreatePrinterIC
10331 ****************************************************************/
10332
10333 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10334                                 struct spoolss_CreatePrinterIC *r)
10335 {
10336         p->rng_fault_state = true;
10337         return WERR_NOT_SUPPORTED;
10338 }
10339
10340 /****************************************************************
10341  _spoolss_PlayGDIScriptOnPrinterIC
10342 ****************************************************************/
10343
10344 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10345                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10346 {
10347         p->rng_fault_state = true;
10348         return WERR_NOT_SUPPORTED;
10349 }
10350
10351 /****************************************************************
10352  _spoolss_DeletePrinterIC
10353 ****************************************************************/
10354
10355 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10356                                 struct spoolss_DeletePrinterIC *r)
10357 {
10358         p->rng_fault_state = true;
10359         return WERR_NOT_SUPPORTED;
10360 }
10361
10362 /****************************************************************
10363  _spoolss_AddPrinterConnection
10364 ****************************************************************/
10365
10366 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10367                                      struct spoolss_AddPrinterConnection *r)
10368 {
10369         p->rng_fault_state = true;
10370         return WERR_NOT_SUPPORTED;
10371 }
10372
10373 /****************************************************************
10374  _spoolss_DeletePrinterConnection
10375 ****************************************************************/
10376
10377 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10378                                         struct spoolss_DeletePrinterConnection *r)
10379 {
10380         p->rng_fault_state = true;
10381         return WERR_NOT_SUPPORTED;
10382 }
10383
10384 /****************************************************************
10385  _spoolss_PrinterMessageBox
10386 ****************************************************************/
10387
10388 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10389                                   struct spoolss_PrinterMessageBox *r)
10390 {
10391         p->rng_fault_state = true;
10392         return WERR_NOT_SUPPORTED;
10393 }
10394
10395 /****************************************************************
10396  _spoolss_AddMonitor
10397 ****************************************************************/
10398
10399 WERROR _spoolss_AddMonitor(pipes_struct *p,
10400                            struct spoolss_AddMonitor *r)
10401 {
10402         p->rng_fault_state = true;
10403         return WERR_NOT_SUPPORTED;
10404 }
10405
10406 /****************************************************************
10407  _spoolss_DeleteMonitor
10408 ****************************************************************/
10409
10410 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10411                               struct spoolss_DeleteMonitor *r)
10412 {
10413         p->rng_fault_state = true;
10414         return WERR_NOT_SUPPORTED;
10415 }
10416
10417 /****************************************************************
10418  _spoolss_DeletePrintProcessor
10419 ****************************************************************/
10420
10421 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10422                                      struct spoolss_DeletePrintProcessor *r)
10423 {
10424         p->rng_fault_state = true;
10425         return WERR_NOT_SUPPORTED;
10426 }
10427
10428 /****************************************************************
10429  _spoolss_AddPrintProvidor
10430 ****************************************************************/
10431
10432 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10433                                  struct spoolss_AddPrintProvidor *r)
10434 {
10435         p->rng_fault_state = true;
10436         return WERR_NOT_SUPPORTED;
10437 }
10438
10439 /****************************************************************
10440  _spoolss_DeletePrintProvidor
10441 ****************************************************************/
10442
10443 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10444                                     struct spoolss_DeletePrintProvidor *r)
10445 {
10446         p->rng_fault_state = true;
10447         return WERR_NOT_SUPPORTED;
10448 }
10449
10450 /****************************************************************
10451  _spoolss_EnumPrintProcDataTypes
10452 ****************************************************************/
10453
10454 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10455                                        struct spoolss_EnumPrintProcDataTypes *r)
10456 {
10457         p->rng_fault_state = true;
10458         return WERR_NOT_SUPPORTED;
10459 }
10460
10461 /****************************************************************
10462  _spoolss_GetPrinterDriver2
10463 ****************************************************************/
10464
10465 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10466                                   struct spoolss_GetPrinterDriver2 *r)
10467 {
10468         p->rng_fault_state = true;
10469         return WERR_NOT_SUPPORTED;
10470 }
10471
10472 /****************************************************************
10473  _spoolss_FindFirstPrinterChangeNotification
10474 ****************************************************************/
10475
10476 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10477                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10478 {
10479         p->rng_fault_state = true;
10480         return WERR_NOT_SUPPORTED;
10481 }
10482
10483 /****************************************************************
10484  _spoolss_FindNextPrinterChangeNotification
10485 ****************************************************************/
10486
10487 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10488                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10489 {
10490         p->rng_fault_state = true;
10491         return WERR_NOT_SUPPORTED;
10492 }
10493
10494 /****************************************************************
10495  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10496 ****************************************************************/
10497
10498 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10499                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10500 {
10501         p->rng_fault_state = true;
10502         return WERR_NOT_SUPPORTED;
10503 }
10504
10505 /****************************************************************
10506  _spoolss_ReplyOpenPrinter
10507 ****************************************************************/
10508
10509 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10510                                  struct spoolss_ReplyOpenPrinter *r)
10511 {
10512         p->rng_fault_state = true;
10513         return WERR_NOT_SUPPORTED;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_RouterReplyPrinter
10518 ****************************************************************/
10519
10520 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10521                                    struct spoolss_RouterReplyPrinter *r)
10522 {
10523         p->rng_fault_state = true;
10524         return WERR_NOT_SUPPORTED;
10525 }
10526
10527 /****************************************************************
10528  _spoolss_ReplyClosePrinter
10529 ****************************************************************/
10530
10531 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10532                                   struct spoolss_ReplyClosePrinter *r)
10533 {
10534         p->rng_fault_state = true;
10535         return WERR_NOT_SUPPORTED;
10536 }
10537
10538 /****************************************************************
10539  _spoolss_AddPortEx
10540 ****************************************************************/
10541
10542 WERROR _spoolss_AddPortEx(pipes_struct *p,
10543                           struct spoolss_AddPortEx *r)
10544 {
10545         p->rng_fault_state = true;
10546         return WERR_NOT_SUPPORTED;
10547 }
10548
10549 /****************************************************************
10550  _spoolss_RouterFindFirstPrinterChangeNotification
10551 ****************************************************************/
10552
10553 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10554                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10555 {
10556         p->rng_fault_state = true;
10557         return WERR_NOT_SUPPORTED;
10558 }
10559
10560 /****************************************************************
10561  _spoolss_SpoolerInit
10562 ****************************************************************/
10563
10564 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10565                             struct spoolss_SpoolerInit *r)
10566 {
10567         p->rng_fault_state = true;
10568         return WERR_NOT_SUPPORTED;
10569 }
10570
10571 /****************************************************************
10572  _spoolss_ResetPrinterEx
10573 ****************************************************************/
10574
10575 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10576                                struct spoolss_ResetPrinterEx *r)
10577 {
10578         p->rng_fault_state = true;
10579         return WERR_NOT_SUPPORTED;
10580 }
10581
10582 /****************************************************************
10583  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10584 ****************************************************************/
10585
10586 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10587                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10588 {
10589         p->rng_fault_state = true;
10590         return WERR_NOT_SUPPORTED;
10591 }
10592
10593 /****************************************************************
10594  _spoolss_RouterReplyPrinterEx
10595 ****************************************************************/
10596
10597 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10598                                      struct spoolss_RouterReplyPrinterEx *r)
10599 {
10600         p->rng_fault_state = true;
10601         return WERR_NOT_SUPPORTED;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_44
10606 ****************************************************************/
10607
10608 WERROR _spoolss_44(pipes_struct *p,
10609                    struct spoolss_44 *r)
10610 {
10611         p->rng_fault_state = true;
10612         return WERR_NOT_SUPPORTED;
10613 }
10614
10615 /****************************************************************
10616  _spoolss_47
10617 ****************************************************************/
10618
10619 WERROR _spoolss_47(pipes_struct *p,
10620                    struct spoolss_47 *r)
10621 {
10622         p->rng_fault_state = true;
10623         return WERR_NOT_SUPPORTED;
10624 }
10625
10626 /****************************************************************
10627  _spoolss_EnumPrinterData
10628 ****************************************************************/
10629
10630 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10631                                 struct spoolss_EnumPrinterData *r)
10632 {
10633         p->rng_fault_state = true;
10634         return WERR_NOT_SUPPORTED;
10635 }
10636
10637 /****************************************************************
10638  _spoolss_4a
10639 ****************************************************************/
10640
10641 WERROR _spoolss_4a(pipes_struct *p,
10642                    struct spoolss_4a *r)
10643 {
10644         p->rng_fault_state = true;
10645         return WERR_NOT_SUPPORTED;
10646 }
10647
10648 /****************************************************************
10649  _spoolss_4b
10650 ****************************************************************/
10651
10652 WERROR _spoolss_4b(pipes_struct *p,
10653                    struct spoolss_4b *r)
10654 {
10655         p->rng_fault_state = true;
10656         return WERR_NOT_SUPPORTED;
10657 }
10658
10659 /****************************************************************
10660  _spoolss_4c
10661 ****************************************************************/
10662
10663 WERROR _spoolss_4c(pipes_struct *p,
10664                    struct spoolss_4c *r)
10665 {
10666         p->rng_fault_state = true;
10667         return WERR_NOT_SUPPORTED;
10668 }
10669
10670 /****************************************************************
10671  _spoolss_EnumPrinterDataEx
10672 ****************************************************************/
10673
10674 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10675                                   struct spoolss_EnumPrinterDataEx *r)
10676 {
10677         p->rng_fault_state = true;
10678         return WERR_NOT_SUPPORTED;
10679 }
10680
10681 /****************************************************************
10682  _spoolss_EnumPrinterKey
10683 ****************************************************************/
10684
10685 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10686                                struct spoolss_EnumPrinterKey *r)
10687 {
10688         p->rng_fault_state = true;
10689         return WERR_NOT_SUPPORTED;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_53
10694 ****************************************************************/
10695
10696 WERROR _spoolss_53(pipes_struct *p,
10697                    struct spoolss_53 *r)
10698 {
10699         p->rng_fault_state = true;
10700         return WERR_NOT_SUPPORTED;
10701 }
10702
10703 /****************************************************************
10704  _spoolss_55
10705 ****************************************************************/
10706
10707 WERROR _spoolss_55(pipes_struct *p,
10708                    struct spoolss_55 *r)
10709 {
10710         p->rng_fault_state = true;
10711         return WERR_NOT_SUPPORTED;
10712 }
10713
10714 /****************************************************************
10715  _spoolss_56
10716 ****************************************************************/
10717
10718 WERROR _spoolss_56(pipes_struct *p,
10719                    struct spoolss_56 *r)
10720 {
10721         p->rng_fault_state = true;
10722         return WERR_NOT_SUPPORTED;
10723 }
10724
10725 /****************************************************************
10726  _spoolss_57
10727 ****************************************************************/
10728
10729 WERROR _spoolss_57(pipes_struct *p,
10730                    struct spoolss_57 *r)
10731 {
10732         p->rng_fault_state = true;
10733         return WERR_NOT_SUPPORTED;
10734 }
10735
10736 /****************************************************************
10737  _spoolss_5a
10738 ****************************************************************/
10739
10740 WERROR _spoolss_5a(pipes_struct *p,
10741                    struct spoolss_5a *r)
10742 {
10743         p->rng_fault_state = true;
10744         return WERR_NOT_SUPPORTED;
10745 }
10746
10747 /****************************************************************
10748  _spoolss_5b
10749 ****************************************************************/
10750
10751 WERROR _spoolss_5b(pipes_struct *p,
10752                    struct spoolss_5b *r)
10753 {
10754         p->rng_fault_state = true;
10755         return WERR_NOT_SUPPORTED;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_5c
10760 ****************************************************************/
10761
10762 WERROR _spoolss_5c(pipes_struct *p,
10763                    struct spoolss_5c *r)
10764 {
10765         p->rng_fault_state = true;
10766         return WERR_NOT_SUPPORTED;
10767 }
10768
10769 /****************************************************************
10770  _spoolss_5d
10771 ****************************************************************/
10772
10773 WERROR _spoolss_5d(pipes_struct *p,
10774                    struct spoolss_5d *r)
10775 {
10776         p->rng_fault_state = true;
10777         return WERR_NOT_SUPPORTED;
10778 }
10779
10780 /****************************************************************
10781  _spoolss_5e
10782 ****************************************************************/
10783
10784 WERROR _spoolss_5e(pipes_struct *p,
10785                    struct spoolss_5e *r)
10786 {
10787         p->rng_fault_state = true;
10788         return WERR_NOT_SUPPORTED;
10789 }
10790
10791 /****************************************************************
10792  _spoolss_5f
10793 ****************************************************************/
10794
10795 WERROR _spoolss_5f(pipes_struct *p,
10796                    struct spoolss_5f *r)
10797 {
10798         p->rng_fault_state = true;
10799         return WERR_NOT_SUPPORTED;
10800 }
10801