s3-spoolss: use pidl for _spoolss_SetJob.
[vlendec/samba-autobuild/.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) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *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 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679                              SPOOL_NOTIFY_INFO_DATA *data,
680                              TALLOC_CTX *mem_ctx)
681 {
682         data->notify_data.value[0] = msg->notify.value[0];
683         data->notify_data.value[1] = 0;
684 }
685
686 static void notify_string(struct spoolss_notify_msg *msg,
687                           SPOOL_NOTIFY_INFO_DATA *data,
688                           TALLOC_CTX *mem_ctx)
689 {
690         UNISTR2 unistr;
691
692         /* The length of the message includes the trailing \0 */
693
694         init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695
696         data->notify_data.data.length = msg->len * 2;
697         data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698
699         if (!data->notify_data.data.string) {
700                 data->notify_data.data.length = 0;
701                 return;
702         }
703
704         memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 }
706
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708                                SPOOL_NOTIFY_INFO_DATA *data,
709                                TALLOC_CTX *mem_ctx)
710 {
711         SYSTEMTIME systime;
712         prs_struct ps;
713
714         if (msg->len != sizeof(time_t)) {
715                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
716                           msg->len));
717                 return;
718         }
719
720         if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721                 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722                 return;
723         }
724
725         if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726                 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
727                 prs_mem_free(&ps);
728                 return;
729         }
730
731         if (!spoolss_io_system_time("", &ps, 0, &systime)) {
732                 prs_mem_free(&ps);
733                 return;
734         }
735
736         data->notify_data.data.length = prs_offset(&ps);
737         if (prs_offset(&ps)) {
738                 data->notify_data.data.string = (uint16 *)
739                         TALLOC(mem_ctx, prs_offset(&ps));
740                 if (!data->notify_data.data.string) {
741                         prs_mem_free(&ps);
742                         return;
743                 }
744                 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
745         } else {
746                 data->notify_data.data.string = NULL;
747         }
748
749         prs_mem_free(&ps);
750 }
751
752 struct notify2_message_table {
753         const char *name;
754         void (*fn)(struct spoolss_notify_msg *msg,
755                    SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 };
757
758 static struct notify2_message_table printer_notify_table[] = {
759         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
760         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
761         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
762         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
763         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
764         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
765         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
766         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
767         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
768         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
769         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
770         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
771         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
773         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
774         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
775         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
776         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
777         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 };
779
780 static struct notify2_message_table job_notify_table[] = {
781         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
782         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
783         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
784         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
785         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
786         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
787         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
788         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
789         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
790         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
791         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
792         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
793         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
794         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
795         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
796         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
797         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
798         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
799         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
801         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
802         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
803         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
804         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
805 };
806
807
808 /***********************************************************************
809  Allocate talloc context for container object
810  **********************************************************************/
811
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 {
814         if ( !ctr )
815                 return;
816
817         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
818
819         return;
820 }
821
822 /***********************************************************************
823  release all allocated memory and zero out structure
824  **********************************************************************/
825
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 {
828         if ( !ctr )
829                 return;
830
831         if ( ctr->ctx )
832                 talloc_destroy(ctr->ctx);
833
834         ZERO_STRUCTP(ctr);
835
836         return;
837 }
838
839 /***********************************************************************
840  **********************************************************************/
841
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
843 {
844         if ( !ctr )
845                 return NULL;
846
847         return ctr->ctx;
848 }
849
850 /***********************************************************************
851  **********************************************************************/
852
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
854 {
855         if ( !ctr || !ctr->msg_groups )
856                 return NULL;
857
858         if ( idx >= ctr->num_groups )
859                 return NULL;
860
861         return &ctr->msg_groups[idx];
862
863 }
864
865 /***********************************************************************
866  How many groups of change messages do we have ?
867  **********************************************************************/
868
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 {
871         if ( !ctr )
872                 return 0;
873
874         return ctr->num_groups;
875 }
876
877 /***********************************************************************
878  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879  **********************************************************************/
880
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 {
883         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
884         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
885         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
886         int                             i, new_slot;
887
888         if ( !ctr || !msg )
889                 return 0;
890
891         /* loop over all groups looking for a matching printer name */
892
893         for ( i=0; i<ctr->num_groups; i++ ) {
894                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895                         break;
896         }
897
898         /* add a new group? */
899
900         if ( i == ctr->num_groups ) {
901                 ctr->num_groups++;
902
903                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905                         return 0;
906                 }
907                 ctr->msg_groups = groups;
908
909                 /* clear the new entry and set the printer name */
910
911                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913         }
914
915         /* add the change messages; 'i' is the correct index now regardless */
916
917         msg_grp = &ctr->msg_groups[i];
918
919         msg_grp->num_msgs++;
920
921         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923                 return 0;
924         }
925         msg_grp->msgs = msg_list;
926
927         new_slot = msg_grp->num_msgs-1;
928         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929
930         /* need to allocate own copy of data */
931
932         if ( msg->len != 0 )
933                 msg_grp->msgs[new_slot].notify.data = (char *)
934                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935
936         return ctr->num_groups;
937 }
938
939 /***********************************************************************
940  Send a change notication message on all handles which have a call
941  back registered
942  **********************************************************************/
943
944 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
945 {
946         Printer_entry            *p;
947         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
948         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
949         SPOOLSS_NOTIFY_MSG       *messages;
950         int                      sending_msg_count;
951
952         if ( !msg_group ) {
953                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954                 return;
955         }
956
957         messages = msg_group->msgs;
958
959         if ( !messages ) {
960                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961                 return;
962         }
963
964         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965
966         /* loop over all printers */
967
968         for (p = printers_list; p; p = p->next) {
969                 SPOOL_NOTIFY_INFO_DATA *data;
970                 uint32  data_len = 0;
971                 uint32  id;
972                 int     i;
973
974                 /* Is there notification on this handle? */
975
976                 if ( !p->notify.client_connected )
977                         continue;
978
979                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980
981                 /* For this printer?  Print servers always receive
982                    notifications. */
983
984                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
985                     ( !strequal(msg_group->printername, p->sharename) ) )
986                         continue;
987
988                 DEBUG(10,("Our printer\n"));
989
990                 /* allocate the max entries possible */
991
992                 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
993                 if (!data) {
994                         return;
995                 }
996
997                 ZERO_STRUCTP(data);
998
999                 /* build the array of change notifications */
1000
1001                 sending_msg_count = 0;
1002
1003                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1004                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1005
1006                         /* Are we monitoring this event? */
1007
1008                         if (!is_monitoring_event(p, msg->type, msg->field))
1009                                 continue;
1010
1011                         sending_msg_count++;
1012
1013
1014                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1015                                 msg->type, msg->field, p->sharename));
1016
1017                         /*
1018                          * if the is a printer notification handle and not a job notification
1019                          * type, then set the id to 0.  Other wise just use what was specified
1020                          * in the message.
1021                          *
1022                          * When registering change notification on a print server handle
1023                          * we always need to send back the id (snum) matching the printer
1024                          * for which the change took place.  For change notify registered
1025                          * on a printer handle, this does not matter and the id should be 0.
1026                          *
1027                          * --jerry
1028                          */
1029
1030                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1031                                 id = 0;
1032                         else
1033                                 id = msg->id;
1034
1035
1036                         /* Convert unix jobid to smb jobid */
1037
1038                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1039                                 id = sysjob_to_jobid(msg->id);
1040
1041                                 if (id == -1) {
1042                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1043                                         goto done;
1044                                 }
1045                         }
1046
1047                         construct_info_data( &data[data_len], msg->type, msg->field, id );
1048
1049                         switch(msg->type) {
1050                         case PRINTER_NOTIFY_TYPE:
1051                                 if ( printer_notify_table[msg->field].fn )
1052                                         printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053                                 break;
1054
1055                         case JOB_NOTIFY_TYPE:
1056                                 if ( job_notify_table[msg->field].fn )
1057                                         job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1058                                 break;
1059
1060                         default:
1061                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062                                 goto done;
1063                         }
1064
1065                         data_len++;
1066                 }
1067
1068                 if ( sending_msg_count ) {
1069                         rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1070                                         data_len, data, p->notify.change, 0 );
1071                 }
1072         }
1073
1074 done:
1075         DEBUG(8,("send_notify2_changes: Exit...\n"));
1076         return;
1077 }
1078
1079 /***********************************************************************
1080  **********************************************************************/
1081
1082 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 {
1084
1085         uint32 tv_sec, tv_usec;
1086         size_t offset = 0;
1087
1088         /* Unpack message */
1089
1090         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1091                              msg->printer);
1092
1093         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1094                                 &tv_sec, &tv_usec,
1095                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1096
1097         if (msg->len == 0)
1098                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1099                            &msg->notify.value[0], &msg->notify.value[1]);
1100         else
1101                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1102                            &msg->len, &msg->notify.data);
1103
1104         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1105                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1106
1107         tv->tv_sec = tv_sec;
1108         tv->tv_usec = tv_usec;
1109
1110         if (msg->len == 0)
1111                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1112                           msg->notify.value[1]));
1113         else
1114                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1115
1116         return True;
1117 }
1118
1119 /********************************************************************
1120  Receive a notify2 message list
1121  ********************************************************************/
1122
1123 static void receive_notify2_message_list(struct messaging_context *msg,
1124                                          void *private_data,
1125                                          uint32_t msg_type,
1126                                          struct server_id server_id,
1127                                          DATA_BLOB *data)
1128 {
1129         size_t                  msg_count, i;
1130         char                    *buf = (char *)data->data;
1131         char                    *msg_ptr;
1132         size_t                  msg_len;
1133         SPOOLSS_NOTIFY_MSG      notify;
1134         SPOOLSS_NOTIFY_MSG_CTR  messages;
1135         int                     num_groups;
1136
1137         if (data->length < 4) {
1138                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1139                 return;
1140         }
1141
1142         msg_count = IVAL(buf, 0);
1143         msg_ptr = buf + 4;
1144
1145         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1146
1147         if (msg_count == 0) {
1148                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1149                 return;
1150         }
1151
1152         /* initialize the container */
1153
1154         ZERO_STRUCT( messages );
1155         notify_msg_ctr_init( &messages );
1156
1157         /*
1158          * build message groups for each printer identified
1159          * in a change_notify msg.  Remember that a PCN message
1160          * includes the handle returned for the srv_spoolss_replyopenprinter()
1161          * call.  Therefore messages are grouped according to printer handle.
1162          */
1163
1164         for ( i=0; i<msg_count; i++ ) {
1165                 struct timeval msg_tv;
1166
1167                 if (msg_ptr + 4 - buf > data->length) {
1168                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1169                         return;
1170                 }
1171
1172                 msg_len = IVAL(msg_ptr,0);
1173                 msg_ptr += 4;
1174
1175                 if (msg_ptr + msg_len - buf > data->length) {
1176                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1177                         return;
1178                 }
1179
1180                 /* unpack messages */
1181
1182                 ZERO_STRUCT( notify );
1183                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1184                 msg_ptr += msg_len;
1185
1186                 /* add to correct list in container */
1187
1188                 notify_msg_ctr_addmsg( &messages, &notify );
1189
1190                 /* free memory that might have been allocated by notify2_unpack_msg() */
1191
1192                 if ( notify.len != 0 )
1193                         SAFE_FREE( notify.notify.data );
1194         }
1195
1196         /* process each group of messages */
1197
1198         num_groups = notify_msg_ctr_numgroups( &messages );
1199         for ( i=0; i<num_groups; i++ )
1200                 send_notify2_changes( &messages, i );
1201
1202
1203         /* cleanup */
1204
1205         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1206
1207         notify_msg_ctr_destroy( &messages );
1208
1209         return;
1210 }
1211
1212 /********************************************************************
1213  Send a message to ourself about new driver being installed
1214  so we can upgrade the information for each printer bound to this
1215  driver
1216  ********************************************************************/
1217
1218 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1219 {
1220         int len = strlen(drivername);
1221
1222         if (!len)
1223                 return False;
1224
1225         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1226                 drivername));
1227
1228         messaging_send_buf(smbd_messaging_context(), procid_self(),
1229                            MSG_PRINTER_DRVUPGRADE,
1230                            (uint8 *)drivername, len+1);
1231
1232         return True;
1233 }
1234
1235 /**********************************************************************
1236  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1237  over all printers, upgrading ones as necessary
1238  **********************************************************************/
1239
1240 void do_drv_upgrade_printer(struct messaging_context *msg,
1241                             void *private_data,
1242                             uint32_t msg_type,
1243                             struct server_id server_id,
1244                             DATA_BLOB *data)
1245 {
1246         fstring drivername;
1247         int snum;
1248         int n_services = lp_numservices();
1249         size_t len;
1250
1251         len = MIN(data->length,sizeof(drivername)-1);
1252         strncpy(drivername, (const char *)data->data, len);
1253
1254         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1255
1256         /* Iterate the printer list */
1257
1258         for (snum=0; snum<n_services; snum++)
1259         {
1260                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1261                 {
1262                         WERROR result;
1263                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1264
1265                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1266                         if (!W_ERROR_IS_OK(result))
1267                                 continue;
1268
1269                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1270                         {
1271                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1272
1273                                 /* all we care about currently is the change_id */
1274
1275                                 result = mod_a_printer(printer, 2);
1276                                 if (!W_ERROR_IS_OK(result)) {
1277                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1278                                                 win_errstr(result)));
1279                                 }
1280                         }
1281
1282                         free_a_printer(&printer, 2);
1283                 }
1284         }
1285
1286         /* all done */
1287 }
1288
1289 /********************************************************************
1290  Update the cache for all printq's with a registered client
1291  connection
1292  ********************************************************************/
1293
1294 void update_monitored_printq_cache( void )
1295 {
1296         Printer_entry *printer = printers_list;
1297         int snum;
1298
1299         /* loop through all printers and update the cache where
1300            client_connected == True */
1301         while ( printer )
1302         {
1303                 if ( (printer->printer_type == SPLHND_PRINTER)
1304                         && printer->notify.client_connected )
1305                 {
1306                         snum = print_queue_snum(printer->sharename);
1307                         print_queue_status( snum, NULL, NULL );
1308                 }
1309
1310                 printer = printer->next;
1311         }
1312
1313         return;
1314 }
1315 /********************************************************************
1316  Send a message to ourself about new driver being installed
1317  so we can upgrade the information for each printer bound to this
1318  driver
1319  ********************************************************************/
1320
1321 static bool srv_spoolss_reset_printerdata(char* drivername)
1322 {
1323         int len = strlen(drivername);
1324
1325         if (!len)
1326                 return False;
1327
1328         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1329                 drivername));
1330
1331         messaging_send_buf(smbd_messaging_context(), procid_self(),
1332                            MSG_PRINTERDATA_INIT_RESET,
1333                            (uint8 *)drivername, len+1);
1334
1335         return True;
1336 }
1337
1338 /**********************************************************************
1339  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1340  over all printers, resetting printer data as neessary
1341  **********************************************************************/
1342
1343 void reset_all_printerdata(struct messaging_context *msg,
1344                            void *private_data,
1345                            uint32_t msg_type,
1346                            struct server_id server_id,
1347                            DATA_BLOB *data)
1348 {
1349         fstring drivername;
1350         int snum;
1351         int n_services = lp_numservices();
1352         size_t len;
1353
1354         len = MIN( data->length, sizeof(drivername)-1 );
1355         strncpy( drivername, (const char *)data->data, len );
1356
1357         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1358
1359         /* Iterate the printer list */
1360
1361         for ( snum=0; snum<n_services; snum++ )
1362         {
1363                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1364                 {
1365                         WERROR result;
1366                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1367
1368                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1369                         if ( !W_ERROR_IS_OK(result) )
1370                                 continue;
1371
1372                         /*
1373                          * if the printer is bound to the driver,
1374                          * then reset to the new driver initdata
1375                          */
1376
1377                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1378                         {
1379                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1380
1381                                 if ( !set_driver_init(printer, 2) ) {
1382                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1383                                                 printer->info_2->printername, printer->info_2->drivername));
1384                                 }
1385
1386                                 result = mod_a_printer( printer, 2 );
1387                                 if ( !W_ERROR_IS_OK(result) ) {
1388                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1389                                                 get_dos_error_msg(result)));
1390                                 }
1391                         }
1392
1393                         free_a_printer( &printer, 2 );
1394                 }
1395         }
1396
1397         /* all done */
1398
1399         return;
1400 }
1401
1402 /********************************************************************
1403  Copy routines used by convert_to_openprinterex()
1404  *******************************************************************/
1405
1406 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1407 {
1408         DEVICEMODE *d;
1409         int len;
1410
1411         if (!devmode)
1412                 return NULL;
1413
1414         DEBUG (8,("dup_devmode\n"));
1415
1416         /* bulk copy first */
1417
1418         d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1419         if (!d)
1420                 return NULL;
1421
1422         /* dup the pointer members separately */
1423
1424         len = unistrlen(devmode->devicename.buffer);
1425         if (len != -1) {
1426                 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1427                 if (!d->devicename.buffer) {
1428                         return NULL;
1429                 }
1430                 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1431                         return NULL;
1432         }
1433
1434
1435         len = unistrlen(devmode->formname.buffer);
1436         if (len != -1) {
1437                 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1438                 if (!d->formname.buffer) {
1439                         return NULL;
1440                 }
1441                 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1442                         return NULL;
1443         }
1444
1445         if (devmode->driverextra) {
1446                 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1447                                                 devmode->driverextra);
1448                 if (!d->dev_private) {
1449                         return NULL;
1450                 }
1451         } else {
1452                 d->dev_private = NULL;
1453         }
1454         return d;
1455 }
1456
1457 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1458 {
1459         if (!new_ctr || !ctr)
1460                 return;
1461
1462         DEBUG(8,("copy_devmode_ctr\n"));
1463
1464         new_ctr->size = ctr->size;
1465         new_ctr->devmode_ptr = ctr->devmode_ptr;
1466
1467         if(ctr->devmode_ptr)
1468                 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 }
1470
1471 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1472 {
1473         if (!new_def || !def)
1474                 return;
1475
1476         DEBUG(8,("copy_printer_defaults\n"));
1477
1478         new_def->datatype_ptr = def->datatype_ptr;
1479
1480         if (def->datatype_ptr)
1481                 copy_unistr2(&new_def->datatype, &def->datatype);
1482
1483         copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1484
1485         new_def->access_required = def->access_required;
1486 }
1487
1488 /********************************************************************
1489  * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1490  * SPOOL_Q_OPEN_PRINTER_EX structure
1491  ********************************************************************/
1492
1493 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1494 {
1495         if (!q_u_ex || !q_u)
1496                 return WERR_OK;
1497
1498         DEBUG(8,("convert_to_openprinterex\n"));
1499
1500         if ( q_u->printername ) {
1501                 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1502                 if (q_u_ex->printername == NULL)
1503                         return WERR_NOMEM;
1504                 copy_unistr2(q_u_ex->printername, q_u->printername);
1505         }
1506
1507         copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1508
1509         return WERR_OK;
1510 }
1511
1512 /********************************************************************
1513  * spoolss_open_printer
1514  *
1515  * called from the spoolss dispatcher
1516  ********************************************************************/
1517
1518 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1519 {
1520         SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1521         SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1522
1523         if (!q_u || !r_u)
1524                 return WERR_NOMEM;
1525
1526         ZERO_STRUCT(q_u_ex);
1527         ZERO_STRUCT(r_u_ex);
1528
1529         /* convert the OpenPrinter() call to OpenPrinterEx() */
1530
1531         r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1532         if (!W_ERROR_IS_OK(r_u_ex.status))
1533                 return r_u_ex.status;
1534
1535         r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1536
1537         /* convert back to OpenPrinter() */
1538
1539         memcpy(r_u, &r_u_ex, sizeof(*r_u));
1540
1541         if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1542                 /* OpenPrinterEx returns this for a bad
1543                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1544                  * instead.
1545                  */
1546                 r_u->status = WERR_INVALID_PRINTER_NAME;
1547         }
1548         return r_u->status;
1549 }
1550
1551 /********************************************************************
1552  FIXME: temporary convert_devicemode_new function
1553  ********************************************************************/
1554
1555 static bool convert_devicemode_new(const char *printername,
1556                                    struct spoolss_DeviceMode *devmode,
1557                                    NT_DEVICEMODE **pp_nt_devmode)
1558 {
1559         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1560
1561         /*
1562          * Ensure nt_devmode is a valid pointer
1563          * as we will be overwriting it.
1564          */
1565
1566         if (nt_devmode == NULL) {
1567                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1568                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1569                         return false;
1570         }
1571
1572         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1573         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1574
1575         nt_devmode->specversion         = devmode->specversion;
1576         nt_devmode->driverversion       = devmode->driverversion;
1577         nt_devmode->size                = devmode->size;
1578         nt_devmode->fields              = devmode->fields;
1579         nt_devmode->orientation         = devmode->orientation;
1580         nt_devmode->papersize           = devmode->papersize;
1581         nt_devmode->paperlength         = devmode->paperlength;
1582         nt_devmode->paperwidth          = devmode->paperwidth;
1583         nt_devmode->scale               = devmode->scale;
1584         nt_devmode->copies              = devmode->copies;
1585         nt_devmode->defaultsource       = devmode->defaultsource;
1586         nt_devmode->printquality        = devmode->printquality;
1587         nt_devmode->color               = devmode->color;
1588         nt_devmode->duplex              = devmode->duplex;
1589         nt_devmode->yresolution         = devmode->yresolution;
1590         nt_devmode->ttoption            = devmode->ttoption;
1591         nt_devmode->collate             = devmode->collate;
1592
1593         nt_devmode->logpixels           = devmode->logpixels;
1594         nt_devmode->bitsperpel          = devmode->bitsperpel;
1595         nt_devmode->pelswidth           = devmode->pelswidth;
1596         nt_devmode->pelsheight          = devmode->pelsheight;
1597         nt_devmode->displayflags        = devmode->displayflags;
1598         nt_devmode->displayfrequency    = devmode->displayfrequency;
1599         nt_devmode->icmmethod           = devmode->icmmethod;
1600         nt_devmode->icmintent           = devmode->icmintent;
1601         nt_devmode->mediatype           = devmode->mediatype;
1602         nt_devmode->dithertype          = devmode->dithertype;
1603         nt_devmode->reserved1           = devmode->reserved1;
1604         nt_devmode->reserved2           = devmode->reserved2;
1605         nt_devmode->panningwidth        = devmode->panningwidth;
1606         nt_devmode->panningheight       = devmode->panningheight;
1607
1608         /*
1609          * Only change private and driverextra if the incoming devmode
1610          * has a new one. JRA.
1611          */
1612
1613         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1614                 SAFE_FREE(nt_devmode->nt_dev_private);
1615                 nt_devmode->driverextra = devmode->__driverextra_length;
1616                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1617                         return false;
1618                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1619         }
1620
1621         *pp_nt_devmode = nt_devmode;
1622
1623         return true;
1624 }
1625
1626 /********************************************************************
1627  ********************************************************************/
1628
1629 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1630 {
1631         PRINTER_DEFAULT         *printer_default = &q_u->printer_default;
1632         POLICY_HND              *handle = &r_u->handle;
1633
1634         fstring name;
1635         int snum;
1636         Printer_entry *Printer=NULL;
1637
1638         if (!q_u->printername) {
1639                 return WERR_INVALID_PARAM;
1640         }
1641
1642         /* some sanity check because you can open a printer or a print server */
1643         /* aka: \\server\printer or \\server */
1644
1645         unistr2_to_ascii(name, q_u->printername, sizeof(name));
1646
1647         DEBUGADD(3,("checking name: %s\n",name));
1648
1649         if (!open_printer_hnd(p, handle, name, 0)) {
1650                 return WERR_INVALID_PARAM;
1651         }
1652
1653         Printer=find_printer_index_by_hnd(p, handle);
1654         if ( !Printer ) {
1655                 DEBUG(0,(" _spoolss_open_printer_ex: logic error.  Can't find printer "
1656                         "handle we created for printer %s\n", name ));
1657                 close_printer_handle(p,handle);
1658                 return WERR_INVALID_PARAM;
1659         }
1660
1661         /*
1662          * First case: the user is opening the print server:
1663          *
1664          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1665          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1666          *
1667          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1668          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1669          * or if the user is listed in the smb.conf printer admin parameter.
1670          *
1671          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1672          * client view printer folder, but does not show the MSAPW.
1673          *
1674          * Note: this test needs code to check access rights here too. Jeremy
1675          * could you look at this?
1676          *
1677          * Second case: the user is opening a printer:
1678          * NT doesn't let us connect to a printer if the connecting user
1679          * doesn't have print permission.
1680          *
1681          * Third case: user is opening a Port Monitor
1682          * access checks same as opening a handle to the print server.
1683          */
1684
1685         switch (Printer->printer_type )
1686         {
1687         case SPLHND_SERVER:
1688         case SPLHND_PORTMON_TCP:
1689         case SPLHND_PORTMON_LOCAL:
1690                 /* Printserver handles use global struct... */
1691
1692                 snum = -1;
1693
1694                 /* Map standard access rights to object specific access rights */
1695
1696                 se_map_standard(&printer_default->access_required,
1697                                 &printserver_std_mapping);
1698
1699                 /* Deny any object specific bits that don't apply to print
1700                    servers (i.e printer and job specific bits) */
1701
1702                 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1703
1704                 if (printer_default->access_required &
1705                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1706                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1707                         close_printer_handle(p, handle);
1708                         return WERR_ACCESS_DENIED;
1709                 }
1710
1711                 /* Allow admin access */
1712
1713                 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1714                 {
1715                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1716
1717                         if (!lp_ms_add_printer_wizard()) {
1718                                 close_printer_handle(p, handle);
1719                                 return WERR_ACCESS_DENIED;
1720                         }
1721
1722                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1723                            and not a printer admin, then fail */
1724
1725                         if ((p->server_info->utok.uid != 0) &&
1726                             !user_has_privileges(p->server_info->ptok,
1727                                                  &se_printop ) &&
1728                             !token_contains_name_in_list(
1729                                     uidtoname(p->server_info->utok.uid),
1730                                     NULL, NULL,
1731                                     p->server_info->ptok,
1732                                     lp_printer_admin(snum))) {
1733                                 close_printer_handle(p, handle);
1734                                 return WERR_ACCESS_DENIED;
1735                         }
1736
1737                         printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1738                 }
1739                 else
1740                 {
1741                         printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1742                 }
1743
1744                 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1745                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1746
1747                 /* We fall through to return WERR_OK */
1748                 break;
1749
1750         case SPLHND_PRINTER:
1751                 /* NT doesn't let us connect to a printer if the connecting user
1752                    doesn't have print permission.  */
1753
1754                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1755                         close_printer_handle(p, handle);
1756                         return WERR_BADFID;
1757                 }
1758
1759                 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1760
1761                 /* map an empty access mask to the minimum access mask */
1762                 if (printer_default->access_required == 0x0)
1763                         printer_default->access_required = PRINTER_ACCESS_USE;
1764
1765                 /*
1766                  * If we are not serving the printer driver for this printer,
1767                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1768                  * will keep NT clients happy  --jerry
1769                  */
1770
1771                 if (lp_use_client_driver(snum)
1772                         && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1773                 {
1774                         printer_default->access_required = PRINTER_ACCESS_USE;
1775                 }
1776
1777                 /* check smb.conf parameters and the the sec_desc */
1778
1779                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1780                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1781                         return WERR_ACCESS_DENIED;
1782                 }
1783
1784                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1785                                    p->server_info->ptok, snum) ||
1786                     !print_access_check(p->server_info, snum,
1787                                         printer_default->access_required)) {
1788                         DEBUG(3, ("access DENIED for printer open\n"));
1789                         close_printer_handle(p, handle);
1790                         return WERR_ACCESS_DENIED;
1791                 }
1792
1793                 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1794                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1795                         close_printer_handle(p, handle);
1796                         return WERR_ACCESS_DENIED;
1797                 }
1798
1799                 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1800                         printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1801                 else
1802                         printer_default->access_required = PRINTER_ACCESS_USE;
1803
1804                 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1805                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1806
1807                 break;
1808
1809         default:
1810                 /* sanity check to prevent programmer error */
1811                 return WERR_BADFID;
1812         }
1813
1814         Printer->access_granted = printer_default->access_required;
1815
1816         /*
1817          * If the client sent a devmode in the OpenPrinter() call, then
1818          * save it here in case we get a job submission on this handle
1819          */
1820
1821          if ( (Printer->printer_type != SPLHND_SERVER)
1822                 && q_u->printer_default.devmode_cont.devmode_ptr )
1823          {
1824                 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1825                         &Printer->nt_devmode );
1826          }
1827
1828 #if 0   /* JERRY -- I'm doubtful this is really effective */
1829         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1830            optimization in Windows 2000 clients  --jerry */
1831
1832         if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1833                 && (RA_WIN2K == get_remote_arch()) )
1834         {
1835                 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1836                 sys_usleep( 500000 );
1837         }
1838 #endif
1839
1840         return WERR_OK;
1841 }
1842
1843 /****************************************************************************
1844 ****************************************************************************/
1845
1846 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1847                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1848 {
1849         bool ret;
1850
1851         switch (level) {
1852                 case 2:
1853                         /* allocate memory if needed.  Messy because
1854                            convert_printer_info is used to update an existing
1855                            printer or build a new one */
1856
1857                         if ( !printer->info_2 ) {
1858                                 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1859                                 if ( !printer->info_2 ) {
1860                                         DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1861                                         return False;
1862                                 }
1863                         }
1864
1865                         ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1866                         printer->info_2->setuptime = time(NULL);
1867
1868                         return ret;
1869         }
1870
1871         return False;
1872 }
1873
1874 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1875                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1876 {
1877         bool result = True;
1878
1879         switch (level) {
1880                 case 3:
1881                         printer->info_3=NULL;
1882                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1883                                 result = False;
1884                         break;
1885                 case 6:
1886                         printer->info_6=NULL;
1887                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1888                                 result = False;
1889                         break;
1890                 default:
1891                         break;
1892         }
1893
1894         return result;
1895 }
1896
1897 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1898                                 NT_DEVICEMODE **pp_nt_devmode)
1899 {
1900         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1901
1902         /*
1903          * Ensure nt_devmode is a valid pointer
1904          * as we will be overwriting it.
1905          */
1906
1907         if (nt_devmode == NULL) {
1908                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1909                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1910                         return False;
1911         }
1912
1913         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1914         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1915
1916         nt_devmode->specversion=devmode->specversion;
1917         nt_devmode->driverversion=devmode->driverversion;
1918         nt_devmode->size=devmode->size;
1919         nt_devmode->fields=devmode->fields;
1920         nt_devmode->orientation=devmode->orientation;
1921         nt_devmode->papersize=devmode->papersize;
1922         nt_devmode->paperlength=devmode->paperlength;
1923         nt_devmode->paperwidth=devmode->paperwidth;
1924         nt_devmode->scale=devmode->scale;
1925         nt_devmode->copies=devmode->copies;
1926         nt_devmode->defaultsource=devmode->defaultsource;
1927         nt_devmode->printquality=devmode->printquality;
1928         nt_devmode->color=devmode->color;
1929         nt_devmode->duplex=devmode->duplex;
1930         nt_devmode->yresolution=devmode->yresolution;
1931         nt_devmode->ttoption=devmode->ttoption;
1932         nt_devmode->collate=devmode->collate;
1933
1934         nt_devmode->logpixels=devmode->logpixels;
1935         nt_devmode->bitsperpel=devmode->bitsperpel;
1936         nt_devmode->pelswidth=devmode->pelswidth;
1937         nt_devmode->pelsheight=devmode->pelsheight;
1938         nt_devmode->displayflags=devmode->displayflags;
1939         nt_devmode->displayfrequency=devmode->displayfrequency;
1940         nt_devmode->icmmethod=devmode->icmmethod;
1941         nt_devmode->icmintent=devmode->icmintent;
1942         nt_devmode->mediatype=devmode->mediatype;
1943         nt_devmode->dithertype=devmode->dithertype;
1944         nt_devmode->reserved1=devmode->reserved1;
1945         nt_devmode->reserved2=devmode->reserved2;
1946         nt_devmode->panningwidth=devmode->panningwidth;
1947         nt_devmode->panningheight=devmode->panningheight;
1948
1949         /*
1950          * Only change private and driverextra if the incoming devmode
1951          * has a new one. JRA.
1952          */
1953
1954         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1955                 SAFE_FREE(nt_devmode->nt_dev_private);
1956                 nt_devmode->driverextra=devmode->driverextra;
1957                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1958                         return False;
1959                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1960         }
1961
1962         *pp_nt_devmode = nt_devmode;
1963
1964         return True;
1965 }
1966
1967 /********************************************************************
1968  * _spoolss_enddocprinter_internal.
1969  ********************************************************************/
1970
1971 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1972 {
1973         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1974         int snum;
1975
1976         if (!Printer) {
1977                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1978                 return WERR_BADFID;
1979         }
1980
1981         if (!get_printer_snum(p, handle, &snum, NULL))
1982                 return WERR_BADFID;
1983
1984         Printer->document_started=False;
1985         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1986         /* error codes unhandled so far ... */
1987
1988         return WERR_OK;
1989 }
1990
1991 /****************************************************************
1992  _spoolss_ClosePrinter
1993 ****************************************************************/
1994
1995 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1996                              struct spoolss_ClosePrinter *r)
1997 {
1998         POLICY_HND *handle = r->in.handle;
1999
2000         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2001
2002         if (Printer && Printer->document_started)
2003                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2004
2005         if (!close_printer_handle(p, handle))
2006                 return WERR_BADFID;
2007
2008         /* clear the returned printer handle.  Observed behavior
2009            from Win2k server.  Don't think this really matters.
2010            Previous code just copied the value of the closed
2011            handle.    --jerry */
2012
2013         ZERO_STRUCTP(r->out.handle);
2014
2015         return WERR_OK;
2016 }
2017
2018 /****************************************************************
2019  _spoolss_DeletePrinter
2020 ****************************************************************/
2021
2022 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2023                               struct spoolss_DeletePrinter *r)
2024 {
2025         POLICY_HND *handle = r->in.handle;
2026         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2027         WERROR result;
2028
2029         if (Printer && Printer->document_started)
2030                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2031
2032         result = delete_printer_handle(p, handle);
2033
2034         update_c_setprinter(False);
2035
2036         return result;
2037 }
2038
2039 /*******************************************************************
2040  * static function to lookup the version id corresponding to an
2041  * long architecture string
2042  ******************************************************************/
2043
2044 static int get_version_id (char * arch)
2045 {
2046         int i;
2047         struct table_node archi_table[]= {
2048
2049                 {"Windows 4.0",          "WIN40",       0 },
2050                 {"Windows NT x86",       "W32X86",      2 },
2051                 {"Windows NT R4000",     "W32MIPS",     2 },
2052                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2053                 {"Windows NT PowerPC",   "W32PPC",      2 },
2054                 {"Windows IA64",         "IA64",        3 },
2055                 {"Windows x64",          "x64",         3 },
2056                 {NULL,                   "",            -1 }
2057         };
2058
2059         for (i=0; archi_table[i].long_archi != NULL; i++)
2060         {
2061                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2062                         return (archi_table[i].version);
2063         }
2064
2065         return -1;
2066 }
2067
2068 /****************************************************************
2069  _spoolss_DeletePrinterDriver
2070 ****************************************************************/
2071
2072 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2073                                     struct spoolss_DeletePrinterDriver *r)
2074 {
2075         char *driver;
2076         char *arch;
2077         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2078         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2079         int                             version;
2080         WERROR                          status;
2081         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2082         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2083
2084         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2085            and not a printer admin, then fail */
2086
2087         if ( (p->server_info->utok.uid != 0)
2088                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2089                 && !token_contains_name_in_list(
2090                         uidtoname(p->server_info->utok.uid), NULL,
2091                         NULL, p->server_info->ptok,
2092                         lp_printer_admin(-1)) )
2093         {
2094                 return WERR_ACCESS_DENIED;
2095         }
2096
2097         driver = CONST_DISCARD(char *, r->in.driver);
2098         arch   = CONST_DISCARD(char *, r->in.architecture);
2099
2100         /* check that we have a valid driver name first */
2101
2102         if ((version=get_version_id(arch)) == -1)
2103                 return WERR_INVALID_ENVIRONMENT;
2104
2105         ZERO_STRUCT(info);
2106         ZERO_STRUCT(info_win2k);
2107
2108         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2109         {
2110                 /* try for Win2k driver if "Windows NT x86" */
2111
2112                 if ( version == 2 ) {
2113                         version = 3;
2114                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2115                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2116                                 goto done;
2117                         }
2118                 }
2119                 /* otherwise it was a failure */
2120                 else {
2121                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2122                         goto done;
2123                 }
2124
2125         }
2126
2127         if (printer_driver_in_use(info.info_3)) {
2128                 status = WERR_PRINTER_DRIVER_IN_USE;
2129                 goto done;
2130         }
2131
2132         if ( version == 2 )
2133         {
2134                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2135                 {
2136                         /* if we get to here, we now have 2 driver info structures to remove */
2137                         /* remove the Win2k driver first*/
2138
2139                         status_win2k = delete_printer_driver(
2140                                 p, info_win2k.info_3, 3, False );
2141                         free_a_printer_driver( info_win2k, 3 );
2142
2143                         /* this should not have failed---if it did, report to client */
2144                         if ( !W_ERROR_IS_OK(status_win2k) )
2145                         {
2146                                 status = status_win2k;
2147                                 goto done;
2148                         }
2149                 }
2150         }
2151
2152         status = delete_printer_driver(p, info.info_3, version, False);
2153
2154         /* if at least one of the deletes succeeded return OK */
2155
2156         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2157                 status = WERR_OK;
2158
2159 done:
2160         free_a_printer_driver( info, 3 );
2161
2162         return status;
2163 }
2164
2165 /****************************************************************
2166  _spoolss_DeletePrinterDriverEx
2167 ****************************************************************/
2168
2169 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2170                                       struct spoolss_DeletePrinterDriverEx *r)
2171 {
2172         char *driver;
2173         char *arch;
2174         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2175         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2176         int                             version;
2177         uint32_t                        flags = r->in.delete_flags;
2178         bool                            delete_files;
2179         WERROR                          status;
2180         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2181         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ( (p->server_info->utok.uid != 0)
2187                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2188                 && !token_contains_name_in_list(
2189                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2190                         p->server_info->ptok, lp_printer_admin(-1)) )
2191         {
2192                 return WERR_ACCESS_DENIED;
2193         }
2194
2195         driver = CONST_DISCARD(char *, r->in.driver);
2196         arch   = CONST_DISCARD(char *, r->in.architecture);
2197
2198         /* check that we have a valid driver name first */
2199         if ((version=get_version_id(arch)) == -1) {
2200                 /* this is what NT returns */
2201                 return WERR_INVALID_ENVIRONMENT;
2202         }
2203
2204         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2205                 version = r->in.version;
2206
2207         ZERO_STRUCT(info);
2208         ZERO_STRUCT(info_win2k);
2209
2210         status = get_a_printer_driver(&info, 3, driver, arch, version);
2211
2212         if ( !W_ERROR_IS_OK(status) )
2213         {
2214                 /*
2215                  * if the client asked for a specific version,
2216                  * or this is something other than Windows NT x86,
2217                  * then we've failed
2218                  */
2219
2220                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2221                         goto done;
2222
2223                 /* try for Win2k driver if "Windows NT x86" */
2224
2225                 version = 3;
2226                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2227                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2228                         goto done;
2229                 }
2230         }
2231
2232         if ( printer_driver_in_use(info.info_3) ) {
2233                 status = WERR_PRINTER_DRIVER_IN_USE;
2234                 goto done;
2235         }
2236
2237         /*
2238          * we have a couple of cases to consider.
2239          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2240          *     then the delete should fail if **any** files overlap with
2241          *     other drivers
2242          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2243          *     non-overlapping files
2244          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2245          *     is set, the do not delete any files
2246          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2247          */
2248
2249         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2250
2251         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2252
2253         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2254                 /* no idea of the correct error here */
2255                 status = WERR_ACCESS_DENIED;
2256                 goto done;
2257         }
2258
2259
2260         /* also check for W32X86/3 if necessary; maybe we already have? */
2261
2262         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2263                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2264                 {
2265
2266                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2267                                 /* no idea of the correct error here */
2268                                 free_a_printer_driver( info_win2k, 3 );
2269                                 status = WERR_ACCESS_DENIED;
2270                                 goto done;
2271                         }
2272
2273                         /* if we get to here, we now have 2 driver info structures to remove */
2274                         /* remove the Win2k driver first*/
2275
2276                         status_win2k = delete_printer_driver(
2277                                 p, info_win2k.info_3, 3, delete_files);
2278                         free_a_printer_driver( info_win2k, 3 );
2279
2280                         /* this should not have failed---if it did, report to client */
2281
2282                         if ( !W_ERROR_IS_OK(status_win2k) )
2283                                 goto done;
2284                 }
2285         }
2286
2287         status = delete_printer_driver(p, info.info_3, version, delete_files);
2288
2289         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2290                 status = WERR_OK;
2291 done:
2292         free_a_printer_driver( info, 3 );
2293
2294         return status;
2295 }
2296
2297
2298 /****************************************************************************
2299  Internal routine for retreiving printerdata
2300  ***************************************************************************/
2301
2302 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2303                                   const char *key, const char *value, uint32 *type, uint8 **data,
2304                                   uint32 *needed, uint32 in_size  )
2305 {
2306         REGISTRY_VALUE          *val;
2307         uint32                  size;
2308         int                     data_len;
2309
2310         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2311                 return WERR_BADFILE;
2312
2313         *type = regval_type( val );
2314
2315         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2316
2317         size = regval_size( val );
2318
2319         /* copy the min(in_size, len) */
2320
2321         if ( in_size ) {
2322                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2323
2324                 /* special case for 0 length values */
2325                 if ( data_len ) {
2326                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2327                                 return WERR_NOMEM;
2328                 }
2329                 else {
2330                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2331                                 return WERR_NOMEM;
2332                 }
2333         }
2334         else
2335                 *data = NULL;
2336
2337         *needed = size;
2338
2339         DEBUG(5,("get_printer_dataex: copy done\n"));
2340
2341         return WERR_OK;
2342 }
2343
2344 /****************************************************************************
2345  Internal routine for removing printerdata
2346  ***************************************************************************/
2347
2348 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2349 {
2350         return delete_printer_data( printer->info_2, key, value );
2351 }
2352
2353 /****************************************************************************
2354  Internal routine for storing printerdata
2355  ***************************************************************************/
2356
2357 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2358                                   uint32 type, uint8 *data, int real_len  )
2359 {
2360         /* the registry objects enforce uniqueness based on value name */
2361
2362         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2363 }
2364
2365 /********************************************************************
2366  GetPrinterData on a printer server Handle.
2367 ********************************************************************/
2368
2369 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2370 {
2371         int i;
2372
2373         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2374
2375         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2376                 *type = REG_DWORD;
2377                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2378                         return WERR_NOMEM;
2379                 SIVAL(*data, 0, 0x00);
2380                 *needed = 0x4;
2381                 return WERR_OK;
2382         }
2383
2384         if (!StrCaseCmp(value, "BeepEnabled")) {
2385                 *type = REG_DWORD;
2386                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2387                         return WERR_NOMEM;
2388                 SIVAL(*data, 0, 0x00);
2389                 *needed = 0x4;
2390                 return WERR_OK;
2391         }
2392
2393         if (!StrCaseCmp(value, "EventLog")) {
2394                 *type = REG_DWORD;
2395                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2396                         return WERR_NOMEM;
2397                 /* formally was 0x1b */
2398                 SIVAL(*data, 0, 0x0);
2399                 *needed = 0x4;
2400                 return WERR_OK;
2401         }
2402
2403         if (!StrCaseCmp(value, "NetPopup")) {
2404                 *type = REG_DWORD;
2405                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2406                         return WERR_NOMEM;
2407                 SIVAL(*data, 0, 0x00);
2408                 *needed = 0x4;
2409                 return WERR_OK;
2410         }
2411
2412         if (!StrCaseCmp(value, "MajorVersion")) {
2413                 *type = REG_DWORD;
2414                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2415                         return WERR_NOMEM;
2416
2417                 /* Windows NT 4.0 seems to not allow uploading of drivers
2418                    to a server that reports 0x3 as the MajorVersion.
2419                    need to investigate more how Win2k gets around this .
2420                    -- jerry */
2421
2422                 if ( RA_WINNT == get_remote_arch() )
2423                         SIVAL(*data, 0, 2);
2424                 else
2425                         SIVAL(*data, 0, 3);
2426
2427                 *needed = 0x4;
2428                 return WERR_OK;
2429         }
2430
2431         if (!StrCaseCmp(value, "MinorVersion")) {
2432                 *type = REG_DWORD;
2433                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2434                         return WERR_NOMEM;
2435                 SIVAL(*data, 0, 0);
2436                 *needed = 0x4;
2437                 return WERR_OK;
2438         }
2439
2440         /* REG_BINARY
2441          *  uint32 size          = 0x114
2442          *  uint32 major         = 5
2443          *  uint32 minor         = [0|1]
2444          *  uint32 build         = [2195|2600]
2445          *  extra unicode string = e.g. "Service Pack 3"
2446          */
2447         if (!StrCaseCmp(value, "OSVersion")) {
2448                 *type = REG_BINARY;
2449                 *needed = 0x114;
2450
2451                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2452                         return WERR_NOMEM;
2453
2454                 SIVAL(*data, 0, *needed);       /* size */
2455                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2456                 SIVAL(*data, 8, 0);
2457                 SIVAL(*data, 12, 2195);         /* build */
2458
2459                 /* leave extra string empty */
2460
2461                 return WERR_OK;
2462         }
2463
2464
2465         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2466                 const char *string="C:\\PRINTERS";
2467                 *type = REG_SZ;
2468                 *needed = 2*(strlen(string)+1);
2469                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2470                         return WERR_NOMEM;
2471                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2472
2473                 /* it's done by hand ready to go on the wire */
2474                 for (i=0; i<strlen(string); i++) {
2475                         (*data)[2*i]=string[i];
2476                         (*data)[2*i+1]='\0';
2477                 }
2478                 return WERR_OK;
2479         }
2480
2481         if (!StrCaseCmp(value, "Architecture")) {
2482                 const char *string="Windows NT x86";
2483                 *type = REG_SZ;
2484                 *needed = 2*(strlen(string)+1);
2485                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2486                         return WERR_NOMEM;
2487                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2488                 for (i=0; i<strlen(string); i++) {
2489                         (*data)[2*i]=string[i];
2490                         (*data)[2*i+1]='\0';
2491                 }
2492                 return WERR_OK;
2493         }
2494
2495         if (!StrCaseCmp(value, "DsPresent")) {
2496                 *type = REG_DWORD;
2497                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2498                         return WERR_NOMEM;
2499
2500                 /* only show the publish check box if we are a
2501                    memeber of a AD domain */
2502
2503                 if ( lp_security() == SEC_ADS )
2504                         SIVAL(*data, 0, 0x01);
2505                 else
2506                         SIVAL(*data, 0, 0x00);
2507
2508                 *needed = 0x4;
2509                 return WERR_OK;
2510         }
2511
2512         if (!StrCaseCmp(value, "DNSMachineName")) {
2513                 const char *hostname = get_mydnsfullname();
2514
2515                 if (!hostname)
2516                         return WERR_BADFILE;
2517                 *type = REG_SZ;
2518                 *needed = 2*(strlen(hostname)+1);
2519                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2520                         return WERR_NOMEM;
2521                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2522                 for (i=0; i<strlen(hostname); i++) {
2523                         (*data)[2*i]=hostname[i];
2524                         (*data)[2*i+1]='\0';
2525                 }
2526                 return WERR_OK;
2527         }
2528
2529
2530         return WERR_BADFILE;
2531 }
2532
2533 /********************************************************************
2534  * spoolss_getprinterdata
2535  ********************************************************************/
2536
2537 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2538 {
2539         POLICY_HND      *handle = &q_u->handle;
2540         UNISTR2         *valuename = &q_u->valuename;
2541         uint32          in_size = q_u->size;
2542         uint32          *type = &r_u->type;
2543         uint32          *out_size = &r_u->size;
2544         uint8           **data = &r_u->data;
2545         uint32          *needed = &r_u->needed;
2546         WERROR          status;
2547         fstring         value;
2548         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2549         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2550         int             snum = 0;
2551
2552         /*
2553          * Reminder: when it's a string, the length is in BYTES
2554          * even if UNICODE is negociated.
2555          *
2556          * JFM, 4/19/1999
2557          */
2558
2559         *out_size = in_size;
2560
2561         /* in case of problem, return some default values */
2562
2563         *needed = 0;
2564         *type   = 0;
2565
2566         DEBUG(4,("_spoolss_getprinterdata\n"));
2567
2568         if ( !Printer ) {
2569                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2570                 status = WERR_BADFID;
2571                 goto done;
2572         }
2573
2574         unistr2_to_ascii(value, valuename, sizeof(value));
2575
2576         if ( Printer->printer_type == SPLHND_SERVER )
2577                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2578         else
2579         {
2580                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2581                         status = WERR_BADFID;
2582                         goto done;
2583                 }
2584
2585                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2586                 if ( !W_ERROR_IS_OK(status) )
2587                         goto done;
2588
2589                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2590
2591                 if ( strequal(value, "ChangeId") ) {
2592                         *type = REG_DWORD;
2593                         *needed = sizeof(uint32);
2594                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2595                                 status = WERR_NOMEM;
2596                                 goto done;
2597                         }
2598                         SIVAL( *data, 0, printer->info_2->changeid );
2599                         status = WERR_OK;
2600                 }
2601                 else
2602                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2603         }
2604
2605         if (*needed > *out_size)
2606                 status = WERR_MORE_DATA;
2607
2608 done:
2609         if ( !W_ERROR_IS_OK(status) )
2610         {
2611                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2612
2613                 /* reply this param doesn't exist */
2614
2615                 if ( *out_size ) {
2616                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2617                                 if ( printer )
2618                                         free_a_printer( &printer, 2 );
2619                                 return WERR_NOMEM;
2620                         }
2621                 } else {
2622                         *data = NULL;
2623                 }
2624         }
2625
2626         /* cleanup & exit */
2627
2628         if ( printer )
2629                 free_a_printer( &printer, 2 );
2630
2631         return status;
2632 }
2633
2634 /*********************************************************
2635  Connect to the client machine.
2636 **********************************************************/
2637
2638 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2639                         struct sockaddr_storage *client_ss, const char *remote_machine)
2640 {
2641         NTSTATUS ret;
2642         struct cli_state *the_cli;
2643         struct sockaddr_storage rm_addr;
2644
2645         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2646                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2647                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2648                         return False;
2649                 }
2650
2651                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2652                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2653                         return False;
2654                 }
2655         } else {
2656                 char addr[INET6_ADDRSTRLEN];
2657                 rm_addr = *client_ss;
2658                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2659                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2660                         addr));
2661         }
2662
2663         /* setup the connection */
2664
2665         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2666                 &rm_addr, 0, "IPC$", "IPC",
2667                 "", /* username */
2668                 "", /* domain */
2669                 "", /* password */
2670                 0, lp_client_signing(), NULL );
2671
2672         if ( !NT_STATUS_IS_OK( ret ) ) {
2673                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2674                         remote_machine ));
2675                 return False;
2676         }
2677
2678         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2679                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2680                 cli_shutdown(the_cli);
2681                 return False;
2682         }
2683
2684         /*
2685          * Ok - we have an anonymous connection to the IPC$ share.
2686          * Now start the NT Domain stuff :-).
2687          */
2688
2689         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2690         if (!NT_STATUS_IS_OK(ret)) {
2691                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2692                         remote_machine, nt_errstr(ret)));
2693                 cli_shutdown(the_cli);
2694                 return False;
2695         }
2696
2697         return True;
2698 }
2699
2700 /***************************************************************************
2701  Connect to the client.
2702 ****************************************************************************/
2703
2704 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2705                                         uint32 localprinter, uint32 type,
2706                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2707 {
2708         WERROR result;
2709
2710         /*
2711          * If it's the first connection, contact the client
2712          * and connect to the IPC$ share anonymously
2713          */
2714         if (smb_connections==0) {
2715                 fstring unix_printer;
2716
2717                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2718
2719                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2720                         return False;
2721
2722                 messaging_register(smbd_messaging_context(), NULL,
2723                                    MSG_PRINTER_NOTIFY2,
2724                                    receive_notify2_message_list);
2725                 /* Tell the connections db we're now interested in printer
2726                  * notify messages. */
2727                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2728         }
2729
2730         /*
2731          * Tell the specific printing tdb we want messages for this printer
2732          * by registering our PID.
2733          */
2734
2735         if (!print_notify_register_pid(snum))
2736                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2737
2738         smb_connections++;
2739
2740         result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2741                         talloc_tos(),
2742                         printer,
2743                         localprinter,
2744                         type,
2745                         handle);
2746
2747         if (!W_ERROR_IS_OK(result))
2748                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2749                         win_errstr(result)));
2750
2751         return (W_ERROR_IS_OK(result));
2752 }
2753
2754 /********************************************************************
2755  * _spoolss_rffpcnex
2756  * ReplyFindFirstPrinterChangeNotifyEx
2757  *
2758  * before replying OK: status=0 a rpc call is made to the workstation
2759  * asking ReplyOpenPrinter
2760  *
2761  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2762  * called from api_spoolss_rffpcnex
2763  ********************************************************************/
2764
2765 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2766 {
2767         POLICY_HND *handle = &q_u->handle;
2768         uint32 flags = q_u->flags;
2769         uint32 options = q_u->options;
2770         UNISTR2 *localmachine = &q_u->localmachine;
2771         uint32 printerlocal = q_u->printerlocal;
2772         int snum = -1;
2773         SPOOL_NOTIFY_OPTION *option = q_u->option;
2774         struct sockaddr_storage client_ss;
2775
2776         /* store the notify value in the printer struct */
2777
2778         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2779
2780         if (!Printer) {
2781                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2782                 return WERR_BADFID;
2783         }
2784
2785         Printer->notify.flags=flags;
2786         Printer->notify.options=options;
2787         Printer->notify.printerlocal=printerlocal;
2788
2789         if (Printer->notify.option)
2790                 free_spool_notify_option(&Printer->notify.option);
2791
2792         Printer->notify.option=dup_spool_notify_option(option);
2793
2794         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2795                        sizeof(Printer->notify.localmachine));
2796
2797         /* Connect to the client machine and send a ReplyOpenPrinter */
2798
2799         if ( Printer->printer_type == SPLHND_SERVER)
2800                 snum = -1;
2801         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2802                         !get_printer_snum(p, handle, &snum, NULL) )
2803                 return WERR_BADFID;
2804
2805         if (!interpret_string_addr(&client_ss, p->client_address,
2806                                    AI_NUMERICHOST)) {
2807                 return WERR_SERVER_UNAVAILABLE;
2808         }
2809
2810         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2811                                         Printer->notify.printerlocal, 1,
2812                                         &Printer->notify.client_hnd, &client_ss))
2813                 return WERR_SERVER_UNAVAILABLE;
2814
2815         Printer->notify.client_connected=True;
2816
2817         return WERR_OK;
2818 }
2819
2820 /*******************************************************************
2821  * fill a notify_info_data with the servername
2822  ********************************************************************/
2823
2824 void spoolss_notify_server_name(int snum,
2825                                        SPOOL_NOTIFY_INFO_DATA *data,
2826                                        print_queue_struct *queue,
2827                                        NT_PRINTER_INFO_LEVEL *printer,
2828                                        TALLOC_CTX *mem_ctx)
2829 {
2830         smb_ucs2_t *temp = NULL;
2831         uint32 len;
2832
2833         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2834         if (len == (uint32)-1) {
2835                 len = 0;
2836         }
2837
2838         data->notify_data.data.length = len;
2839         if (len) {
2840                 data->notify_data.data.string = (uint16 *)temp;
2841         } else {
2842                 data->notify_data.data.string = NULL;
2843         }
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the printername (not including the servername).
2848  ********************************************************************/
2849
2850 void spoolss_notify_printer_name(int snum,
2851                                         SPOOL_NOTIFY_INFO_DATA *data,
2852                                         print_queue_struct *queue,
2853                                         NT_PRINTER_INFO_LEVEL *printer,
2854                                         TALLOC_CTX *mem_ctx)
2855 {
2856         smb_ucs2_t *temp = NULL;
2857         uint32 len;
2858
2859         /* the notify name should not contain the \\server\ part */
2860         char *p = strrchr(printer->info_2->printername, '\\');
2861
2862         if (!p) {
2863                 p = printer->info_2->printername;
2864         } else {
2865                 p++;
2866         }
2867
2868         len = rpcstr_push_talloc(mem_ctx, &temp, p);
2869         if (len == (uint32)-1) {
2870                 len = 0;
2871         }
2872
2873         data->notify_data.data.length = len;
2874         if (len) {
2875                 data->notify_data.data.string = (uint16 *)temp;
2876         } else {
2877                 data->notify_data.data.string = NULL;
2878         }
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the servicename
2883  ********************************************************************/
2884
2885 void spoolss_notify_share_name(int snum,
2886                                       SPOOL_NOTIFY_INFO_DATA *data,
2887                                       print_queue_struct *queue,
2888                                       NT_PRINTER_INFO_LEVEL *printer,
2889                                       TALLOC_CTX *mem_ctx)
2890 {
2891         smb_ucs2_t *temp = NULL;
2892         uint32 len;
2893
2894         len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2895         if (len == (uint32)-1) {
2896                 len = 0;
2897         }
2898
2899         data->notify_data.data.length = len;
2900         if (len) {
2901                 data->notify_data.data.string = (uint16 *)temp;
2902         } else {
2903                 data->notify_data.data.string = NULL;
2904         }
2905
2906 }
2907
2908 /*******************************************************************
2909  * fill a notify_info_data with the port name
2910  ********************************************************************/
2911
2912 void spoolss_notify_port_name(int snum,
2913                                      SPOOL_NOTIFY_INFO_DATA *data,
2914                                      print_queue_struct *queue,
2915                                      NT_PRINTER_INFO_LEVEL *printer,
2916                                      TALLOC_CTX *mem_ctx)
2917 {
2918         smb_ucs2_t *temp = NULL;
2919         uint32 len;
2920
2921         /* even if it's strange, that's consistant in all the code */
2922
2923         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2924         if (len == (uint32)-1) {
2925                 len = 0;
2926         }
2927
2928         data->notify_data.data.length = len;
2929         if (len) {
2930                 data->notify_data.data.string = (uint16 *)temp;
2931         } else {
2932                 data->notify_data.data.string = NULL;
2933         }
2934 }
2935
2936 /*******************************************************************
2937  * fill a notify_info_data with the printername
2938  * but it doesn't exist, have to see what to do
2939  ********************************************************************/
2940
2941 void spoolss_notify_driver_name(int snum,
2942                                        SPOOL_NOTIFY_INFO_DATA *data,
2943                                        print_queue_struct *queue,
2944                                        NT_PRINTER_INFO_LEVEL *printer,
2945                                        TALLOC_CTX *mem_ctx)
2946 {
2947         smb_ucs2_t *temp = NULL;
2948         uint32 len;
2949
2950         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2951         if (len == (uint32)-1) {
2952                 len = 0;
2953         }
2954
2955         data->notify_data.data.length = len;
2956         if (len) {
2957                 data->notify_data.data.string = (uint16 *)temp;
2958         } else {
2959                 data->notify_data.data.string = NULL;
2960         }
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the comment
2965  ********************************************************************/
2966
2967 void spoolss_notify_comment(int snum,
2968                                    SPOOL_NOTIFY_INFO_DATA *data,
2969                                    print_queue_struct *queue,
2970                                    NT_PRINTER_INFO_LEVEL *printer,
2971                                    TALLOC_CTX *mem_ctx)
2972 {
2973         smb_ucs2_t *temp = NULL;
2974         uint32 len;
2975
2976         if (*printer->info_2->comment == '\0')
2977                 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2978         else
2979                 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2980
2981         if (len == (uint32)-1) {
2982                 len = 0;
2983         }
2984         data->notify_data.data.length = len;
2985         if (len) {
2986                 data->notify_data.data.string = (uint16 *)temp;
2987         } else {
2988                 data->notify_data.data.string = NULL;
2989         }
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the comment
2994  * location = "Room 1, floor 2, building 3"
2995  ********************************************************************/
2996
2997 void spoolss_notify_location(int snum,
2998                                     SPOOL_NOTIFY_INFO_DATA *data,
2999                                     print_queue_struct *queue,
3000                                     NT_PRINTER_INFO_LEVEL *printer,
3001                                     TALLOC_CTX *mem_ctx)
3002 {
3003         smb_ucs2_t *temp = NULL;
3004         uint32 len;
3005
3006         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
3007         if (len == (uint32)-1) {
3008                 len = 0;
3009         }
3010
3011         data->notify_data.data.length = len;
3012         if (len) {
3013                 data->notify_data.data.string = (uint16 *)temp;
3014         } else {
3015                 data->notify_data.data.string = NULL;
3016         }
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the device mode
3021  * jfm:xxxx don't to it for know but that's a real problem !!!
3022  ********************************************************************/
3023
3024 static void spoolss_notify_devmode(int snum,
3025                                    SPOOL_NOTIFY_INFO_DATA *data,
3026                                    print_queue_struct *queue,
3027                                    NT_PRINTER_INFO_LEVEL *printer,
3028                                    TALLOC_CTX *mem_ctx)
3029 {
3030         /* for a dummy implementation we have to zero the fields */
3031         data->notify_data.data.length = 0;
3032         data->notify_data.data.string = NULL;
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the separator file name
3037  ********************************************************************/
3038
3039 void spoolss_notify_sepfile(int snum,
3040                                    SPOOL_NOTIFY_INFO_DATA *data,
3041                                    print_queue_struct *queue,
3042                                    NT_PRINTER_INFO_LEVEL *printer,
3043                                    TALLOC_CTX *mem_ctx)
3044 {
3045         smb_ucs2_t *temp = NULL;
3046         uint32 len;
3047
3048         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
3049         if (len == (uint32)-1) {
3050                 len = 0;
3051         }
3052
3053         data->notify_data.data.length = len;
3054         if (len) {
3055                 data->notify_data.data.string = (uint16 *)temp;
3056         } else {
3057                 data->notify_data.data.string = NULL;
3058         }
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the print processor
3063  * jfm:xxxx return always winprint to indicate we don't do anything to it
3064  ********************************************************************/
3065
3066 void spoolss_notify_print_processor(int snum,
3067                                            SPOOL_NOTIFY_INFO_DATA *data,
3068                                            print_queue_struct *queue,
3069                                            NT_PRINTER_INFO_LEVEL *printer,
3070                                            TALLOC_CTX *mem_ctx)
3071 {
3072         smb_ucs2_t *temp = NULL;
3073         uint32 len;
3074
3075         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3076         if (len == (uint32)-1) {
3077                 len = 0;
3078         }
3079
3080         data->notify_data.data.length = len;
3081         if (len) {
3082                 data->notify_data.data.string = (uint16 *)temp;
3083         } else {
3084                 data->notify_data.data.string = NULL;
3085         }
3086 }
3087
3088 /*******************************************************************
3089  * fill a notify_info_data with the print processor options
3090  * jfm:xxxx send an empty string
3091  ********************************************************************/
3092
3093 void spoolss_notify_parameters(int snum,
3094                                       SPOOL_NOTIFY_INFO_DATA *data,
3095                                       print_queue_struct *queue,
3096                                       NT_PRINTER_INFO_LEVEL *printer,
3097                                       TALLOC_CTX *mem_ctx)
3098 {
3099         smb_ucs2_t *temp = NULL;
3100         uint32 len;
3101
3102         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3103         if (len == (uint32)-1) {
3104                 len = 0;
3105         }
3106
3107         data->notify_data.data.length = len;
3108         if (len) {
3109                 data->notify_data.data.string = (uint16 *)temp;
3110         } else {
3111                 data->notify_data.data.string = NULL;
3112         }
3113 }
3114
3115 /*******************************************************************
3116  * fill a notify_info_data with the data type
3117  * jfm:xxxx always send RAW as data type
3118  ********************************************************************/
3119
3120 void spoolss_notify_datatype(int snum,
3121                                     SPOOL_NOTIFY_INFO_DATA *data,
3122                                     print_queue_struct *queue,
3123                                     NT_PRINTER_INFO_LEVEL *printer,
3124                                     TALLOC_CTX *mem_ctx)
3125 {
3126         smb_ucs2_t *temp = NULL;
3127         uint32 len;
3128
3129         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3130         if (len == (uint32)-1) {
3131                 len = 0;
3132         }
3133
3134         data->notify_data.data.length = len;
3135         if (len) {
3136                 data->notify_data.data.string = (uint16 *)temp;
3137         } else {
3138                 data->notify_data.data.string = NULL;
3139         }
3140 }
3141
3142 /*******************************************************************
3143  * fill a notify_info_data with the security descriptor
3144  * jfm:xxxx send an null pointer to say no security desc
3145  * have to implement security before !
3146  ********************************************************************/
3147
3148 static void spoolss_notify_security_desc(int snum,
3149                                          SPOOL_NOTIFY_INFO_DATA *data,
3150                                          print_queue_struct *queue,
3151                                          NT_PRINTER_INFO_LEVEL *printer,
3152                                          TALLOC_CTX *mem_ctx)
3153 {
3154         data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3155         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3156 }
3157
3158 /*******************************************************************
3159  * fill a notify_info_data with the attributes
3160  * jfm:xxxx a samba printer is always shared
3161  ********************************************************************/
3162
3163 void spoolss_notify_attributes(int snum,
3164                                       SPOOL_NOTIFY_INFO_DATA *data,
3165                                       print_queue_struct *queue,
3166                                       NT_PRINTER_INFO_LEVEL *printer,
3167                                       TALLOC_CTX *mem_ctx)
3168 {
3169         data->notify_data.value[0] = printer->info_2->attributes;
3170         data->notify_data.value[1] = 0;
3171 }
3172
3173 /*******************************************************************
3174  * fill a notify_info_data with the priority
3175  ********************************************************************/
3176
3177 static void spoolss_notify_priority(int snum,
3178                                     SPOOL_NOTIFY_INFO_DATA *data,
3179                                     print_queue_struct *queue,
3180                                     NT_PRINTER_INFO_LEVEL *printer,
3181                                     TALLOC_CTX *mem_ctx)
3182 {
3183         data->notify_data.value[0] = printer->info_2->priority;
3184         data->notify_data.value[1] = 0;
3185 }
3186
3187 /*******************************************************************
3188  * fill a notify_info_data with the default priority
3189  ********************************************************************/
3190
3191 static void spoolss_notify_default_priority(int snum,
3192                                             SPOOL_NOTIFY_INFO_DATA *data,
3193                                             print_queue_struct *queue,
3194                                             NT_PRINTER_INFO_LEVEL *printer,
3195                                             TALLOC_CTX *mem_ctx)
3196 {
3197         data->notify_data.value[0] = printer->info_2->default_priority;
3198         data->notify_data.value[1] = 0;
3199 }
3200
3201 /*******************************************************************
3202  * fill a notify_info_data with the start time
3203  ********************************************************************/
3204
3205 static void spoolss_notify_start_time(int snum,
3206                                       SPOOL_NOTIFY_INFO_DATA *data,
3207                                       print_queue_struct *queue,
3208                                       NT_PRINTER_INFO_LEVEL *printer,
3209                                       TALLOC_CTX *mem_ctx)
3210 {
3211         data->notify_data.value[0] = printer->info_2->starttime;
3212         data->notify_data.value[1] = 0;
3213 }
3214
3215 /*******************************************************************
3216  * fill a notify_info_data with the until time
3217  ********************************************************************/
3218
3219 static void spoolss_notify_until_time(int snum,
3220                                       SPOOL_NOTIFY_INFO_DATA *data,
3221                                       print_queue_struct *queue,
3222                                       NT_PRINTER_INFO_LEVEL *printer,
3223                                       TALLOC_CTX *mem_ctx)
3224 {
3225         data->notify_data.value[0] = printer->info_2->untiltime;
3226         data->notify_data.value[1] = 0;
3227 }
3228
3229 /*******************************************************************
3230  * fill a notify_info_data with the status
3231  ********************************************************************/
3232
3233 static void spoolss_notify_status(int snum,
3234                                   SPOOL_NOTIFY_INFO_DATA *data,
3235                                   print_queue_struct *queue,
3236                                   NT_PRINTER_INFO_LEVEL *printer,
3237                                   TALLOC_CTX *mem_ctx)
3238 {
3239         print_status_struct status;
3240
3241         print_queue_length(snum, &status);
3242         data->notify_data.value[0]=(uint32) status.status;
3243         data->notify_data.value[1] = 0;
3244 }
3245
3246 /*******************************************************************
3247  * fill a notify_info_data with the number of jobs queued
3248  ********************************************************************/
3249
3250 void spoolss_notify_cjobs(int snum,
3251                                  SPOOL_NOTIFY_INFO_DATA *data,
3252                                  print_queue_struct *queue,
3253                                  NT_PRINTER_INFO_LEVEL *printer,
3254                                  TALLOC_CTX *mem_ctx)
3255 {
3256         data->notify_data.value[0] = print_queue_length(snum, NULL);
3257         data->notify_data.value[1] = 0;
3258 }
3259
3260 /*******************************************************************
3261  * fill a notify_info_data with the average ppm
3262  ********************************************************************/
3263
3264 static void spoolss_notify_average_ppm(int snum,
3265                                        SPOOL_NOTIFY_INFO_DATA *data,
3266                                        print_queue_struct *queue,
3267                                        NT_PRINTER_INFO_LEVEL *printer,
3268                                        TALLOC_CTX *mem_ctx)
3269 {
3270         /* always respond 8 pages per minutes */
3271         /* a little hard ! */
3272         data->notify_data.value[0] = printer->info_2->averageppm;
3273         data->notify_data.value[1] = 0;
3274 }
3275
3276 /*******************************************************************
3277  * fill a notify_info_data with username
3278  ********************************************************************/
3279
3280 static void spoolss_notify_username(int snum,
3281                                     SPOOL_NOTIFY_INFO_DATA *data,
3282                                     print_queue_struct *queue,
3283                                     NT_PRINTER_INFO_LEVEL *printer,
3284                                     TALLOC_CTX *mem_ctx)
3285 {
3286         smb_ucs2_t *temp = NULL;
3287         uint32 len;
3288
3289         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3290         if (len == (uint32)-1) {
3291                 len = 0;
3292         }
3293
3294         data->notify_data.data.length = len;
3295         if (len) {
3296                 data->notify_data.data.string = (uint16 *)temp;
3297         } else {
3298                 data->notify_data.data.string = NULL;
3299         }
3300 }
3301
3302 /*******************************************************************
3303  * fill a notify_info_data with job status
3304  ********************************************************************/
3305
3306 static void spoolss_notify_job_status(int snum,
3307                                       SPOOL_NOTIFY_INFO_DATA *data,
3308                                       print_queue_struct *queue,
3309                                       NT_PRINTER_INFO_LEVEL *printer,
3310                                       TALLOC_CTX *mem_ctx)
3311 {
3312         data->notify_data.value[0]=nt_printj_status(queue->status);
3313         data->notify_data.value[1] = 0;
3314 }
3315
3316 /*******************************************************************
3317  * fill a notify_info_data with job name
3318  ********************************************************************/
3319
3320 static void spoolss_notify_job_name(int snum,
3321                                     SPOOL_NOTIFY_INFO_DATA *data,
3322                                     print_queue_struct *queue,
3323                                     NT_PRINTER_INFO_LEVEL *printer,
3324                                     TALLOC_CTX *mem_ctx)
3325 {
3326         smb_ucs2_t *temp = NULL;
3327         uint32 len;
3328
3329         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3330         if (len == (uint32)-1) {
3331                 len = 0;
3332         }
3333
3334         data->notify_data.data.length = len;
3335         if (len) {
3336                 data->notify_data.data.string = (uint16 *)temp;
3337         } else {
3338                 data->notify_data.data.string = NULL;
3339         }
3340 }
3341
3342 /*******************************************************************
3343  * fill a notify_info_data with job status
3344  ********************************************************************/
3345
3346 static void spoolss_notify_job_status_string(int snum,
3347                                              SPOOL_NOTIFY_INFO_DATA *data,
3348                                              print_queue_struct *queue,
3349                                              NT_PRINTER_INFO_LEVEL *printer,
3350                                              TALLOC_CTX *mem_ctx)
3351 {
3352         /*
3353          * Now we're returning job status codes we just return a "" here. JRA.
3354          */
3355
3356         const char *p = "";
3357         smb_ucs2_t *temp = NULL;
3358         uint32 len;
3359
3360 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3361         p = "unknown";
3362
3363         switch (queue->status) {
3364         case LPQ_QUEUED:
3365                 p = "Queued";
3366                 break;
3367         case LPQ_PAUSED:
3368                 p = "";    /* NT provides the paused string */
3369                 break;
3370         case LPQ_SPOOLING:
3371                 p = "Spooling";
3372                 break;
3373         case LPQ_PRINTING:
3374                 p = "Printing";
3375                 break;
3376         }
3377 #endif /* NO LONGER NEEDED. */
3378
3379         len = rpcstr_push_talloc(mem_ctx, &temp, p);
3380         if (len == (uint32)-1) {
3381                 len = 0;
3382         }
3383
3384         data->notify_data.data.length = len;
3385         if (len) {
3386                 data->notify_data.data.string = (uint16 *)temp;
3387         } else {
3388                 data->notify_data.data.string = NULL;
3389         }
3390 }
3391
3392 /*******************************************************************
3393  * fill a notify_info_data with job time
3394  ********************************************************************/
3395
3396 static void spoolss_notify_job_time(int snum,
3397                                     SPOOL_NOTIFY_INFO_DATA *data,
3398                                     print_queue_struct *queue,
3399                                     NT_PRINTER_INFO_LEVEL *printer,
3400                                     TALLOC_CTX *mem_ctx)
3401 {
3402         data->notify_data.value[0]=0x0;
3403         data->notify_data.value[1]=0;
3404 }
3405
3406 /*******************************************************************
3407  * fill a notify_info_data with job size
3408  ********************************************************************/
3409
3410 static void spoolss_notify_job_size(int snum,
3411                                     SPOOL_NOTIFY_INFO_DATA *data,
3412                                     print_queue_struct *queue,
3413                                     NT_PRINTER_INFO_LEVEL *printer,
3414                                     TALLOC_CTX *mem_ctx)
3415 {
3416         data->notify_data.value[0]=queue->size;
3417         data->notify_data.value[1]=0;
3418 }
3419
3420 /*******************************************************************
3421  * fill a notify_info_data with page info
3422  ********************************************************************/
3423 static void spoolss_notify_total_pages(int snum,
3424                                 SPOOL_NOTIFY_INFO_DATA *data,
3425                                 print_queue_struct *queue,
3426                                 NT_PRINTER_INFO_LEVEL *printer,
3427                                 TALLOC_CTX *mem_ctx)
3428 {
3429         data->notify_data.value[0]=queue->page_count;
3430         data->notify_data.value[1]=0;
3431 }
3432
3433 /*******************************************************************
3434  * fill a notify_info_data with pages printed info.
3435  ********************************************************************/
3436 static void spoolss_notify_pages_printed(int snum,
3437                                 SPOOL_NOTIFY_INFO_DATA *data,
3438                                 print_queue_struct *queue,
3439                                 NT_PRINTER_INFO_LEVEL *printer,
3440                                 TALLOC_CTX *mem_ctx)
3441 {
3442         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3443         data->notify_data.value[1]=0;
3444 }
3445
3446 /*******************************************************************
3447  Fill a notify_info_data with job position.
3448  ********************************************************************/
3449
3450 static void spoolss_notify_job_position(int snum,
3451                                         SPOOL_NOTIFY_INFO_DATA *data,
3452                                         print_queue_struct *queue,
3453                                         NT_PRINTER_INFO_LEVEL *printer,
3454                                         TALLOC_CTX *mem_ctx)
3455 {
3456         data->notify_data.value[0]=queue->job;
3457         data->notify_data.value[1]=0;
3458 }
3459
3460 /*******************************************************************
3461  Fill a notify_info_data with submitted time.
3462  ********************************************************************/
3463
3464 static void spoolss_notify_submitted_time(int snum,
3465                                           SPOOL_NOTIFY_INFO_DATA *data,
3466                                           print_queue_struct *queue,
3467                                           NT_PRINTER_INFO_LEVEL *printer,
3468                                           TALLOC_CTX *mem_ctx)
3469 {
3470         struct tm *t;
3471         uint32 len;
3472         SYSTEMTIME st;
3473         char *p;
3474
3475         t=gmtime(&queue->time);
3476
3477         len = sizeof(SYSTEMTIME);
3478
3479         data->notify_data.data.length = len;
3480         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3481
3482         if (!data->notify_data.data.string) {
3483                 data->notify_data.data.length = 0;
3484                 return;
3485         }
3486
3487         make_systemtime(&st, t);
3488
3489         /*
3490          * Systemtime must be linearized as a set of UINT16's.
3491          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3492          */
3493
3494         p = (char *)data->notify_data.data.string;
3495         SSVAL(p, 0, st.year);
3496         SSVAL(p, 2, st.month);
3497         SSVAL(p, 4, st.dayofweek);
3498         SSVAL(p, 6, st.day);
3499         SSVAL(p, 8, st.hour);
3500         SSVAL(p, 10, st.minute);
3501         SSVAL(p, 12, st.second);
3502         SSVAL(p, 14, st.milliseconds);
3503 }
3504
3505 struct s_notify_info_data_table
3506 {
3507         uint16 type;
3508         uint16 field;
3509         const char *name;
3510         uint32 size;
3511         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3512                     print_queue_struct *queue,
3513                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3514 };
3515
3516 /* A table describing the various print notification constants and
3517    whether the notification data is a pointer to a variable sized
3518    buffer, a one value uint32 or a two value uint32. */
3519
3520 static const struct s_notify_info_data_table notify_info_data_table[] =
3521 {
3522 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3523 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3524 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3525 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3526 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3527 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3528 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3529 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3530 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3531 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3532 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3533 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3534 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3535 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3536 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3537 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3538 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3539 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3540 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3541 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3542 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3543 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3544 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3545 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3546 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3547 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3548 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3549 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3550 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3551 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3552 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3553 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3554 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3555 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3556 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3557 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3558 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3559 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3560 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3561 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3562 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3563 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3564 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3565 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3566 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3567 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3568 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3569 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3570 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3571 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3572 };
3573
3574 /*******************************************************************
3575  Return the size of info_data structure.
3576 ********************************************************************/
3577
3578 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3579 {
3580         int i=0;
3581
3582         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3583                 if ( (notify_info_data_table[i].type == type)
3584                         && (notify_info_data_table[i].field == field) ) {
3585                         switch(notify_info_data_table[i].size) {
3586                                 case NOTIFY_ONE_VALUE:
3587                                 case NOTIFY_TWO_VALUE:
3588                                         return 1;
3589                                 case NOTIFY_STRING:
3590                                         return 2;
3591
3592                                 /* The only pointer notify data I have seen on
3593                                    the wire is the submitted time and this has
3594                                    the notify size set to 4. -tpot */
3595
3596                                 case NOTIFY_POINTER:
3597                                         return 4;
3598
3599                                 case NOTIFY_SECDESC:
3600                                         return 5;
3601                         }
3602                 }
3603         }
3604
3605         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3606
3607         return 0;
3608 }
3609
3610 /*******************************************************************
3611  Return the type of notify_info_data.
3612 ********************************************************************/
3613
3614 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3615 {
3616         uint32 i=0;
3617
3618         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3619                 if (notify_info_data_table[i].type == type &&
3620                     notify_info_data_table[i].field == field)
3621                         return notify_info_data_table[i].size;
3622         }
3623
3624         return 0;
3625 }
3626
3627 /****************************************************************************
3628 ****************************************************************************/
3629
3630 static bool search_notify(uint16 type, uint16 field, int *value)
3631 {
3632         int i;
3633
3634         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3635                 if (notify_info_data_table[i].type == type &&
3636                     notify_info_data_table[i].field == field &&
3637                     notify_info_data_table[i].fn != NULL) {
3638                         *value = i;
3639                         return True;
3640                 }
3641         }
3642
3643         return False;
3644 }
3645
3646 /****************************************************************************
3647 ****************************************************************************/
3648
3649 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3650 {
3651         info_data->type     = type;
3652         info_data->field    = field;
3653         info_data->reserved = 0;
3654
3655         info_data->size     = size_of_notify_info_data(type, field);
3656         info_data->enc_type = type_of_notify_info_data(type, field);
3657
3658         info_data->id = id;
3659 }
3660
3661 /*******************************************************************
3662  *
3663  * fill a notify_info struct with info asked
3664  *
3665  ********************************************************************/
3666
3667 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3668                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3669                                           *option_type, uint32 id,
3670                                           TALLOC_CTX *mem_ctx)
3671 {
3672         int field_num,j;
3673         uint16 type;
3674         uint16 field;
3675
3676         SPOOL_NOTIFY_INFO_DATA *current_data;
3677         NT_PRINTER_INFO_LEVEL *printer = NULL;
3678         print_queue_struct *queue=NULL;
3679
3680         type=option_type->type;
3681
3682         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3683                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3684                 option_type->count, lp_servicename(snum)));
3685
3686         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3687                 return False;
3688
3689         for(field_num=0; field_num<option_type->count; field_num++) {
3690                 field = option_type->fields[field_num];
3691
3692                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3693
3694                 if (!search_notify(type, field, &j) )
3695                         continue;
3696
3697                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3698                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3699                         free_a_printer(&printer, 2);
3700                         return False;
3701                 }
3702
3703                 current_data = &info->data[info->count];
3704
3705                 construct_info_data(current_data, type, field, id);
3706
3707                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3708                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3709
3710                 notify_info_data_table[j].fn(snum, current_data, queue,
3711                                              printer, mem_ctx);
3712
3713                 info->count++;
3714         }
3715
3716         free_a_printer(&printer, 2);
3717         return True;
3718 }
3719
3720 /*******************************************************************
3721  *
3722  * fill a notify_info struct with info asked
3723  *
3724  ********************************************************************/
3725
3726 static bool construct_notify_jobs_info(print_queue_struct *queue,
3727                                        SPOOL_NOTIFY_INFO *info,
3728                                        NT_PRINTER_INFO_LEVEL *printer,
3729                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3730                                        *option_type, uint32 id,
3731                                        TALLOC_CTX *mem_ctx)
3732 {
3733         int field_num,j;
3734         uint16 type;
3735         uint16 field;
3736
3737         SPOOL_NOTIFY_INFO_DATA *current_data;
3738
3739         DEBUG(4,("construct_notify_jobs_info\n"));
3740
3741         type = option_type->type;
3742
3743         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3744                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3745                 option_type->count));
3746
3747         for(field_num=0; field_num<option_type->count; field_num++) {
3748                 field = option_type->fields[field_num];
3749
3750                 if (!search_notify(type, field, &j) )
3751                         continue;
3752
3753                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3754                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3755                         return False;
3756                 }
3757
3758                 current_data=&(info->data[info->count]);
3759
3760                 construct_info_data(current_data, type, field, id);
3761                 notify_info_data_table[j].fn(snum, current_data, queue,
3762                                              printer, mem_ctx);
3763                 info->count++;
3764         }
3765
3766         return True;
3767 }
3768
3769 /*
3770  * JFM: The enumeration is not that simple, it's even non obvious.
3771  *
3772  * let's take an example: I want to monitor the PRINTER SERVER for
3773  * the printer's name and the number of jobs currently queued.
3774  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3775  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3776  *
3777  * I have 3 printers on the back of my server.
3778  *
3779  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3780  * structures.
3781  *   Number     Data                    Id
3782  *      1       printer 1 name          1
3783  *      2       printer 1 cjob          1
3784  *      3       printer 2 name          2
3785  *      4       printer 2 cjob          2
3786  *      5       printer 3 name          3
3787  *      6       printer 3 name          3
3788  *
3789  * that's the print server case, the printer case is even worse.
3790  */
3791
3792 /*******************************************************************
3793  *
3794  * enumerate all printers on the printserver
3795  * fill a notify_info struct with info asked
3796  *
3797  ********************************************************************/
3798
3799 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3800                                       SPOOL_NOTIFY_INFO *info,
3801                                       TALLOC_CTX *mem_ctx)
3802 {
3803         int snum;
3804         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3805         int n_services=lp_numservices();
3806         int i;
3807         SPOOL_NOTIFY_OPTION *option;
3808         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3809
3810         DEBUG(4,("printserver_notify_info\n"));
3811
3812         if (!Printer)
3813                 return WERR_BADFID;
3814
3815         option=Printer->notify.option;
3816         info->version=2;
3817         info->data=NULL;
3818         info->count=0;
3819
3820         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3821            sending a ffpcn() request first */
3822
3823         if ( !option )
3824                 return WERR_BADFID;
3825
3826         for (i=0; i<option->count; i++) {
3827                 option_type=&(option->ctr.type[i]);
3828
3829                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3830                         continue;
3831
3832                 for (snum=0; snum<n_services; snum++)
3833                 {
3834                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3835                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3836                 }
3837         }
3838
3839 #if 0
3840         /*
3841          * Debugging information, don't delete.
3842          */
3843
3844         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3845         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3846         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3847
3848         for (i=0; i<info->count; i++) {
3849                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3850                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3851                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3852         }
3853 #endif
3854
3855         return WERR_OK;
3856 }
3857
3858 /*******************************************************************
3859  *
3860  * fill a notify_info struct with info asked
3861  *
3862  ********************************************************************/
3863
3864 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3865                                   TALLOC_CTX *mem_ctx)
3866 {
3867         int snum;
3868         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3869         int i;
3870         uint32 id;
3871         SPOOL_NOTIFY_OPTION *option;
3872         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3873         int count,j;
3874         print_queue_struct *queue=NULL;
3875         print_status_struct status;
3876
3877         DEBUG(4,("printer_notify_info\n"));
3878
3879         if (!Printer)
3880                 return WERR_BADFID;
3881
3882         option=Printer->notify.option;
3883         id = 0x0;
3884         info->version=2;
3885         info->data=NULL;
3886         info->count=0;
3887
3888         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3889            sending a ffpcn() request first */
3890
3891         if ( !option )
3892                 return WERR_BADFID;
3893
3894         get_printer_snum(p, hnd, &snum, NULL);
3895
3896         for (i=0; i<option->count; i++) {
3897                 option_type=&option->ctr.type[i];
3898
3899                 switch ( option_type->type ) {
3900                 case PRINTER_NOTIFY_TYPE:
3901                         if(construct_notify_printer_info(Printer, info, snum,
3902                                                          option_type, id,
3903                                                          mem_ctx))
3904                                 id--;
3905                         break;
3906
3907                 case JOB_NOTIFY_TYPE: {
3908                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3909
3910                         count = print_queue_status(snum, &queue, &status);
3911
3912                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3913                                 goto done;
3914
3915                         for (j=0; j<count; j++) {
3916                                 construct_notify_jobs_info(&queue[j], info,
3917                                                            printer, snum,
3918                                                            option_type,
3919                                                            queue[j].job,
3920                                                            mem_ctx);
3921                         }
3922
3923                         free_a_printer(&printer, 2);
3924
3925                 done:
3926                         SAFE_FREE(queue);
3927                         break;
3928                 }
3929                 }
3930         }
3931
3932         /*
3933          * Debugging information, don't delete.
3934          */
3935         /*
3936         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3937         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3938         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3939
3940         for (i=0; i<info->count; i++) {
3941                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3942                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3943                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3944         }
3945         */
3946         return WERR_OK;
3947 }
3948
3949 /********************************************************************
3950  * spoolss_rfnpcnex
3951  ********************************************************************/
3952
3953 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3954 {
3955         POLICY_HND *handle = &q_u->handle;
3956         SPOOL_NOTIFY_INFO *info = &r_u->info;
3957
3958         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3959         WERROR result = WERR_BADFID;
3960
3961         /* we always have a NOTIFY_INFO struct */
3962         r_u->info_ptr=0x1;
3963
3964         if (!Printer) {
3965                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3966                          OUR_HANDLE(handle)));
3967                 goto done;
3968         }
3969
3970         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3971
3972         /*
3973          *      We are now using the change value, and
3974          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3975          *      I don't have a global notification system, I'm sending back all the
3976          *      informations even when _NOTHING_ has changed.
3977          */
3978
3979         /* We need to keep track of the change value to send back in
3980            RRPCN replies otherwise our updates are ignored. */
3981
3982         Printer->notify.fnpcn = True;
3983
3984         if (Printer->notify.client_connected) {
3985                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3986                 Printer->notify.change = q_u->change;
3987         }
3988
3989         /* just ignore the SPOOL_NOTIFY_OPTION */
3990
3991         switch (Printer->printer_type) {
3992                 case SPLHND_SERVER:
3993                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3994                         break;
3995
3996                 case SPLHND_PRINTER:
3997                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3998                         break;
3999         }
4000
4001         Printer->notify.fnpcn = False;
4002
4003 done:
4004         return result;
4005 }
4006
4007 /********************************************************************
4008  * construct_printer_info_0
4009  * fill a printer_info_0 struct
4010  ********************************************************************/
4011
4012 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
4013 {
4014         char *chaine = NULL;
4015         int count;
4016         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4017         counter_printer_0 *session_counter;
4018         uint32 global_counter;
4019         struct tm *t;
4020         time_t setuptime;
4021         print_status_struct status;
4022         TALLOC_CTX *ctx = talloc_tos();
4023
4024         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4025                 return False;
4026
4027         init_unistr(&printer->printername, ntprinter->info_2->printername);
4028
4029         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
4030         if (!chaine) {
4031                 free_a_printer(&ntprinter,2);
4032                 return false;
4033         }
4034
4035         count = print_queue_length(snum, &status);
4036
4037         /* check if we already have a counter for this printer */
4038         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
4039                 if (session_counter->snum == snum)
4040                         break;
4041         }
4042
4043         init_unistr(&printer->servername, chaine);
4044
4045         /* it's the first time, add it to the list */
4046         if (session_counter==NULL) {
4047                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
4048                         free_a_printer(&ntprinter, 2);
4049                         return False;
4050                 }
4051                 ZERO_STRUCTP(session_counter);
4052                 session_counter->snum=snum;
4053                 session_counter->counter=0;
4054                 DLIST_ADD(counter_list, session_counter);
4055         }
4056
4057         /* increment it */
4058         session_counter->counter++;
4059
4060         /* JFM:
4061          * the global_counter should be stored in a TDB as it's common to all the clients
4062          * and should be zeroed on samba startup
4063          */
4064         global_counter=session_counter->counter;
4065         printer->cjobs = count;
4066         printer->total_jobs = 0;
4067         printer->total_bytes = 0;
4068
4069         setuptime = (time_t)ntprinter->info_2->setuptime;
4070         t=gmtime(&setuptime);
4071
4072         printer->year = t->tm_year+1900;
4073         printer->month = t->tm_mon+1;
4074         printer->dayofweek = t->tm_wday;
4075         printer->day = t->tm_mday;
4076         printer->hour = t->tm_hour;
4077         printer->minute = t->tm_min;
4078         printer->second = t->tm_sec;
4079         printer->milliseconds = 0;
4080
4081         printer->global_counter = global_counter;
4082         printer->total_pages = 0;
4083
4084         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4085         printer->major_version = 0x0005;        /* NT 5 */
4086         printer->build_version = 0x0893;        /* build 2195 */
4087
4088         printer->unknown7 = 0x1;
4089         printer->unknown8 = 0x0;
4090         printer->unknown9 = 0x0;
4091         printer->session_counter = session_counter->counter;
4092         printer->unknown11 = 0x0;
4093         printer->printer_errors = 0x0;          /* number of print failure */
4094         printer->unknown13 = 0x0;
4095         printer->unknown14 = 0x1;
4096         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4097         printer->unknown16 =  0x0;
4098         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4099         printer->unknown18 =  0x0;
4100         printer->status = nt_printq_status(status.status);
4101         printer->unknown20 =  0x0;
4102         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4103         printer->unknown22 = 0x0;
4104         printer->unknown23 = 0x6;               /* 6  ???*/
4105         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4106         printer->unknown25 = 0;
4107         printer->unknown26 = 0;
4108         printer->unknown27 = 0;
4109         printer->unknown28 = 0;
4110         printer->unknown29 = 0;
4111
4112         free_a_printer(&ntprinter,2);
4113         return (True);
4114 }
4115
4116 /********************************************************************
4117  * construct_printer_info_1
4118  * fill a printer_info_1 struct
4119  ********************************************************************/
4120 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4121 {
4122         char *chaine = NULL;
4123         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4124         TALLOC_CTX *ctx = talloc_tos();
4125
4126         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4127                 return false;
4128
4129         printer->flags=flags;
4130
4131         if (*ntprinter->info_2->comment == '\0') {
4132                 init_unistr(&printer->comment, lp_comment(snum));
4133                 chaine = talloc_asprintf(ctx,
4134                                 "%s,%s,%s", ntprinter->info_2->printername,
4135                                 ntprinter->info_2->drivername, lp_comment(snum));
4136         }
4137         else {
4138                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4139                 chaine = talloc_asprintf(ctx,
4140                                 "%s,%s,%s", ntprinter->info_2->printername,
4141                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4142         }
4143
4144         if (!chaine) {
4145                 free_a_printer(&ntprinter,2);
4146                 return false;
4147         }
4148
4149         init_unistr(&printer->description, chaine);
4150         init_unistr(&printer->name, ntprinter->info_2->printername);
4151
4152         free_a_printer(&ntprinter,2);
4153
4154         return True;
4155 }
4156
4157 /****************************************************************************
4158  Free a DEVMODE struct.
4159 ****************************************************************************/
4160
4161 static void free_dev_mode(DEVICEMODE *dev)
4162 {
4163         if (dev == NULL)
4164                 return;
4165
4166         SAFE_FREE(dev->dev_private);
4167         SAFE_FREE(dev);
4168 }
4169
4170
4171 /****************************************************************************
4172  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4173  should be valid upon entry
4174 ****************************************************************************/
4175
4176 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4177 {
4178         if ( !devmode || !ntdevmode )
4179                 return False;
4180
4181         init_unistr(&devmode->devicename, ntdevmode->devicename);
4182
4183         init_unistr(&devmode->formname, ntdevmode->formname);
4184
4185         devmode->specversion      = ntdevmode->specversion;
4186         devmode->driverversion    = ntdevmode->driverversion;
4187         devmode->size             = ntdevmode->size;
4188         devmode->driverextra      = ntdevmode->driverextra;
4189         devmode->fields           = ntdevmode->fields;
4190
4191         devmode->orientation      = ntdevmode->orientation;
4192         devmode->papersize        = ntdevmode->papersize;
4193         devmode->paperlength      = ntdevmode->paperlength;
4194         devmode->paperwidth       = ntdevmode->paperwidth;
4195         devmode->scale            = ntdevmode->scale;
4196         devmode->copies           = ntdevmode->copies;
4197         devmode->defaultsource    = ntdevmode->defaultsource;
4198         devmode->printquality     = ntdevmode->printquality;
4199         devmode->color            = ntdevmode->color;
4200         devmode->duplex           = ntdevmode->duplex;
4201         devmode->yresolution      = ntdevmode->yresolution;
4202         devmode->ttoption         = ntdevmode->ttoption;
4203         devmode->collate          = ntdevmode->collate;
4204         devmode->icmmethod        = ntdevmode->icmmethod;
4205         devmode->icmintent        = ntdevmode->icmintent;
4206         devmode->mediatype        = ntdevmode->mediatype;
4207         devmode->dithertype       = ntdevmode->dithertype;
4208
4209         if (ntdevmode->nt_dev_private != NULL) {
4210                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4211                         return False;
4212         }
4213
4214         return True;
4215 }
4216
4217 /****************************************************************************
4218  Create a DEVMODE struct. Returns malloced memory.
4219 ****************************************************************************/
4220
4221 DEVICEMODE *construct_dev_mode(const char *servicename)
4222 {
4223         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4224         DEVICEMODE              *devmode = NULL;
4225
4226         DEBUG(7,("construct_dev_mode\n"));
4227
4228         DEBUGADD(8,("getting printer characteristics\n"));
4229
4230         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4231                 return NULL;
4232
4233         if ( !printer->info_2->devmode ) {
4234                 DEBUG(5, ("BONG! There was no device mode!\n"));
4235                 goto done;
4236         }
4237
4238         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4239                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4240                 goto done;
4241         }
4242
4243         ZERO_STRUCTP(devmode);
4244
4245         DEBUGADD(8,("loading DEVICEMODE\n"));
4246
4247         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4248                 free_dev_mode( devmode );
4249                 devmode = NULL;
4250         }
4251
4252 done:
4253         free_a_printer(&printer,2);
4254
4255         return devmode;
4256 }
4257
4258 /********************************************************************
4259  * construct_printer_info_2
4260  * fill a printer_info_2 struct
4261  ********************************************************************/
4262
4263 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4264 {
4265         int count;
4266         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4267
4268         print_status_struct status;
4269
4270         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4271                 return False;
4272
4273         count = print_queue_length(snum, &status);
4274
4275         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4276         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4277         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4278         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4279         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4280
4281         if (*ntprinter->info_2->comment == '\0')
4282                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4283         else
4284                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4285
4286         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4287         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4288         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4289         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4290         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4291
4292         printer->attributes = ntprinter->info_2->attributes;
4293
4294         printer->priority = ntprinter->info_2->priority;                                /* priority */
4295         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4296         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4297         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4298         printer->status = nt_printq_status(status.status);                      /* status */
4299         printer->cjobs = count;                                                 /* jobs */
4300         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4301
4302         if ( !(printer->devmode = construct_dev_mode(
4303                        lp_const_servicename(snum))) )
4304                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4305
4306         printer->secdesc = NULL;
4307
4308         if ( ntprinter->info_2->secdesc_buf
4309                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4310         {
4311                 /* don't use talloc_steal() here unless you do a deep steal of all
4312                    the SEC_DESC members */
4313
4314                 printer->secdesc = dup_sec_desc( talloc_tos(),
4315                         ntprinter->info_2->secdesc_buf->sd );
4316         }
4317
4318         free_a_printer(&ntprinter, 2);
4319
4320         return True;
4321 }
4322
4323 /********************************************************************
4324  * construct_printer_info_3
4325  * fill a printer_info_3 struct
4326  ********************************************************************/
4327
4328 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4329 {
4330         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4331         PRINTER_INFO_3 *printer = NULL;
4332
4333         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4334                 return False;
4335
4336         *pp_printer = NULL;
4337         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4338                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4339                 free_a_printer(&ntprinter, 2);
4340                 return False;
4341         }
4342
4343         ZERO_STRUCTP(printer);
4344
4345         /* These are the components of the SD we are returning. */
4346
4347         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4348                 /* don't use talloc_steal() here unless you do a deep steal of all
4349                    the SEC_DESC members */
4350
4351                 printer->secdesc = dup_sec_desc( talloc_tos(),
4352                         ntprinter->info_2->secdesc_buf->sd );
4353         }
4354
4355         free_a_printer(&ntprinter, 2);
4356
4357         *pp_printer = printer;
4358         return True;
4359 }
4360
4361 /********************************************************************
4362  * construct_printer_info_4
4363  * fill a printer_info_4 struct
4364  ********************************************************************/
4365
4366 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4367 {
4368         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4369
4370         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4371                 return False;
4372
4373         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4374         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4375         printer->attributes = ntprinter->info_2->attributes;
4376
4377         free_a_printer(&ntprinter, 2);
4378         return True;
4379 }
4380
4381 /********************************************************************
4382  * construct_printer_info_5
4383  * fill a printer_info_5 struct
4384  ********************************************************************/
4385
4386 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4387 {
4388         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4389
4390         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4391                 return False;
4392
4393         init_unistr(&printer->printername, ntprinter->info_2->printername);
4394         init_unistr(&printer->portname, ntprinter->info_2->portname);
4395         printer->attributes = ntprinter->info_2->attributes;
4396
4397         /* these two are not used by NT+ according to MSDN */
4398
4399         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4400         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4401
4402         free_a_printer(&ntprinter, 2);
4403
4404         return True;
4405 }
4406
4407 /********************************************************************
4408  * construct_printer_info_6
4409  * fill a printer_info_6 struct
4410  ********************************************************************/
4411
4412 static bool construct_printer_info_6(Printer_entry *print_hnd,
4413                                      PRINTER_INFO_6 *printer,
4414                                      int snum)
4415 {
4416         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4417         int count;
4418         print_status_struct status;
4419
4420         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4421                                          lp_const_servicename(snum))))
4422                 return False;
4423
4424         count = print_queue_length(snum, &status);
4425
4426         printer->status = nt_printq_status(status.status);
4427
4428         free_a_printer(&ntprinter, 2);
4429
4430         return True;
4431 }
4432
4433 /********************************************************************
4434  * construct_printer_info_7
4435  * fill a printer_info_7 struct
4436  ********************************************************************/
4437
4438 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4439 {
4440         char *guid_str = NULL;
4441         struct GUID guid;
4442
4443         if (is_printer_published(print_hnd, snum, &guid)) {
4444                 if (asprintf(&guid_str, "{%s}",
4445                              GUID_string(talloc_tos(), &guid)) == -1) {
4446                         return false;
4447                 }
4448                 strupper_m(guid_str);
4449                 init_unistr(&printer->guid, guid_str);
4450                 SAFE_FREE(guid_str);
4451                 printer->action = SPOOL_DS_PUBLISH;
4452         } else {
4453                 init_unistr(&printer->guid, "");
4454                 printer->action = SPOOL_DS_UNPUBLISH;
4455         }
4456
4457         return True;
4458 }
4459
4460 /********************************************************************
4461  Spoolss_enumprinters.
4462 ********************************************************************/
4463
4464 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4465 {
4466         int snum;
4467         int i;
4468         int n_services=lp_numservices();
4469         PRINTER_INFO_1 *printers=NULL;
4470         PRINTER_INFO_1 current_prt;
4471         WERROR result = WERR_OK;
4472
4473         DEBUG(4,("enum_all_printers_info_1\n"));
4474
4475         for (snum=0; snum<n_services; snum++) {
4476                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4477                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4478
4479                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4480                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4481                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4482                                         *returned=0;
4483                                         return WERR_NOMEM;
4484                                 }
4485                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4486
4487                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4488                                 (*returned)++;
4489                         }
4490                 }
4491         }
4492
4493         /* check the required size. */
4494         for (i=0; i<*returned; i++)
4495                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4496
4497         if (*needed > offered) {
4498                 result = WERR_INSUFFICIENT_BUFFER;
4499                 goto out;
4500         }
4501
4502         if (!rpcbuf_alloc_size(buffer, *needed)) {
4503                 result = WERR_NOMEM;
4504                 goto out;
4505         }
4506
4507         /* fill the buffer with the structures */
4508         for (i=0; i<*returned; i++)
4509                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4510
4511 out:
4512         /* clear memory */
4513
4514         SAFE_FREE(printers);
4515
4516         if ( !W_ERROR_IS_OK(result) )
4517                 *returned = 0;
4518
4519         return result;
4520 }
4521
4522 /********************************************************************
4523  enum_all_printers_info_1_local.
4524 *********************************************************************/
4525
4526 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4527 {
4528         DEBUG(4,("enum_all_printers_info_1_local\n"));
4529
4530         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4531 }
4532
4533 /********************************************************************
4534  enum_all_printers_info_1_name.
4535 *********************************************************************/
4536
4537 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4538 {
4539         char *s = name;
4540
4541         DEBUG(4,("enum_all_printers_info_1_name\n"));
4542
4543         if ((name[0] == '\\') && (name[1] == '\\'))
4544                 s = name + 2;
4545
4546         if (is_myname_or_ipaddr(s)) {
4547                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4548         }
4549         else
4550                 return WERR_INVALID_NAME;
4551 }
4552
4553 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4554 /********************************************************************
4555  enum_all_printers_info_1_remote.
4556 *********************************************************************/
4557
4558 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4559 {
4560         PRINTER_INFO_1 *printer;
4561         fstring printername;
4562         fstring desc;
4563         fstring comment;
4564         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4565         WERROR result = WERR_OK;
4566
4567         /* JFM: currently it's more a place holder than anything else.
4568          * In the spooler world there is a notion of server registration.
4569          * the print servers are registered on the PDC (in the same domain)
4570          *
4571          * We should have a TDB here. The registration is done thru an
4572          * undocumented RPC call.
4573          */
4574
4575         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4576                 return WERR_NOMEM;
4577
4578         *returned=1;
4579
4580         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4581         slprintf(desc, sizeof(desc)-1,"%s", name);
4582         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4583
4584         init_unistr(&printer->description, desc);
4585         init_unistr(&printer->name, printername);
4586         init_unistr(&printer->comment, comment);
4587         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4588
4589         /* check the required size. */
4590         *needed += spoolss_size_printer_info_1(printer);
4591
4592         if (*needed > offered) {
4593                 result = WERR_INSUFFICIENT_BUFFER;
4594                 goto out;
4595         }
4596
4597         if (!rpcbuf_alloc_size(buffer, *needed)) {
4598                 result = WERR_NOMEM;
4599                 goto out;
4600         }
4601
4602         /* fill the buffer with the structures */
4603         smb_io_printer_info_1("", buffer, printer, 0);
4604
4605 out:
4606         /* clear memory */
4607         SAFE_FREE(printer);
4608
4609         if ( !W_ERROR_IS_OK(result) )
4610                 *returned = 0;
4611
4612         return result;
4613 }
4614
4615 #endif
4616
4617 /********************************************************************
4618  enum_all_printers_info_1_network.
4619 *********************************************************************/
4620
4621 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4622 {
4623         char *s = name;
4624
4625         DEBUG(4,("enum_all_printers_info_1_network\n"));
4626
4627         /* If we respond to a enum_printers level 1 on our name with flags
4628            set to PRINTER_ENUM_REMOTE with a list of printers then these
4629            printers incorrectly appear in the APW browse list.
4630            Specifically the printers for the server appear at the workgroup
4631            level where all the other servers in the domain are
4632            listed. Windows responds to this call with a
4633            WERR_CAN_NOT_COMPLETE so we should do the same. */
4634
4635         if (name[0] == '\\' && name[1] == '\\')
4636                  s = name + 2;
4637
4638         if (is_myname_or_ipaddr(s))
4639                  return WERR_CAN_NOT_COMPLETE;
4640
4641         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4642 }
4643
4644 /********************************************************************
4645  * api_spoolss_enumprinters
4646  *
4647  * called from api_spoolss_enumprinters (see this to understand)
4648  ********************************************************************/
4649
4650 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4651 {
4652         int snum;
4653         int i;
4654         int n_services=lp_numservices();
4655         PRINTER_INFO_2 *printers=NULL;
4656         PRINTER_INFO_2 current_prt;
4657         WERROR result = WERR_OK;
4658
4659         *returned = 0;
4660
4661         for (snum=0; snum<n_services; snum++) {
4662                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4663                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4664
4665                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4666                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4667                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4668                                         *returned = 0;
4669                                         return WERR_NOMEM;
4670                                 }
4671
4672                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4673
4674                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4675
4676                                 (*returned)++;
4677                         }
4678                 }
4679         }
4680
4681         /* check the required size. */
4682         for (i=0; i<*returned; i++)
4683                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4684
4685         if (*needed > offered) {
4686                 result = WERR_INSUFFICIENT_BUFFER;
4687                 goto out;
4688         }
4689
4690         if (!rpcbuf_alloc_size(buffer, *needed)) {
4691                 result = WERR_NOMEM;
4692                 goto out;
4693         }
4694
4695         /* fill the buffer with the structures */
4696         for (i=0; i<*returned; i++)
4697                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4698
4699 out:
4700         /* clear memory */
4701
4702         for (i=0; i<*returned; i++)
4703                 free_devmode(printers[i].devmode);
4704
4705         SAFE_FREE(printers);
4706
4707         if ( !W_ERROR_IS_OK(result) )
4708                 *returned = 0;
4709
4710         return result;
4711 }
4712
4713 /********************************************************************
4714  * handle enumeration of printers at level 1
4715  ********************************************************************/
4716
4717 static WERROR enumprinters_level1( uint32 flags, fstring name,
4718                                  RPC_BUFFER *buffer, uint32 offered,
4719                                  uint32 *needed, uint32 *returned)
4720 {
4721         /* Not all the flags are equals */
4722
4723         if (flags & PRINTER_ENUM_LOCAL)
4724                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4725
4726         if (flags & PRINTER_ENUM_NAME)
4727                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4728
4729 #if 0   /* JERRY - disabled for now */
4730         if (flags & PRINTER_ENUM_REMOTE)
4731                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4732 #endif
4733
4734         if (flags & PRINTER_ENUM_NETWORK)
4735                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4736
4737         return WERR_OK; /* NT4sp5 does that */
4738 }
4739
4740 /********************************************************************
4741  * handle enumeration of printers at level 2
4742  ********************************************************************/
4743
4744 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4745                                  RPC_BUFFER *buffer, uint32 offered,
4746                                  uint32 *needed, uint32 *returned)
4747 {
4748         if (flags & PRINTER_ENUM_LOCAL) {
4749                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4750         }
4751
4752         if (flags & PRINTER_ENUM_NAME) {
4753                 if (is_myname_or_ipaddr(canon_servername(servername)))
4754                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4755                 else
4756                         return WERR_INVALID_NAME;
4757         }
4758
4759         if (flags & PRINTER_ENUM_REMOTE)
4760                 return WERR_UNKNOWN_LEVEL;
4761
4762         return WERR_OK;
4763 }
4764
4765 /********************************************************************
4766  * handle enumeration of printers at level 5
4767  ********************************************************************/
4768
4769 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4770                                  RPC_BUFFER *buffer, uint32 offered,
4771                                  uint32 *needed, uint32 *returned)
4772 {
4773 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4774         return WERR_OK;
4775 }
4776
4777 /********************************************************************
4778  * api_spoolss_enumprinters
4779  *
4780  * called from api_spoolss_enumprinters (see this to understand)
4781  ********************************************************************/
4782
4783 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4784 {
4785         uint32 flags = q_u->flags;
4786         UNISTR2 *servername = &q_u->servername;
4787         uint32 level = q_u->level;
4788         RPC_BUFFER *buffer = NULL;
4789         uint32 offered = q_u->offered;
4790         uint32 *needed = &r_u->needed;
4791         uint32 *returned = &r_u->returned;
4792
4793         fstring name;
4794
4795         /* that's an [in out] buffer */
4796
4797         if (!q_u->buffer && (offered!=0)) {
4798                 return WERR_INVALID_PARAM;
4799         }
4800
4801         rpcbuf_move(q_u->buffer, &r_u->buffer);
4802         buffer = r_u->buffer;
4803
4804         DEBUG(4,("_spoolss_enumprinters\n"));
4805
4806         *needed=0;
4807         *returned=0;
4808
4809         /*
4810          * Level 1:
4811          *          flags==PRINTER_ENUM_NAME
4812          *           if name=="" then enumerates all printers
4813          *           if name!="" then enumerate the printer
4814          *          flags==PRINTER_ENUM_REMOTE
4815          *          name is NULL, enumerate printers
4816          * Level 2: name!="" enumerates printers, name can't be NULL
4817          * Level 3: doesn't exist
4818          * Level 4: does a local registry lookup
4819          * Level 5: same as Level 2
4820          */
4821
4822         unistr2_to_ascii(name, servername, sizeof(name));
4823         strupper_m(name);
4824
4825         switch (level) {
4826         case 1:
4827                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4828         case 2:
4829                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4830         case 5:
4831                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4832         case 3:
4833         case 4:
4834                 break;
4835         }
4836         return WERR_UNKNOWN_LEVEL;
4837 }
4838
4839 /****************************************************************************
4840 ****************************************************************************/
4841
4842 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4843 {
4844         PRINTER_INFO_0 *printer=NULL;
4845         WERROR result = WERR_OK;
4846
4847         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4848                 return WERR_NOMEM;
4849
4850         construct_printer_info_0(print_hnd, printer, snum);
4851
4852         /* check the required size. */
4853         *needed += spoolss_size_printer_info_0(printer);
4854
4855         if (*needed > offered) {
4856                 result = WERR_INSUFFICIENT_BUFFER;
4857                 goto out;
4858         }
4859
4860         if (!rpcbuf_alloc_size(buffer, *needed)) {
4861                 result = WERR_NOMEM;
4862                 goto out;
4863         }
4864
4865         /* fill the buffer with the structures */
4866         smb_io_printer_info_0("", buffer, printer, 0);
4867
4868 out:
4869         /* clear memory */
4870
4871         SAFE_FREE(printer);
4872
4873         return result;
4874 }
4875
4876 /****************************************************************************
4877 ****************************************************************************/
4878
4879 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4880 {
4881         PRINTER_INFO_1 *printer=NULL;
4882         WERROR result = WERR_OK;
4883
4884         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4885                 return WERR_NOMEM;
4886
4887         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4888
4889         /* check the required size. */
4890         *needed += spoolss_size_printer_info_1(printer);
4891
4892         if (*needed > offered) {
4893                 result = WERR_INSUFFICIENT_BUFFER;
4894                 goto out;
4895         }
4896
4897         if (!rpcbuf_alloc_size(buffer, *needed)) {
4898                 result = WERR_NOMEM;
4899                 goto out;
4900         }
4901
4902         /* fill the buffer with the structures */
4903         smb_io_printer_info_1("", buffer, printer, 0);
4904
4905 out:
4906         /* clear memory */
4907         SAFE_FREE(printer);
4908
4909         return result;
4910 }
4911
4912 /****************************************************************************
4913 ****************************************************************************/
4914
4915 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4916 {
4917         PRINTER_INFO_2 *printer=NULL;
4918         WERROR result = WERR_OK;
4919
4920         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4921                 return WERR_NOMEM;
4922
4923         construct_printer_info_2(print_hnd, printer, snum);
4924
4925         /* check the required size. */
4926         *needed += spoolss_size_printer_info_2(printer);
4927
4928         if (*needed > offered) {
4929                 result = WERR_INSUFFICIENT_BUFFER;
4930                 goto out;
4931         }
4932
4933         if (!rpcbuf_alloc_size(buffer, *needed)) {
4934                 result = WERR_NOMEM;
4935                 goto out;
4936         }
4937
4938         /* fill the buffer with the structures */
4939         if (!smb_io_printer_info_2("", buffer, printer, 0))
4940                 result = WERR_NOMEM;
4941
4942 out:
4943         /* clear memory */
4944         free_printer_info_2(printer);
4945
4946         return result;
4947 }
4948
4949 /****************************************************************************
4950 ****************************************************************************/
4951
4952 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4953 {
4954         PRINTER_INFO_3 *printer=NULL;
4955         WERROR result = WERR_OK;
4956
4957         if (!construct_printer_info_3(print_hnd, &printer, snum))
4958                 return WERR_NOMEM;
4959
4960         /* check the required size. */
4961         *needed += spoolss_size_printer_info_3(printer);
4962
4963         if (*needed > offered) {
4964                 result = WERR_INSUFFICIENT_BUFFER;
4965                 goto out;
4966         }
4967
4968         if (!rpcbuf_alloc_size(buffer, *needed)) {
4969                 result = WERR_NOMEM;
4970                 goto out;
4971         }
4972
4973         /* fill the buffer with the structures */
4974         smb_io_printer_info_3("", buffer, printer, 0);
4975
4976 out:
4977         /* clear memory */
4978         free_printer_info_3(printer);
4979
4980         return result;
4981 }
4982
4983 /****************************************************************************
4984 ****************************************************************************/
4985
4986 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4987 {
4988         PRINTER_INFO_4 *printer=NULL;
4989         WERROR result = WERR_OK;
4990
4991         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4992                 return WERR_NOMEM;
4993
4994         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4995                 SAFE_FREE(printer);
4996                 return WERR_NOMEM;
4997         }
4998
4999         /* check the required size. */
5000         *needed += spoolss_size_printer_info_4(printer);
5001
5002         if (*needed > offered) {
5003                 result = WERR_INSUFFICIENT_BUFFER;
5004                 goto out;
5005         }
5006
5007         if (!rpcbuf_alloc_size(buffer, *needed)) {
5008                 result = WERR_NOMEM;
5009                 goto out;
5010         }
5011
5012         /* fill the buffer with the structures */
5013         smb_io_printer_info_4("", buffer, printer, 0);
5014
5015 out:
5016         /* clear memory */
5017         free_printer_info_4(printer);
5018
5019         return result;
5020 }
5021
5022 /****************************************************************************
5023 ****************************************************************************/
5024
5025 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5026 {
5027         PRINTER_INFO_5 *printer=NULL;
5028         WERROR result = WERR_OK;
5029
5030         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5031                 return WERR_NOMEM;
5032
5033         if (!construct_printer_info_5(print_hnd, printer, snum)) {
5034                 free_printer_info_5(printer);
5035                 return WERR_NOMEM;
5036         }
5037
5038         /* check the required size. */
5039         *needed += spoolss_size_printer_info_5(printer);
5040
5041         if (*needed > offered) {
5042                 result = WERR_INSUFFICIENT_BUFFER;
5043                 goto out;
5044         }
5045
5046         if (!rpcbuf_alloc_size(buffer, *needed)) {
5047                 result = WERR_NOMEM;
5048                 goto out;
5049         }
5050
5051         /* fill the buffer with the structures */
5052         smb_io_printer_info_5("", buffer, printer, 0);
5053
5054 out:
5055         /* clear memory */
5056         free_printer_info_5(printer);
5057
5058         return result;
5059 }
5060
5061 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5062                                  int snum,
5063                                  RPC_BUFFER *buffer, uint32 offered,
5064                                  uint32 *needed)
5065 {
5066         PRINTER_INFO_6 *printer;
5067         WERROR result = WERR_OK;
5068
5069         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5070                 return WERR_NOMEM;
5071         }
5072
5073         if (!construct_printer_info_6(print_hnd, printer, snum)) {
5074                 free_printer_info_6(printer);
5075                 return WERR_NOMEM;
5076         }
5077
5078         /* check the required size. */
5079         *needed += spoolss_size_printer_info_6(printer);
5080
5081         if (*needed > offered) {
5082                 result = WERR_INSUFFICIENT_BUFFER;
5083                 goto out;
5084         }
5085
5086         if (!rpcbuf_alloc_size(buffer, *needed)) {
5087                 result = WERR_NOMEM;
5088                 goto out;
5089         }
5090
5091         /* fill the buffer with the structures */
5092         smb_io_printer_info_6("", buffer, printer, 0);
5093
5094 out:
5095         /* clear memory */
5096         free_printer_info_6(printer);
5097
5098         return result;
5099 }
5100
5101 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5102 {
5103         PRINTER_INFO_7 *printer=NULL;
5104         WERROR result = WERR_OK;
5105
5106         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5107                 return WERR_NOMEM;
5108
5109         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5110                 result = WERR_NOMEM;
5111                 goto out;
5112         }
5113
5114         /* check the required size. */
5115         *needed += spoolss_size_printer_info_7(printer);
5116
5117         if (*needed > offered) {
5118                 result = WERR_INSUFFICIENT_BUFFER;
5119                 goto out;
5120         }
5121
5122         if (!rpcbuf_alloc_size(buffer, *needed)) {
5123                 result = WERR_NOMEM;
5124                 goto out;
5125
5126         }
5127
5128         /* fill the buffer with the structures */
5129         smb_io_printer_info_7("", buffer, printer, 0);
5130
5131 out:
5132         /* clear memory */
5133         free_printer_info_7(printer);
5134
5135         return result;
5136 }
5137
5138 /****************************************************************************
5139 ****************************************************************************/
5140
5141 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5142 {
5143         POLICY_HND *handle = &q_u->handle;
5144         uint32 level = q_u->level;
5145         RPC_BUFFER *buffer = NULL;
5146         uint32 offered = q_u->offered;
5147         uint32 *needed = &r_u->needed;
5148         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5149
5150         int snum;
5151
5152         /* that's an [in out] buffer */
5153
5154         if (!q_u->buffer && (offered!=0)) {
5155                 return WERR_INVALID_PARAM;
5156         }
5157
5158         rpcbuf_move(q_u->buffer, &r_u->buffer);
5159         buffer = r_u->buffer;
5160
5161         *needed=0;
5162
5163         if (!get_printer_snum(p, handle, &snum, NULL))
5164                 return WERR_BADFID;
5165
5166         switch (level) {
5167         case 0:
5168                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5169         case 1:
5170                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5171         case 2:
5172                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5173         case 3:
5174                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5175         case 4:
5176                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5177         case 5:
5178                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5179         case 6:
5180                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5181         case 7:
5182                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5183         }
5184         return WERR_UNKNOWN_LEVEL;
5185 }
5186
5187 /********************************************************************
5188  * fill a DRIVER_INFO_1 struct
5189  ********************************************************************/
5190
5191 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5192 {
5193         init_unistr( &info->name, driver.info_3->name);
5194 }
5195
5196 /********************************************************************
5197  * construct_printer_driver_info_1
5198  ********************************************************************/
5199
5200 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5201 {
5202         NT_PRINTER_INFO_LEVEL *printer = NULL;
5203         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5204
5205         ZERO_STRUCT(driver);
5206
5207         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5208                 return WERR_INVALID_PRINTER_NAME;
5209
5210         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5211                 free_a_printer(&printer, 2);
5212                 return WERR_UNKNOWN_PRINTER_DRIVER;
5213         }
5214
5215         fill_printer_driver_info_1(info, driver, servername, architecture);
5216
5217         free_a_printer(&printer,2);
5218
5219         return WERR_OK;
5220 }
5221
5222 /********************************************************************
5223  * construct_printer_driver_info_2
5224  * fill a printer_info_2 struct
5225  ********************************************************************/
5226
5227 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5228 {
5229         TALLOC_CTX *ctx = talloc_tos();
5230         char *temp = NULL;
5231         const char *cservername = canon_servername(servername);
5232
5233         info->version=driver.info_3->cversion;
5234
5235         init_unistr( &info->name, driver.info_3->name );
5236         init_unistr( &info->architecture, driver.info_3->environment );
5237
5238         if (strlen(driver.info_3->driverpath)) {
5239                 temp = talloc_asprintf(ctx,
5240                                 "\\\\%s%s",
5241                                 cservername,
5242                                 driver.info_3->driverpath);
5243                 init_unistr( &info->driverpath, temp );
5244         } else {
5245                 init_unistr( &info->driverpath, "" );
5246         }
5247
5248         TALLOC_FREE(temp);
5249         if (strlen(driver.info_3->datafile)) {
5250                 temp = talloc_asprintf(ctx,
5251                                 "\\\\%s%s",
5252                                 cservername,
5253                                 driver.info_3->datafile);
5254                 init_unistr( &info->datafile, temp );
5255         } else
5256                 init_unistr( &info->datafile, "" );
5257
5258         TALLOC_FREE(temp);
5259         if (strlen(driver.info_3->configfile)) {
5260                 temp = talloc_asprintf(ctx,
5261                                 "\\\\%s%s",
5262                                 cservername,
5263                                 driver.info_3->configfile);
5264                 init_unistr( &info->configfile, temp );
5265         } else
5266                 init_unistr( &info->configfile, "" );
5267 }
5268
5269 /********************************************************************
5270  * construct_printer_driver_info_2
5271  * fill a printer_info_2 struct
5272  ********************************************************************/
5273
5274 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5275 {
5276         NT_PRINTER_INFO_LEVEL *printer = NULL;
5277         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5278
5279         ZERO_STRUCT(printer);
5280         ZERO_STRUCT(driver);
5281
5282         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5283                 return WERR_INVALID_PRINTER_NAME;
5284
5285         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5286                 free_a_printer(&printer, 2);
5287                 return WERR_UNKNOWN_PRINTER_DRIVER;
5288         }
5289
5290         fill_printer_driver_info_2(info, driver, servername);
5291
5292         free_a_printer(&printer,2);
5293
5294         return WERR_OK;
5295 }
5296
5297 /********************************************************************
5298  * copy a strings array and convert to UNICODE
5299  *
5300  * convert an array of ascii string to a UNICODE string
5301  ********************************************************************/
5302
5303 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5304 {
5305         int i=0;
5306         int j=0;
5307         const char *v;
5308         char *line = NULL;
5309         TALLOC_CTX *ctx = talloc_tos();
5310
5311         DEBUG(6,("init_unistr_array\n"));
5312         *uni_array=NULL;
5313
5314         while (true) {
5315                 if ( !char_array ) {
5316                         v = "";
5317                 } else {
5318                         v = char_array[i];
5319                         if (!v)
5320                                 v = ""; /* hack to handle null lists */
5321                 }
5322
5323                 /* hack to allow this to be used in places other than when generating
5324                    the list of dependent files */
5325
5326                 TALLOC_FREE(line);
5327                 if ( servername ) {
5328                         line = talloc_asprintf(ctx,
5329                                         "\\\\%s%s",
5330                                         canon_servername(servername),
5331                                         v);
5332                 } else {
5333                         line = talloc_strdup(ctx, v);
5334                 }
5335
5336                 if (!line) {
5337                         SAFE_FREE(*uni_array);
5338                         return 0;
5339                 }
5340                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5341
5342                 /* add one extra unit16 for the second terminating NULL */
5343
5344                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5345                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5346                         return 0;
5347                 }
5348
5349                 if ( !strlen(v) )
5350                         break;
5351
5352                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5353                 i++;
5354         }
5355
5356         if (*uni_array) {
5357                 /* special case for ""; we need to add both NULL's here */
5358                 if (!j)
5359                         (*uni_array)[j++]=0x0000;
5360                 (*uni_array)[j]=0x0000;
5361         }
5362
5363         DEBUGADD(6,("last one:done\n"));
5364
5365         /* return size of array in uint16's */
5366
5367         return j+1;
5368 }
5369
5370 /********************************************************************
5371  * construct_printer_info_3
5372  * fill a printer_info_3 struct
5373  ********************************************************************/
5374
5375 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5376 {
5377         char *temp = NULL;
5378         TALLOC_CTX *ctx = talloc_tos();
5379         const char *cservername = canon_servername(servername);
5380
5381         ZERO_STRUCTP(info);
5382
5383         info->version=driver.info_3->cversion;
5384
5385         init_unistr( &info->name, driver.info_3->name );
5386         init_unistr( &info->architecture, driver.info_3->environment );
5387
5388         if (strlen(driver.info_3->driverpath)) {
5389                 temp = talloc_asprintf(ctx,
5390                                 "\\\\%s%s",
5391                                 cservername,
5392                                 driver.info_3->driverpath);
5393                 init_unistr( &info->driverpath, temp );
5394         } else
5395                 init_unistr( &info->driverpath, "" );
5396
5397         TALLOC_FREE(temp);
5398         if (strlen(driver.info_3->datafile)) {
5399                 temp = talloc_asprintf(ctx,
5400                                 "\\\\%s%s",
5401                                 cservername,
5402                                 driver.info_3->datafile);
5403                 init_unistr( &info->datafile, temp );
5404         } else
5405                 init_unistr( &info->datafile, "" );
5406
5407         TALLOC_FREE(temp);
5408         if (strlen(driver.info_3->configfile)) {
5409                 temp = talloc_asprintf(ctx,
5410                                 "\\\\%s%s",
5411                                 cservername,
5412                                 driver.info_3->configfile);
5413                 init_unistr( &info->configfile, temp );
5414         } else
5415                 init_unistr( &info->configfile, "" );
5416
5417         TALLOC_FREE(temp);
5418         if (strlen(driver.info_3->helpfile)) {
5419                 temp = talloc_asprintf(ctx,
5420                                 "\\\\%s%s",
5421                                 cservername,
5422                                 driver.info_3->helpfile);
5423                 init_unistr( &info->helpfile, temp );
5424         } else
5425                 init_unistr( &info->helpfile, "" );
5426
5427         TALLOC_FREE(temp);
5428         init_unistr( &info->monitorname, driver.info_3->monitorname );
5429         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5430
5431         info->dependentfiles=NULL;
5432         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5433 }
5434
5435 /********************************************************************
5436  * construct_printer_info_3
5437  * fill a printer_info_3 struct
5438  ********************************************************************/
5439
5440 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5441 {
5442         NT_PRINTER_INFO_LEVEL *printer = NULL;
5443         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5444         WERROR status;
5445         ZERO_STRUCT(driver);
5446
5447         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5448         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5449         if (!W_ERROR_IS_OK(status))
5450                 return WERR_INVALID_PRINTER_NAME;
5451
5452         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5453         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5454
5455 #if 0   /* JERRY */
5456
5457         /*
5458          * I put this code in during testing.  Helpful when commenting out the
5459          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5460          * as win2k always queries the driver using an infor level of 6.
5461          * I've left it in (but ifdef'd out) because I'll probably
5462          * use it in experimentation again in the future.   --jerry 22/01/2002
5463          */
5464
5465         if (!W_ERROR_IS_OK(status)) {
5466                 /*
5467                  * Is this a W2k client ?
5468                  */
5469                 if (version == 3) {
5470                         /* Yes - try again with a WinNT driver. */
5471                         version = 2;
5472                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5473                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5474                 }
5475 #endif
5476
5477                 if (!W_ERROR_IS_OK(status)) {
5478                         free_a_printer(&printer,2);
5479                         return WERR_UNKNOWN_PRINTER_DRIVER;
5480                 }
5481
5482 #if 0   /* JERRY */
5483         }
5484 #endif
5485
5486
5487         fill_printer_driver_info_3(info, driver, servername);
5488
5489         free_a_printer(&printer,2);
5490
5491         return WERR_OK;
5492 }
5493
5494 /********************************************************************
5495  * construct_printer_info_6
5496  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5497  ********************************************************************/
5498
5499 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5500 {
5501         char *temp = NULL;
5502         fstring nullstr;
5503         TALLOC_CTX *ctx = talloc_tos();
5504         const char *cservername = canon_servername(servername);
5505
5506         ZERO_STRUCTP(info);
5507         memset(&nullstr, '\0', sizeof(fstring));
5508
5509         info->version=driver.info_3->cversion;
5510
5511         init_unistr( &info->name, driver.info_3->name );
5512         init_unistr( &info->architecture, driver.info_3->environment );
5513
5514         if (strlen(driver.info_3->driverpath)) {
5515                 temp = talloc_asprintf(ctx,
5516                                 "\\\\%s%s",
5517                                 cservername,
5518                                 driver.info_3->driverpath);
5519                 init_unistr( &info->driverpath, temp );
5520         } else
5521                 init_unistr( &info->driverpath, "" );
5522
5523         TALLOC_FREE(temp);
5524         if (strlen(driver.info_3->datafile)) {
5525                 temp = talloc_asprintf(ctx,
5526                                 "\\\\%s%s",
5527                                 cservername,
5528                                 driver.info_3->datafile);
5529                 init_unistr( &info->datafile, temp );
5530         } else
5531                 init_unistr( &info->datafile, "" );
5532
5533         TALLOC_FREE(temp);
5534         if (strlen(driver.info_3->configfile)) {
5535                 temp = talloc_asprintf(ctx,
5536                                 "\\\\%s%s",
5537                                 cservername,
5538                                 driver.info_3->configfile);
5539                 init_unistr( &info->configfile, temp );
5540         } else
5541                 init_unistr( &info->configfile, "" );
5542
5543         TALLOC_FREE(temp);
5544         if (strlen(driver.info_3->helpfile)) {
5545                 temp = talloc_asprintf(ctx,
5546                                 "\\\\%s%s",
5547                                 cservername,
5548                                 driver.info_3->helpfile);
5549                 init_unistr( &info->helpfile, temp );
5550         } else
5551                 init_unistr( &info->helpfile, "" );
5552
5553         TALLOC_FREE(temp);
5554         init_unistr( &info->monitorname, driver.info_3->monitorname );
5555         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5556
5557         info->dependentfiles = NULL;
5558         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5559
5560         info->previousdrivernames=NULL;
5561         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5562
5563         info->driver_date=0;
5564
5565         info->padding=0;
5566         info->driver_version_low=0;
5567         info->driver_version_high=0;
5568
5569         init_unistr( &info->mfgname, "");
5570         init_unistr( &info->oem_url, "");
5571         init_unistr( &info->hardware_id, "");
5572         init_unistr( &info->provider, "");
5573 }
5574
5575 /********************************************************************
5576  * construct_printer_info_6
5577  * fill a printer_info_6 struct
5578  ********************************************************************/
5579
5580 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5581               const char *servername, fstring architecture, uint32 version)
5582 {
5583         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5584         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5585         WERROR                          status;
5586
5587         ZERO_STRUCT(driver);
5588
5589         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5590
5591         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5592
5593         if (!W_ERROR_IS_OK(status))
5594                 return WERR_INVALID_PRINTER_NAME;
5595
5596         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5597
5598         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5599
5600         if (!W_ERROR_IS_OK(status))
5601         {
5602                 /*
5603                  * Is this a W2k client ?
5604                  */
5605
5606                 if (version < 3) {
5607                         free_a_printer(&printer,2);
5608                         return WERR_UNKNOWN_PRINTER_DRIVER;
5609                 }
5610
5611                 /* Yes - try again with a WinNT driver. */
5612                 version = 2;
5613                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5614                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5615                 if (!W_ERROR_IS_OK(status)) {
5616                         free_a_printer(&printer,2);
5617                         return WERR_UNKNOWN_PRINTER_DRIVER;
5618                 }
5619         }
5620
5621         fill_printer_driver_info_6(info, driver, servername);
5622
5623         free_a_printer(&printer,2);
5624         free_a_printer_driver(driver, 3);
5625
5626         return WERR_OK;
5627 }
5628
5629 /****************************************************************************
5630 ****************************************************************************/
5631
5632 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5633 {
5634         SAFE_FREE(info->dependentfiles);
5635 }
5636
5637 /****************************************************************************
5638 ****************************************************************************/
5639
5640 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5641 {
5642         SAFE_FREE(info->dependentfiles);
5643 }
5644
5645 /****************************************************************************
5646 ****************************************************************************/
5647
5648 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5649 {
5650         DRIVER_INFO_1 *info=NULL;
5651         WERROR result;
5652
5653         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5654                 return WERR_NOMEM;
5655
5656         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5657         if (!W_ERROR_IS_OK(result))
5658                 goto out;
5659
5660         /* check the required size. */
5661         *needed += spoolss_size_printer_driver_info_1(info);
5662
5663         if (*needed > offered) {
5664                 result = WERR_INSUFFICIENT_BUFFER;
5665                 goto out;
5666         }
5667
5668         if (!rpcbuf_alloc_size(buffer, *needed)) {
5669                 result = WERR_NOMEM;
5670                 goto out;
5671         }
5672
5673         /* fill the buffer with the structures */
5674         smb_io_printer_driver_info_1("", buffer, info, 0);
5675
5676 out:
5677         /* clear memory */
5678         SAFE_FREE(info);
5679
5680         return result;
5681 }
5682
5683 /****************************************************************************
5684 ****************************************************************************/
5685
5686 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5687 {
5688         DRIVER_INFO_2 *info=NULL;
5689         WERROR result;
5690
5691         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5692                 return WERR_NOMEM;
5693
5694         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5695         if (!W_ERROR_IS_OK(result))
5696                 goto out;
5697
5698         /* check the required size. */
5699         *needed += spoolss_size_printer_driver_info_2(info);
5700
5701         if (*needed > offered) {
5702                 result = WERR_INSUFFICIENT_BUFFER;
5703                 goto out;
5704         }
5705
5706         if (!rpcbuf_alloc_size(buffer, *needed)) {
5707                 result = WERR_NOMEM;
5708                 goto out;
5709         }
5710
5711         /* fill the buffer with the structures */
5712         smb_io_printer_driver_info_2("", buffer, info, 0);
5713
5714 out:
5715         /* clear memory */
5716         SAFE_FREE(info);
5717
5718         return result;
5719 }
5720
5721 /****************************************************************************
5722 ****************************************************************************/
5723
5724 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5725 {
5726         DRIVER_INFO_3 info;
5727         WERROR result;
5728
5729         ZERO_STRUCT(info);
5730
5731         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5732         if (!W_ERROR_IS_OK(result))
5733                 goto out;
5734
5735         /* check the required size. */
5736         *needed += spoolss_size_printer_driver_info_3(&info);
5737
5738         if (*needed > offered) {
5739                 result = WERR_INSUFFICIENT_BUFFER;
5740                 goto out;
5741         }
5742
5743         if (!rpcbuf_alloc_size(buffer, *needed)) {
5744                 result = WERR_NOMEM;
5745                 goto out;
5746         }
5747
5748         /* fill the buffer with the structures */
5749         smb_io_printer_driver_info_3("", buffer, &info, 0);
5750
5751 out:
5752         free_printer_driver_info_3(&info);
5753
5754         return result;
5755 }
5756
5757 /****************************************************************************
5758 ****************************************************************************/
5759
5760 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5761 {
5762         DRIVER_INFO_6 info;
5763         WERROR result;
5764
5765         ZERO_STRUCT(info);
5766
5767         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5768         if (!W_ERROR_IS_OK(result))
5769                 goto out;
5770
5771         /* check the required size. */
5772         *needed += spoolss_size_printer_driver_info_6(&info);
5773
5774         if (*needed > offered) {
5775                 result = WERR_INSUFFICIENT_BUFFER;
5776                 goto out;
5777         }
5778
5779         if (!rpcbuf_alloc_size(buffer, *needed)) {
5780                 result = WERR_NOMEM;
5781                 goto out;
5782         }
5783
5784         /* fill the buffer with the structures */
5785         smb_io_printer_driver_info_6("", buffer, &info, 0);
5786
5787 out:
5788         free_printer_driver_info_6(&info);
5789
5790         return result;
5791 }
5792
5793 /****************************************************************************
5794 ****************************************************************************/
5795
5796 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5797 {
5798         POLICY_HND *handle = &q_u->handle;
5799         UNISTR2 *uni_arch = &q_u->architecture;
5800         uint32 level = q_u->level;
5801         uint32 clientmajorversion = q_u->clientmajorversion;
5802         RPC_BUFFER *buffer = NULL;
5803         uint32 offered = q_u->offered;
5804         uint32 *needed = &r_u->needed;
5805         uint32 *servermajorversion = &r_u->servermajorversion;
5806         uint32 *serverminorversion = &r_u->serverminorversion;
5807         Printer_entry *printer;
5808
5809         fstring servername;
5810         fstring architecture;
5811         int snum;
5812
5813         /* that's an [in out] buffer */
5814
5815         if (!q_u->buffer && (offered!=0)) {
5816                 return WERR_INVALID_PARAM;
5817         }
5818
5819         rpcbuf_move(q_u->buffer, &r_u->buffer);
5820         buffer = r_u->buffer;
5821
5822         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5823
5824         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5825                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5826                 return WERR_INVALID_PRINTER_NAME;
5827         }
5828
5829         *needed = 0;
5830         *servermajorversion = 0;
5831         *serverminorversion = 0;
5832
5833         fstrcpy(servername, get_server_name( printer ));
5834         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5835
5836         if (!get_printer_snum(p, handle, &snum, NULL))
5837                 return WERR_BADFID;
5838
5839         switch (level) {
5840         case 1:
5841                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5842         case 2:
5843                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5844         case 3:
5845                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5846         case 6:
5847                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5848 #if 0   /* JERRY */
5849         case 101:
5850                 /* apparently this call is the equivalent of
5851                    EnumPrinterDataEx() for the DsDriver key */
5852                 break;
5853 #endif
5854         }
5855
5856         return WERR_UNKNOWN_LEVEL;
5857 }
5858
5859
5860 /****************************************************************
5861  _spoolss_StartPagePrinter
5862 ****************************************************************/
5863
5864 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5865                                  struct spoolss_StartPagePrinter *r)
5866 {
5867         POLICY_HND *handle = r->in.handle;
5868
5869         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5870
5871         if (!Printer) {
5872                 DEBUG(3,("_spoolss_StartPagePrinter: "
5873                         "Error in startpageprinter printer handle\n"));
5874                 return WERR_BADFID;
5875         }
5876
5877         Printer->page_started=True;
5878         return WERR_OK;
5879 }
5880
5881 /****************************************************************
5882  _spoolss_EndPagePrinter
5883 ****************************************************************/
5884
5885 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5886                                struct spoolss_EndPagePrinter *r)
5887 {
5888         POLICY_HND *handle = r->in.handle;
5889         int snum;
5890
5891         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5892
5893         if (!Printer) {
5894                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5895                         OUR_HANDLE(handle)));
5896                 return WERR_BADFID;
5897         }
5898
5899         if (!get_printer_snum(p, handle, &snum, NULL))
5900                 return WERR_BADFID;
5901
5902         Printer->page_started=False;
5903         print_job_endpage(snum, Printer->jobid);
5904
5905         return WERR_OK;
5906 }
5907
5908 /****************************************************************
5909  _spoolss_StartDocPrinter
5910 ****************************************************************/
5911
5912 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5913                                 struct spoolss_StartDocPrinter *r)
5914 {
5915         POLICY_HND *handle = r->in.handle;
5916         uint32_t *jobid = r->out.job_id;
5917         struct spoolss_DocumentInfo1 *info_1;
5918         int snum;
5919         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5920
5921         if (!Printer) {
5922                 DEBUG(2,("_spoolss_StartDocPrinter: "
5923                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5924                 return WERR_BADFID;
5925         }
5926
5927         if (r->in.level != 1) {
5928                 return WERR_UNKNOWN_LEVEL;
5929         }
5930
5931         info_1 = r->in.info.info1;
5932
5933         /*
5934          * a nice thing with NT is it doesn't listen to what you tell it.
5935          * when asked to send _only_ RAW datas, it tries to send datas
5936          * in EMF format.
5937          *
5938          * So I add checks like in NT Server ...
5939          */
5940
5941         if (info_1->datatype) {
5942                 if (strcmp(info_1->datatype, "RAW") != 0) {
5943                         (*jobid)=0;
5944                         return WERR_INVALID_DATATYPE;
5945                 }
5946         }
5947
5948         /* get the share number of the printer */
5949         if (!get_printer_snum(p, handle, &snum, NULL)) {
5950                 return WERR_BADFID;
5951         }
5952
5953         Printer->jobid = print_job_start(p->server_info, snum,
5954                                          CONST_DISCARD(char *,info_1->document_name),
5955                                          Printer->nt_devmode);
5956
5957         /* An error occured in print_job_start() so return an appropriate
5958            NT error code. */
5959
5960         if (Printer->jobid == -1) {
5961                 return map_werror_from_unix(errno);
5962         }
5963
5964         Printer->document_started=True;
5965         (*jobid) = Printer->jobid;
5966
5967         return WERR_OK;
5968 }
5969
5970 /****************************************************************
5971  _spoolss_EndDocPrinter
5972 ****************************************************************/
5973
5974 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5975                               struct spoolss_EndDocPrinter *r)
5976 {
5977         POLICY_HND *handle = r->in.handle;
5978
5979         return _spoolss_enddocprinter_internal(p, handle);
5980 }
5981
5982 /****************************************************************
5983  _spoolss_WritePrinter
5984 ****************************************************************/
5985
5986 WERROR _spoolss_WritePrinter(pipes_struct *p,
5987                              struct spoolss_WritePrinter *r)
5988 {
5989         POLICY_HND *handle = r->in.handle;
5990         uint32 buffer_size = r->in._data_size;
5991         uint8 *buffer = r->in.data.data;
5992         uint32 *buffer_written = &r->in._data_size;
5993         int snum;
5994         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5995
5996         if (!Printer) {
5997                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5998                         OUR_HANDLE(handle)));
5999                 *r->out.num_written = r->in._data_size;
6000                 return WERR_BADFID;
6001         }
6002
6003         if (!get_printer_snum(p, handle, &snum, NULL))
6004                 return WERR_BADFID;
6005
6006         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
6007                                         (SMB_OFF_T)-1, (size_t)buffer_size);
6008         if (*buffer_written == (uint32)-1) {
6009                 *r->out.num_written = 0;
6010                 if (errno == ENOSPC)
6011                         return WERR_NO_SPOOL_SPACE;
6012                 else
6013                         return WERR_ACCESS_DENIED;
6014         }
6015
6016         *r->out.num_written = r->in._data_size;
6017
6018         return WERR_OK;
6019 }
6020
6021 /********************************************************************
6022  * api_spoolss_getprinter
6023  * called from the spoolss dispatcher
6024  *
6025  ********************************************************************/
6026
6027 static WERROR control_printer(POLICY_HND *handle, uint32 command,
6028                               pipes_struct *p)
6029 {
6030         int snum;
6031         WERROR errcode = WERR_BADFUNC;
6032         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6033
6034         if (!Printer) {
6035                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6036                 return WERR_BADFID;
6037         }
6038
6039         if (!get_printer_snum(p, handle, &snum, NULL))
6040                 return WERR_BADFID;
6041
6042         switch (command) {
6043         case PRINTER_CONTROL_PAUSE:
6044                 if (print_queue_pause(p->server_info, snum, &errcode)) {
6045                         errcode = WERR_OK;
6046                 }
6047                 break;
6048         case PRINTER_CONTROL_RESUME:
6049         case PRINTER_CONTROL_UNPAUSE:
6050                 if (print_queue_resume(p->server_info, snum, &errcode)) {
6051                         errcode = WERR_OK;
6052                 }
6053                 break;
6054         case PRINTER_CONTROL_PURGE:
6055                 if (print_queue_purge(p->server_info, snum, &errcode)) {
6056                         errcode = WERR_OK;
6057                 }
6058                 break;
6059         default:
6060                 return WERR_UNKNOWN_LEVEL;
6061         }
6062
6063         return errcode;
6064 }
6065
6066
6067 /****************************************************************
6068  _spoolss_AbortPrinter
6069  * From MSDN: "Deletes printer's spool file if printer is configured
6070  * for spooling"
6071 ****************************************************************/
6072
6073 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6074                              struct spoolss_AbortPrinter *r)
6075 {
6076         POLICY_HND      *handle = r->in.handle;
6077         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6078         int             snum;
6079         WERROR          errcode = WERR_OK;
6080
6081         if (!Printer) {
6082                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6083                         OUR_HANDLE(handle)));
6084                 return WERR_BADFID;
6085         }
6086
6087         if (!get_printer_snum(p, handle, &snum, NULL))
6088                 return WERR_BADFID;
6089
6090         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6091
6092         return errcode;
6093 }
6094
6095 /********************************************************************
6096  * called by spoolss_api_setprinter
6097  * when updating a printer description
6098  ********************************************************************/
6099
6100 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6101                                  const SPOOL_PRINTER_INFO_LEVEL *info,
6102                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6103 {
6104         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6105         WERROR result;
6106         int snum;
6107
6108         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6109
6110         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6111                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6112                          OUR_HANDLE(handle)));
6113
6114                 result = WERR_BADFID;
6115                 goto done;
6116         }
6117
6118         if (!secdesc_ctr) {
6119                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6120                 result = WERR_INVALID_PARAM;
6121                 goto done;
6122         }
6123
6124         /* Check the user has permissions to change the security
6125            descriptor.  By experimentation with two NT machines, the user
6126            requires Full Access to the printer to change security
6127            information. */
6128
6129         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6130                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6131                 result = WERR_ACCESS_DENIED;
6132                 goto done;
6133         }
6134
6135         /* NT seems to like setting the security descriptor even though
6136            nothing may have actually changed. */
6137
6138         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6139                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6140                 result = WERR_BADFID;
6141                 goto done;
6142         }
6143
6144         if (DEBUGLEVEL >= 10) {
6145                 SEC_ACL *the_acl;
6146                 int i;
6147
6148                 the_acl = old_secdesc_ctr->sd->dacl;
6149                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6150                            PRINTERNAME(snum), the_acl->num_aces));
6151
6152                 for (i = 0; i < the_acl->num_aces; i++) {
6153                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6154                                            &the_acl->aces[i].trustee),
6155                                   the_acl->aces[i].access_mask));
6156                 }
6157
6158                 the_acl = secdesc_ctr->sd->dacl;
6159
6160                 if (the_acl) {
6161                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6162                                    PRINTERNAME(snum), the_acl->num_aces));
6163
6164                         for (i = 0; i < the_acl->num_aces; i++) {
6165                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6166                                                    &the_acl->aces[i].trustee),
6167                                            the_acl->aces[i].access_mask));
6168                         }
6169                 } else {
6170                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6171                 }
6172         }
6173
6174         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6175         if (!new_secdesc_ctr) {
6176                 result = WERR_NOMEM;
6177                 goto done;
6178         }
6179
6180         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6181                 result = WERR_OK;
6182                 goto done;
6183         }
6184
6185         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6186
6187  done:
6188
6189         return result;
6190 }
6191
6192 /********************************************************************
6193  Canonicalize printer info from a client
6194
6195  ATTN: It does not matter what we set the servername to hear
6196  since we do the necessary work in get_a_printer() to set it to
6197  the correct value based on what the client sent in the
6198  _spoolss_open_printer_ex().
6199  ********************************************************************/
6200
6201 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6202 {
6203         fstring printername;
6204         const char *p;
6205
6206         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6207                 "portname=%s drivername=%s comment=%s location=%s\n",
6208                 info->servername, info->printername, info->sharename,
6209                 info->portname, info->drivername, info->comment, info->location));
6210
6211         /* we force some elements to "correct" values */
6212         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6213         fstrcpy(info->sharename, lp_servicename(snum));
6214
6215         /* check to see if we allow printername != sharename */
6216
6217         if ( lp_force_printername(snum) ) {
6218                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6219                         global_myname(), info->sharename );
6220         } else {
6221
6222                 /* make sure printername is in \\server\printername format */
6223
6224                 fstrcpy( printername, info->printername );
6225                 p = printername;
6226                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6227                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6228                                 p++;
6229                 }
6230
6231                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6232                          global_myname(), p );
6233         }
6234
6235         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6236         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6237
6238
6239
6240         return True;
6241 }
6242
6243 /****************************************************************************
6244 ****************************************************************************/
6245
6246 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6247 {
6248         char *cmd = lp_addport_cmd();
6249         char *command = NULL;
6250         int ret;
6251         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6252         bool is_print_op = False;
6253
6254         if ( !*cmd ) {
6255                 return WERR_ACCESS_DENIED;
6256         }
6257
6258         command = talloc_asprintf(ctx,
6259                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6260         if (!command) {
6261                 return WERR_NOMEM;
6262         }
6263
6264         if ( token )
6265                 is_print_op = user_has_privileges( token, &se_printop );
6266
6267         DEBUG(10,("Running [%s]\n", command));
6268
6269         /********* BEGIN SePrintOperatorPrivilege **********/
6270
6271         if ( is_print_op )
6272                 become_root();
6273
6274         ret = smbrun(command, NULL);
6275
6276         if ( is_print_op )
6277                 unbecome_root();
6278
6279         /********* END SePrintOperatorPrivilege **********/
6280
6281         DEBUGADD(10,("returned [%d]\n", ret));
6282
6283         TALLOC_FREE(command);
6284
6285         if ( ret != 0 ) {
6286                 return WERR_ACCESS_DENIED;
6287         }
6288
6289         return WERR_OK;
6290 }
6291
6292 /****************************************************************************
6293 ****************************************************************************/
6294
6295 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6296 {
6297         char *cmd = lp_addprinter_cmd();
6298         char **qlines;
6299         char *command = NULL;
6300         int numlines;
6301         int ret;
6302         int fd;
6303         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6304         bool is_print_op = False;
6305         char *remote_machine = talloc_strdup(ctx, "%m");
6306
6307         if (!remote_machine) {
6308                 return false;
6309         }
6310         remote_machine = talloc_sub_basic(ctx,
6311                                 current_user_info.smb_name,
6312                                 current_user_info.domain,
6313                                 remote_machine);
6314         if (!remote_machine) {
6315                 return false;
6316         }
6317
6318         command = talloc_asprintf(ctx,
6319                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6320                         cmd, printer->info_2->printername, printer->info_2->sharename,
6321                         printer->info_2->portname, printer->info_2->drivername,
6322                         printer->info_2->location, printer->info_2->comment, remote_machine);
6323         if (!command) {
6324                 return false;
6325         }
6326
6327         if ( token )
6328                 is_print_op = user_has_privileges( token, &se_printop );
6329
6330         DEBUG(10,("Running [%s]\n", command));
6331
6332         /********* BEGIN SePrintOperatorPrivilege **********/
6333
6334         if ( is_print_op )
6335                 become_root();
6336
6337         if ( (ret = smbrun(command, &fd)) == 0 ) {
6338                 /* Tell everyone we updated smb.conf. */
6339                 message_send_all(smbd_messaging_context(),
6340                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6341         }
6342
6343         if ( is_print_op )
6344                 unbecome_root();
6345
6346         /********* END SePrintOperatorPrivilege **********/
6347
6348         DEBUGADD(10,("returned [%d]\n", ret));
6349
6350         TALLOC_FREE(command);
6351         TALLOC_FREE(remote_machine);
6352
6353         if ( ret != 0 ) {
6354                 if (fd != -1)
6355                         close(fd);
6356                 return False;
6357         }
6358
6359         /* reload our services immediately */
6360         reload_services( False );
6361
6362         numlines = 0;
6363         /* Get lines and convert them back to dos-codepage */
6364         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6365         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6366         close(fd);
6367
6368         /* Set the portname to what the script says the portname should be. */
6369         /* but don't require anything to be return from the script exit a good error code */
6370
6371         if (numlines) {
6372                 /* Set the portname to what the script says the portname should be. */
6373                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6374                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6375         }
6376
6377         TALLOC_FREE(qlines);
6378         return True;
6379 }
6380
6381
6382 /********************************************************************
6383  * Called by spoolss_api_setprinter
6384  * when updating a printer description.
6385  ********************************************************************/
6386
6387 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6388                            const SPOOL_PRINTER_INFO_LEVEL *info,
6389                            DEVICEMODE *devmode)
6390 {
6391         int snum;
6392         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6393         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6394         WERROR result;
6395         UNISTR2 buffer;
6396         fstring asc_buffer;
6397
6398         DEBUG(8,("update_printer\n"));
6399
6400         result = WERR_OK;
6401
6402         if (!Printer) {
6403                 result = WERR_BADFID;
6404                 goto done;
6405         }
6406
6407         if (!get_printer_snum(p, handle, &snum, NULL)) {
6408                 result = WERR_BADFID;
6409                 goto done;
6410         }
6411
6412         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6413             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6414                 result = WERR_BADFID;
6415                 goto done;
6416         }
6417
6418         DEBUGADD(8,("Converting info_2 struct\n"));
6419
6420         /*
6421          * convert_printer_info converts the incoming
6422          * info from the client and overwrites the info
6423          * just read from the tdb in the pointer 'printer'.
6424          */
6425
6426         if (!convert_printer_info(info, printer, level)) {
6427                 result =  WERR_NOMEM;
6428                 goto done;
6429         }
6430
6431         if (devmode) {
6432                 /* we have a valid devmode
6433                    convert it and link it*/
6434
6435                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6436                 if (!convert_devicemode(printer->info_2->printername, devmode,
6437                                 &printer->info_2->devmode)) {
6438                         result =  WERR_NOMEM;
6439                         goto done;
6440                 }
6441         }
6442
6443         /* Do sanity check on the requested changes for Samba */
6444
6445         if (!check_printer_ok(printer->info_2, snum)) {
6446                 result = WERR_INVALID_PARAM;
6447                 goto done;
6448         }
6449
6450         /* FIXME!!! If the driver has changed we really should verify that
6451            it is installed before doing much else   --jerry */
6452
6453         /* Check calling user has permission to update printer description */
6454
6455         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6456                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6457                 result = WERR_ACCESS_DENIED;
6458                 goto done;
6459         }
6460
6461         /* Call addprinter hook */
6462         /* Check changes to see if this is really needed */
6463
6464         if ( *lp_addprinter_cmd()
6465                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6466                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6467                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6468                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6469         {
6470                 /* add_printer_hook() will call reload_services() */
6471
6472                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6473                                        printer) ) {
6474                         result = WERR_ACCESS_DENIED;
6475                         goto done;
6476                 }
6477         }
6478
6479         /*
6480          * When a *new* driver is bound to a printer, the drivername is used to
6481          * lookup previously saved driver initialization info, which is then
6482          * bound to the printer, simulating what happens in the Windows arch.
6483          */
6484         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6485         {
6486                 if (!set_driver_init(printer, 2))
6487                 {
6488                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6489                                 printer->info_2->drivername));
6490                 }
6491
6492                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6493                         printer->info_2->drivername));
6494
6495                 notify_printer_driver(snum, printer->info_2->drivername);
6496         }
6497
6498         /*
6499          * flag which changes actually occured.  This is a small subset of
6500          * all the possible changes.  We also have to update things in the
6501          * DsSpooler key.
6502          */
6503
6504         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6505                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6506                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6507                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6508
6509                 notify_printer_comment(snum, printer->info_2->comment);
6510         }
6511
6512         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6513                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6514                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6515                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6516
6517                 notify_printer_sharename(snum, printer->info_2->sharename);
6518         }
6519
6520         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6521                 char *pname;
6522
6523                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6524                         pname++;
6525                 else
6526                         pname = printer->info_2->printername;
6527
6528
6529                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6530                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6531                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6532
6533                 notify_printer_printername( snum, pname );
6534         }
6535
6536         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6537                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6538                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6539                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6540
6541                 notify_printer_port(snum, printer->info_2->portname);
6542         }
6543
6544         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6545                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6546                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6547                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6548
6549                 notify_printer_location(snum, printer->info_2->location);
6550         }
6551
6552         /* here we need to update some more DsSpooler keys */
6553         /* uNCName, serverName, shortServerName */
6554
6555         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6556         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6557                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6558         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6559                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6560
6561         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6562                  global_myname(), printer->info_2->sharename );
6563         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6564         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6565                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6566
6567         /* Update printer info */
6568         result = mod_a_printer(printer, 2);
6569
6570 done:
6571         free_a_printer(&printer, 2);
6572         free_a_printer(&old_printer, 2);
6573
6574
6575         return result;
6576 }
6577
6578 /****************************************************************************
6579 ****************************************************************************/
6580 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6581                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6582 {
6583 #ifdef HAVE_ADS
6584         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6585         int snum;
6586         Printer_entry *Printer;
6587
6588         if ( lp_security() != SEC_ADS ) {
6589                 return WERR_UNKNOWN_LEVEL;
6590         }
6591
6592         Printer = find_printer_index_by_hnd(p, handle);
6593
6594         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6595
6596         if (!Printer)
6597                 return WERR_BADFID;
6598
6599         if (!get_printer_snum(p, handle, &snum, NULL))
6600                 return WERR_BADFID;
6601
6602         nt_printer_publish(Printer, snum, info7->action);
6603
6604         return WERR_OK;
6605 #else
6606         return WERR_UNKNOWN_LEVEL;
6607 #endif
6608 }
6609 /****************************************************************************
6610 ****************************************************************************/
6611
6612 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6613 {
6614         POLICY_HND *handle = &q_u->handle;
6615         uint32 level = q_u->level;
6616         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6617         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6618         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6619         uint32 command = q_u->command;
6620         WERROR result;
6621
6622         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6623
6624         if (!Printer) {
6625                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6626                 return WERR_BADFID;
6627         }
6628
6629         /* check the level */
6630         switch (level) {
6631                 case 0:
6632                         return control_printer(handle, command, p);
6633                 case 2:
6634                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6635                         if (!W_ERROR_IS_OK(result))
6636                                 return result;
6637                         if (secdesc_ctr)
6638                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6639                         return result;
6640                 case 3:
6641                         return update_printer_sec(handle, level, info, p,
6642                                                   secdesc_ctr);
6643                 case 7:
6644                         return publish_or_unpublish_printer(p, handle, info);
6645                 default:
6646                         return WERR_UNKNOWN_LEVEL;
6647         }
6648 }
6649
6650 /****************************************************************
6651  _spoolss_FindClosePrinterNotify
6652 ****************************************************************/
6653
6654 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6655                                        struct spoolss_FindClosePrinterNotify *r)
6656 {
6657         POLICY_HND *handle = r->in.handle;
6658         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6659
6660         if (!Printer) {
6661                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6662                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6663                 return WERR_BADFID;
6664         }
6665
6666         if (Printer->notify.client_connected==True) {
6667                 int snum = -1;
6668
6669                 if ( Printer->printer_type == SPLHND_SERVER)
6670                         snum = -1;
6671                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6672                                 !get_printer_snum(p, handle, &snum, NULL) )
6673                         return WERR_BADFID;
6674
6675                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6676         }
6677
6678         Printer->notify.flags=0;
6679         Printer->notify.options=0;
6680         Printer->notify.localmachine[0]='\0';
6681         Printer->notify.printerlocal=0;
6682         if (Printer->notify.option)
6683                 free_spool_notify_option(&Printer->notify.option);
6684         Printer->notify.client_connected=False;
6685
6686         return WERR_OK;
6687 }
6688
6689 /****************************************************************
6690  _spoolss_AddJob
6691 ****************************************************************/
6692
6693 WERROR _spoolss_AddJob(pipes_struct *p,
6694                        struct spoolss_AddJob *r)
6695 {
6696         if (!r->in.buffer && (r->in.offered != 0)) {
6697                 return WERR_INVALID_PARAM;
6698         }
6699
6700         /* this is what a NT server returns for AddJob. AddJob must fail on
6701          * non-local printers */
6702
6703         return WERR_INVALID_PARAM;
6704 }
6705
6706 /****************************************************************************
6707 ****************************************************************************/
6708
6709 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6710                             int position, int snum,
6711                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6712 {
6713         struct tm *t;
6714
6715         t=gmtime(&queue->time);
6716
6717         job_info->jobid=queue->job;
6718         init_unistr(&job_info->printername, lp_servicename(snum));
6719         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6720         init_unistr(&job_info->username, queue->fs_user);
6721         init_unistr(&job_info->document, queue->fs_file);
6722         init_unistr(&job_info->datatype, "RAW");
6723         init_unistr(&job_info->text_status, "");
6724         job_info->status=nt_printj_status(queue->status);
6725         job_info->priority=queue->priority;
6726         job_info->position=position;
6727         job_info->totalpages=queue->page_count;
6728         job_info->pagesprinted=0;
6729
6730         make_systemtime(&job_info->submitted, t);
6731 }
6732
6733 /****************************************************************************
6734 ****************************************************************************/
6735
6736 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6737                             int position, int snum,
6738                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6739                             DEVICEMODE *devmode)
6740 {
6741         struct tm *t;
6742
6743         t=gmtime(&queue->time);
6744
6745         job_info->jobid=queue->job;
6746
6747         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6748
6749         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6750         init_unistr(&job_info->username, queue->fs_user);
6751         init_unistr(&job_info->document, queue->fs_file);
6752         init_unistr(&job_info->notifyname, queue->fs_user);
6753         init_unistr(&job_info->datatype, "RAW");
6754         init_unistr(&job_info->printprocessor, "winprint");
6755         init_unistr(&job_info->parameters, "");
6756         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6757         init_unistr(&job_info->text_status, "");
6758
6759 /* and here the security descriptor */
6760
6761         job_info->status=nt_printj_status(queue->status);
6762         job_info->priority=queue->priority;
6763         job_info->position=position;
6764         job_info->starttime=0;
6765         job_info->untiltime=0;
6766         job_info->totalpages=queue->page_count;
6767         job_info->size=queue->size;
6768         make_systemtime(&(job_info->submitted), t);
6769         job_info->timeelapsed=0;
6770         job_info->pagesprinted=0;
6771
6772         job_info->devmode = devmode;
6773
6774         return (True);
6775 }
6776
6777 /****************************************************************************
6778  Enumjobs at level 1.
6779 ****************************************************************************/
6780
6781 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6782                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6783                               RPC_BUFFER *buffer, uint32 offered,
6784                               uint32 *needed, uint32 *returned)
6785 {
6786         JOB_INFO_1 *info;
6787         int i;
6788         WERROR result = WERR_OK;
6789
6790         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6791         if (info==NULL) {
6792                 *returned=0;
6793                 return WERR_NOMEM;
6794         }
6795
6796         for (i=0; i<*returned; i++)
6797                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6798
6799         /* check the required size. */
6800         for (i=0; i<*returned; i++)
6801                 (*needed) += spoolss_size_job_info_1(&info[i]);
6802
6803         if (*needed > offered) {
6804                 result = WERR_INSUFFICIENT_BUFFER;
6805                 goto out;
6806         }
6807
6808         if (!rpcbuf_alloc_size(buffer, *needed)) {
6809                 result = WERR_NOMEM;
6810                 goto out;
6811         }
6812
6813         /* fill the buffer with the structures */
6814         for (i=0; i<*returned; i++)
6815                 smb_io_job_info_1("", buffer, &info[i], 0);
6816
6817 out:
6818         /* clear memory */
6819         SAFE_FREE(info);
6820
6821         if ( !W_ERROR_IS_OK(result) )
6822                 *returned = 0;
6823
6824         return result;
6825 }
6826
6827 /****************************************************************************
6828  Enumjobs at level 2.
6829 ****************************************************************************/
6830
6831 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6832                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6833                               RPC_BUFFER *buffer, uint32 offered,
6834                               uint32 *needed, uint32 *returned)
6835 {
6836         JOB_INFO_2 *info = NULL;
6837         int i;
6838         WERROR result = WERR_OK;
6839         DEVICEMODE *devmode = NULL;
6840
6841         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6842                 *returned=0;
6843                 return WERR_NOMEM;
6844         }
6845
6846         /* this should not be a failure condition if the devmode is NULL */
6847
6848         devmode = construct_dev_mode(lp_const_servicename(snum));
6849
6850         for (i=0; i<*returned; i++)
6851                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6852
6853         /* check the required size. */
6854         for (i=0; i<*returned; i++)
6855                 (*needed) += spoolss_size_job_info_2(&info[i]);
6856
6857         if (*needed > offered) {
6858                 result = WERR_INSUFFICIENT_BUFFER;
6859                 goto out;
6860         }
6861
6862         if (!rpcbuf_alloc_size(buffer, *needed)) {
6863                 result = WERR_NOMEM;
6864                 goto out;
6865         }
6866
6867         /* fill the buffer with the structures */
6868         for (i=0; i<*returned; i++)
6869                 smb_io_job_info_2("", buffer, &info[i], 0);
6870
6871 out:
6872         free_devmode(devmode);
6873         SAFE_FREE(info);
6874
6875         if ( !W_ERROR_IS_OK(result) )
6876                 *returned = 0;
6877
6878         return result;
6879
6880 }
6881
6882 /****************************************************************************
6883  Enumjobs.
6884 ****************************************************************************/
6885
6886 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6887 {
6888         POLICY_HND *handle = &q_u->handle;
6889         uint32 level = q_u->level;
6890         RPC_BUFFER *buffer = NULL;
6891         uint32 offered = q_u->offered;
6892         uint32 *needed = &r_u->needed;
6893         uint32 *returned = &r_u->returned;
6894         WERROR wret;
6895         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6896         int snum;
6897         print_status_struct prt_status;
6898         print_queue_struct *queue=NULL;
6899
6900         /* that's an [in out] buffer */
6901
6902         if (!q_u->buffer && (offered!=0)) {
6903                 return WERR_INVALID_PARAM;
6904         }
6905
6906         rpcbuf_move(q_u->buffer, &r_u->buffer);
6907         buffer = r_u->buffer;
6908
6909         DEBUG(4,("_spoolss_enumjobs\n"));
6910
6911         *needed=0;
6912         *returned=0;
6913
6914         /* lookup the printer snum and tdb entry */
6915
6916         if (!get_printer_snum(p, handle, &snum, NULL))
6917                 return WERR_BADFID;
6918
6919         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6920         if ( !W_ERROR_IS_OK(wret) )
6921                 return wret;
6922
6923         *returned = print_queue_status(snum, &queue, &prt_status);
6924         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6925
6926         if (*returned == 0) {
6927                 SAFE_FREE(queue);
6928                 free_a_printer(&ntprinter, 2);
6929                 return WERR_OK;
6930         }
6931
6932         switch (level) {
6933         case 1:
6934                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6935                 break;
6936         case 2:
6937                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6938                 break;
6939         default:
6940                 *returned=0;
6941                 wret = WERR_UNKNOWN_LEVEL;
6942                 break;
6943         }
6944
6945         SAFE_FREE(queue);
6946         free_a_printer( &ntprinter, 2 );
6947         return wret;
6948 }
6949
6950 /****************************************************************
6951  _spoolss_ScheduleJob
6952 ****************************************************************/
6953
6954 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6955                             struct spoolss_ScheduleJob *r)
6956 {
6957         return WERR_OK;
6958 }
6959
6960 /****************************************************************
6961  _spoolss_SetJob
6962 ****************************************************************/
6963
6964 WERROR _spoolss_SetJob(pipes_struct *p,
6965                        struct spoolss_SetJob *r)
6966 {
6967         POLICY_HND *handle = r->in.handle;
6968         uint32 jobid = r->in.job_id;
6969         uint32 command = r->in.command;
6970
6971         int snum;
6972         WERROR errcode = WERR_BADFUNC;
6973
6974         if (!get_printer_snum(p, handle, &snum, NULL)) {
6975                 return WERR_BADFID;
6976         }
6977
6978         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6979                 return WERR_INVALID_PRINTER_NAME;
6980         }
6981
6982         switch (command) {
6983         case SPOOLSS_JOB_CONTROL_CANCEL:
6984         case SPOOLSS_JOB_CONTROL_DELETE:
6985                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6986                         errcode = WERR_OK;
6987                 }
6988                 break;
6989         case SPOOLSS_JOB_CONTROL_PAUSE:
6990                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6991                         errcode = WERR_OK;
6992                 }
6993                 break;
6994         case SPOOLSS_JOB_CONTROL_RESTART:
6995         case SPOOLSS_JOB_CONTROL_RESUME:
6996                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6997                         errcode = WERR_OK;
6998                 }
6999                 break;
7000         default:
7001                 return WERR_UNKNOWN_LEVEL;
7002         }
7003
7004         return errcode;
7005 }
7006
7007 /****************************************************************************
7008  Enumerates all printer drivers at level 1.
7009 ****************************************************************************/
7010
7011 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7012 {
7013         int i;
7014         int ndrivers;
7015         uint32 version;
7016         fstring *list = NULL;
7017         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7018         DRIVER_INFO_1 *driver_info_1=NULL;
7019         WERROR result = WERR_OK;
7020
7021         *returned=0;
7022
7023         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7024                 list=NULL;
7025                 ndrivers=get_ntdrivers(&list, architecture, version);
7026                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7027
7028                 if(ndrivers == -1) {
7029                         SAFE_FREE(driver_info_1);
7030                         return WERR_NOMEM;
7031                 }
7032
7033                 if(ndrivers != 0) {
7034                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
7035                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
7036                                 SAFE_FREE(list);
7037                                 return WERR_NOMEM;
7038                         }
7039                 }
7040
7041                 for (i=0; i<ndrivers; i++) {
7042                         WERROR status;
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_1);
7050                                 return status;
7051                         }
7052                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
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_1(&driver_info_1[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 driver structures */
7077         for (i=0; i<*returned; i++) {
7078                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7079                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7080         }
7081
7082 out:
7083         SAFE_FREE(driver_info_1);
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 2.
7093 ****************************************************************************/
7094
7095 static WERROR enumprinterdrivers_level2(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         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7102         DRIVER_INFO_2 *driver_info_2=NULL;
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_2);
7114                         return WERR_NOMEM;
7115                 }
7116
7117                 if(ndrivers != 0) {
7118                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7119                                 DEBUG(0,("enumprinterdrivers_level2: 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_2);
7135                                 return status;
7136                         }
7137                         fill_printer_driver_info_2(&driver_info_2[*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_2(&(driver_info_2[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 form structures */
7162         for (i=0; i<*returned; i++) {
7163                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7164                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7165         }
7166
7167 out:
7168         SAFE_FREE(driver_info_2);
7169
7170         if ( !W_ERROR_IS_OK(result) )
7171                 *returned = 0;
7172
7173         return result;
7174 }
7175
7176 /****************************************************************************
7177  Enumerates all printer drivers at level 3.
7178 ****************************************************************************/
7179
7180 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7181 {
7182         int i;
7183         int ndrivers;
7184         uint32 version;
7185         fstring *list = NULL;
7186         DRIVER_INFO_3 *driver_info_3=NULL;
7187         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7188         WERROR result = WERR_OK;
7189
7190         *returned=0;
7191
7192         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7193                 list=NULL;
7194                 ndrivers=get_ntdrivers(&list, architecture, version);
7195                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7196
7197                 if(ndrivers == -1) {
7198                         SAFE_FREE(driver_info_3);
7199                         return WERR_NOMEM;
7200                 }
7201
7202                 if(ndrivers != 0) {
7203                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7204                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7205                                 SAFE_FREE(list);
7206                                 return WERR_NOMEM;
7207                         }
7208                 }
7209
7210                 for (i=0; i<ndrivers; i++) {
7211                         WERROR status;
7212
7213                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7214                         ZERO_STRUCT(driver);
7215                         status = get_a_printer_driver(&driver, 3, list[i],
7216                                                       architecture, version);
7217                         if (!W_ERROR_IS_OK(status)) {
7218                                 SAFE_FREE(list);
7219                                 SAFE_FREE(driver_info_3);
7220                                 return status;
7221                         }
7222                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7223                         free_a_printer_driver(driver, 3);
7224                 }
7225
7226                 *returned+=ndrivers;
7227                 SAFE_FREE(list);
7228         }
7229
7230         /* check the required size. */
7231         for (i=0; i<*returned; i++) {
7232                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7233                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7234         }
7235
7236         if (*needed > offered) {
7237                 result = WERR_INSUFFICIENT_BUFFER;
7238                 goto out;
7239         }
7240
7241         if (!rpcbuf_alloc_size(buffer, *needed)) {
7242                 result = WERR_NOMEM;
7243                 goto out;
7244         }
7245
7246         /* fill the buffer with the driver structures */
7247         for (i=0; i<*returned; i++) {
7248                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7249                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7250         }
7251
7252 out:
7253         for (i=0; i<*returned; i++) {
7254                 SAFE_FREE(driver_info_3[i].dependentfiles);
7255         }
7256
7257         SAFE_FREE(driver_info_3);
7258
7259         if ( !W_ERROR_IS_OK(result) )
7260                 *returned = 0;
7261
7262         return result;
7263 }
7264
7265 /****************************************************************************
7266  Enumerates all printer drivers.
7267 ****************************************************************************/
7268
7269 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7270 {
7271         uint32 level = q_u->level;
7272         RPC_BUFFER *buffer = NULL;
7273         uint32 offered = q_u->offered;
7274         uint32 *needed = &r_u->needed;
7275         uint32 *returned = &r_u->returned;
7276         const char *cservername;
7277         fstring servername;
7278         fstring architecture;
7279
7280         /* that's an [in out] buffer */
7281
7282         if (!q_u->buffer && (offered!=0)) {
7283                 return WERR_INVALID_PARAM;
7284         }
7285
7286         rpcbuf_move(q_u->buffer, &r_u->buffer);
7287         buffer = r_u->buffer;
7288
7289         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7290
7291         *needed   = 0;
7292         *returned = 0;
7293
7294         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7295         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7296
7297         cservername = canon_servername(servername);
7298
7299         if (!is_myname_or_ipaddr(cservername))
7300                 return WERR_UNKNOWN_PRINTER_DRIVER;
7301
7302         switch (level) {
7303         case 1:
7304                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7305         case 2:
7306                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7307         case 3:
7308                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7309         default:
7310                 return WERR_UNKNOWN_LEVEL;
7311         }
7312 }
7313
7314 /****************************************************************************
7315 ****************************************************************************/
7316
7317 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7318 {
7319         form->flag=list->flag;
7320         init_unistr(&form->name, list->name);
7321         form->width=list->width;
7322         form->length=list->length;
7323         form->left=list->left;
7324         form->top=list->top;
7325         form->right=list->right;
7326         form->bottom=list->bottom;
7327 }
7328
7329 /****************************************************************************
7330 ****************************************************************************/
7331
7332 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7333                                struct spoolss_FormInfo1 *form,
7334                                nt_forms_struct *list)
7335 {
7336         form->form_name         = talloc_strdup(mem_ctx, list->name);
7337         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7338
7339         form->flags             = list->flag;
7340         form->size.width        = list->width;
7341         form->size.height       = list->length;
7342         form->area.left         = list->left;
7343         form->area.top          = list->top;
7344         form->area.right        = list->right;
7345         form->area.bottom       = list->bottom;
7346
7347         return WERR_OK;
7348 }
7349
7350 /****************************************************************************
7351 ****************************************************************************/
7352
7353 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7354 {
7355         uint32 level = q_u->level;
7356         RPC_BUFFER *buffer = NULL;
7357         uint32 offered = q_u->offered;
7358         uint32 *needed = &r_u->needed;
7359         uint32 *numofforms = &r_u->numofforms;
7360         uint32 numbuiltinforms;
7361
7362         nt_forms_struct *list=NULL;
7363         nt_forms_struct *builtinlist=NULL;
7364         FORM_1 *forms_1;
7365         int buffer_size=0;
7366         int i;
7367
7368         /* that's an [in out] buffer */
7369
7370         if (!q_u->buffer && (offered!=0) ) {
7371                 return WERR_INVALID_PARAM;
7372         }
7373
7374         rpcbuf_move(q_u->buffer, &r_u->buffer);
7375         buffer = r_u->buffer;
7376
7377         DEBUG(4,("_spoolss_enumforms\n"));
7378         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7379         DEBUGADD(5,("Info level [%d]\n",          level));
7380
7381         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7382         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7383         *numofforms = get_ntforms(&list);
7384         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7385         *numofforms += numbuiltinforms;
7386
7387         if (*numofforms == 0) {
7388                 SAFE_FREE(builtinlist);
7389                 SAFE_FREE(list);
7390                 return WERR_NO_MORE_ITEMS;
7391         }
7392
7393         switch (level) {
7394         case 1:
7395                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7396                         SAFE_FREE(builtinlist);
7397                         SAFE_FREE(list);
7398                         *numofforms=0;
7399                         return WERR_NOMEM;
7400                 }
7401
7402                 /* construct the list of form structures */
7403                 for (i=0; i<numbuiltinforms; i++) {
7404                         DEBUGADD(6,("Filling form number [%d]\n",i));
7405                         fill_form_1(&forms_1[i], &builtinlist[i]);
7406                 }
7407
7408                 SAFE_FREE(builtinlist);
7409
7410                 for (; i<*numofforms; i++) {
7411                         DEBUGADD(6,("Filling form number [%d]\n",i));
7412                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7413                 }
7414
7415                 SAFE_FREE(list);
7416
7417                 /* check the required size. */
7418                 for (i=0; i<numbuiltinforms; i++) {
7419                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7420                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7421                 }
7422                 for (; i<*numofforms; i++) {
7423                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7424                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7425                 }
7426
7427                 *needed=buffer_size;
7428
7429                 if (*needed > offered) {
7430                         SAFE_FREE(forms_1);
7431                         *numofforms=0;
7432                         return WERR_INSUFFICIENT_BUFFER;
7433                 }
7434
7435                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7436                         SAFE_FREE(forms_1);
7437                         *numofforms=0;
7438                         return WERR_NOMEM;
7439                 }
7440
7441                 /* fill the buffer with the form structures */
7442                 for (i=0; i<numbuiltinforms; i++) {
7443                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7444                         smb_io_form_1("", buffer, &forms_1[i], 0);
7445                 }
7446                 for (; i<*numofforms; i++) {
7447                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7448                         smb_io_form_1("", buffer, &forms_1[i], 0);
7449                 }
7450
7451                 SAFE_FREE(forms_1);
7452
7453                 return WERR_OK;
7454
7455         default:
7456                 SAFE_FREE(list);
7457                 SAFE_FREE(builtinlist);
7458                 return WERR_UNKNOWN_LEVEL;
7459         }
7460 }
7461
7462 /****************************************************************
7463  _spoolss_GetForm
7464 ****************************************************************/
7465
7466 WERROR _spoolss_GetForm(pipes_struct *p,
7467                         struct spoolss_GetForm *r)
7468 {
7469         uint32 level = r->in.level;
7470         uint32 offered = r->in.offered;
7471         uint32 *needed = r->out.needed;
7472
7473         nt_forms_struct *list=NULL;
7474         nt_forms_struct builtin_form;
7475         bool foundBuiltin;
7476         union spoolss_FormInfo info;
7477         struct spoolss_FormInfo1 form_1;
7478         int numofforms=0, i=0;
7479
7480         /* that's an [in out] buffer */
7481
7482         if (!r->in.buffer && (offered!=0)) {
7483                 return WERR_INVALID_PARAM;
7484         }
7485
7486         DEBUG(4,("_spoolss_GetForm\n"));
7487         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7488         DEBUGADD(5,("Info level [%d]\n",          level));
7489
7490         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7491         if (!foundBuiltin) {
7492                 numofforms = get_ntforms(&list);
7493                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7494
7495                 if (numofforms == 0)
7496                         return WERR_BADFID;
7497         }
7498
7499         switch (level) {
7500         case 1:
7501                 if (foundBuiltin) {
7502                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7503                 } else {
7504
7505                         /* Check if the requested name is in the list of form structures */
7506                         for (i=0; i<numofforms; i++) {
7507
7508                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7509                                         list[i].name, r->in.form_name));
7510
7511                                 if (strequal(r->in.form_name, list[i].name)) {
7512                                         DEBUGADD(6,("Found form %s number [%d]\n",
7513                                                 r->in.form_name, i));
7514                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7515                                         break;
7516                                 }
7517                         }
7518
7519                         SAFE_FREE(list);
7520                         if (i == numofforms) {
7521                                 return WERR_BADFID;
7522                         }
7523                 }
7524                 /* check the required size. */
7525
7526                 info.info1 = form_1;
7527
7528                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7529
7530                 if (*needed > offered) {
7531                         r->out.info = NULL;
7532                         return WERR_INSUFFICIENT_BUFFER;
7533                 }
7534
7535                 r->out.info->info1 = form_1;
7536
7537                 /* fill the buffer with the form structures */
7538                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7539                         r->in.form_name, i));
7540
7541                 return WERR_OK;
7542
7543         default:
7544                 SAFE_FREE(list);
7545                 return WERR_UNKNOWN_LEVEL;
7546         }
7547 }
7548
7549 /****************************************************************************
7550 ****************************************************************************/
7551
7552 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7553 {
7554         init_unistr(&port->port_name, name);
7555 }
7556
7557 /****************************************************************************
7558  TODO: This probably needs distinguish between TCP/IP and Local ports
7559  somehow.
7560 ****************************************************************************/
7561
7562 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7563 {
7564         init_unistr(&port->port_name, name);
7565         init_unistr(&port->monitor_name, "Local Monitor");
7566         init_unistr(&port->description, SPL_LOCAL_PORT );
7567         port->port_type=PORT_TYPE_WRITE;
7568         port->reserved=0x0;
7569 }
7570
7571
7572 /****************************************************************************
7573  wrapper around the enumer ports command
7574 ****************************************************************************/
7575
7576 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7577 {
7578         char *cmd = lp_enumports_cmd();
7579         char **qlines = NULL;
7580         char *command = NULL;
7581         int numlines;
7582         int ret;
7583         int fd;
7584
7585         *count = 0;
7586         *lines = NULL;
7587
7588         /* if no hook then just fill in the default port */
7589
7590         if ( !*cmd ) {
7591                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7592                         return WERR_NOMEM;
7593                 }
7594                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7595                         TALLOC_FREE(qlines);
7596                         return WERR_NOMEM;
7597                 }
7598                 qlines[1] = NULL;
7599                 numlines = 1;
7600         }
7601         else {
7602                 /* we have a valid enumport command */
7603
7604                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7605                 if (!command) {
7606                         return WERR_NOMEM;
7607                 }
7608
7609                 DEBUG(10,("Running [%s]\n", command));
7610                 ret = smbrun(command, &fd);
7611                 DEBUG(10,("Returned [%d]\n", ret));
7612                 TALLOC_FREE(command);
7613                 if (ret != 0) {
7614                         if (fd != -1) {
7615                                 close(fd);
7616                         }
7617                         return WERR_ACCESS_DENIED;
7618                 }
7619
7620                 numlines = 0;
7621                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7622                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7623                 close(fd);
7624         }
7625
7626         *count = numlines;
7627         *lines = qlines;
7628
7629         return WERR_OK;
7630 }
7631
7632 /****************************************************************************
7633  enumports level 1.
7634 ****************************************************************************/
7635
7636 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7637 {
7638         PORT_INFO_1 *ports=NULL;
7639         int i=0;
7640         WERROR result = WERR_OK;
7641         char **qlines = NULL;
7642         int numlines = 0;
7643
7644         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7645         if (!W_ERROR_IS_OK(result)) {
7646                 TALLOC_FREE(qlines);
7647                 return result;
7648         }
7649
7650         if(numlines) {
7651                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7652                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7653                                   win_errstr(WERR_NOMEM)));
7654                         TALLOC_FREE(qlines);
7655                         return WERR_NOMEM;
7656                 }
7657
7658                 for (i=0; i<numlines; i++) {
7659                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7660                         fill_port_1(&ports[i], qlines[i]);
7661                 }
7662         }
7663         TALLOC_FREE(qlines);
7664
7665         *returned = numlines;
7666
7667         /* check the required size. */
7668         for (i=0; i<*returned; i++) {
7669                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7670                 *needed += spoolss_size_port_info_1(&ports[i]);
7671         }
7672
7673         if (*needed > offered) {
7674                 result = WERR_INSUFFICIENT_BUFFER;
7675                 goto out;
7676         }
7677
7678         if (!rpcbuf_alloc_size(buffer, *needed)) {
7679                 result = WERR_NOMEM;
7680                 goto out;
7681         }
7682
7683         /* fill the buffer with the ports structures */
7684         for (i=0; i<*returned; i++) {
7685                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7686                 smb_io_port_1("", buffer, &ports[i], 0);
7687         }
7688
7689 out:
7690         SAFE_FREE(ports);
7691
7692         if ( !W_ERROR_IS_OK(result) )
7693                 *returned = 0;
7694
7695         return result;
7696 }
7697
7698 /****************************************************************************
7699  enumports level 2.
7700 ****************************************************************************/
7701
7702 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7703 {
7704         PORT_INFO_2 *ports=NULL;
7705         int i=0;
7706         WERROR result = WERR_OK;
7707         char **qlines = NULL;
7708         int numlines = 0;
7709
7710         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7711         if ( !W_ERROR_IS_OK(result)) {
7712                 TALLOC_FREE(qlines);
7713                 return result;
7714         }
7715
7716         if(numlines) {
7717                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7718                         TALLOC_FREE(qlines);
7719                         return WERR_NOMEM;
7720                 }
7721
7722                 for (i=0; i<numlines; i++) {
7723                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7724                         fill_port_2(&(ports[i]), qlines[i]);
7725                 }
7726         }
7727
7728         TALLOC_FREE(qlines);
7729
7730         *returned = numlines;
7731
7732         /* check the required size. */
7733         for (i=0; i<*returned; i++) {
7734                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7735                 *needed += spoolss_size_port_info_2(&ports[i]);
7736         }
7737
7738         if (*needed > offered) {
7739                 result = WERR_INSUFFICIENT_BUFFER;
7740                 goto out;
7741         }
7742
7743         if (!rpcbuf_alloc_size(buffer, *needed)) {
7744                 result = WERR_NOMEM;
7745                 goto out;
7746         }
7747
7748         /* fill the buffer with the ports structures */
7749         for (i=0; i<*returned; i++) {
7750                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7751                 smb_io_port_2("", buffer, &ports[i], 0);
7752         }
7753
7754 out:
7755         SAFE_FREE(ports);
7756
7757         if ( !W_ERROR_IS_OK(result) )
7758                 *returned = 0;
7759
7760         return result;
7761 }
7762
7763 /****************************************************************************
7764  enumports.
7765 ****************************************************************************/
7766
7767 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7768 {
7769         uint32 level = q_u->level;
7770         RPC_BUFFER *buffer = NULL;
7771         uint32 offered = q_u->offered;
7772         uint32 *needed = &r_u->needed;
7773         uint32 *returned = &r_u->returned;
7774
7775         /* that's an [in out] buffer */
7776
7777         if (!q_u->buffer && (offered!=0)) {
7778                 return WERR_INVALID_PARAM;
7779         }
7780
7781         rpcbuf_move(q_u->buffer, &r_u->buffer);
7782         buffer = r_u->buffer;
7783
7784         DEBUG(4,("_spoolss_enumports\n"));
7785
7786         *returned=0;
7787         *needed=0;
7788
7789         switch (level) {
7790         case 1:
7791                 return enumports_level_1(buffer, offered, needed, returned);
7792         case 2:
7793                 return enumports_level_2(buffer, offered, needed, returned);
7794         default:
7795                 return WERR_UNKNOWN_LEVEL;
7796         }
7797 }
7798
7799 /****************************************************************************
7800 ****************************************************************************/
7801
7802 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7803                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7804                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7805                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7806                                 POLICY_HND *handle)
7807 {
7808         NT_PRINTER_INFO_LEVEL *printer = NULL;
7809         fstring name;
7810         int     snum;
7811         WERROR err = WERR_OK;
7812
7813         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7814                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7815                 return WERR_NOMEM;
7816         }
7817
7818         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7819         if (!convert_printer_info(info, printer, 2)) {
7820                 free_a_printer(&printer, 2);
7821                 return WERR_NOMEM;
7822         }
7823
7824         /* check to see if the printer already exists */
7825
7826         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7827                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7828                         printer->info_2->sharename));
7829                 free_a_printer(&printer, 2);
7830                 return WERR_PRINTER_ALREADY_EXISTS;
7831         }
7832
7833         /* FIXME!!!  smbd should check to see if the driver is installed before
7834            trying to add a printer like this  --jerry */
7835
7836         if (*lp_addprinter_cmd() ) {
7837                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7838                                        printer) ) {
7839                         free_a_printer(&printer,2);
7840                         return WERR_ACCESS_DENIED;
7841                 }
7842         } else {
7843                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7844                         "smb.conf parameter \"addprinter command\" is defined. This"
7845                         "parameter must exist for this call to succeed\n",
7846                         printer->info_2->sharename ));
7847         }
7848
7849         /* use our primary netbios name since get_a_printer() will convert
7850            it to what the client expects on a case by case basis */
7851
7852         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7853              printer->info_2->sharename);
7854
7855
7856         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7857                 free_a_printer(&printer,2);
7858                 return WERR_ACCESS_DENIED;
7859         }
7860
7861         /* you must be a printer admin to add a new printer */
7862         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7863                 free_a_printer(&printer,2);
7864                 return WERR_ACCESS_DENIED;
7865         }
7866
7867         /*
7868          * Do sanity check on the requested changes for Samba.
7869          */
7870
7871         if (!check_printer_ok(printer->info_2, snum)) {
7872                 free_a_printer(&printer,2);
7873                 return WERR_INVALID_PARAM;
7874         }
7875
7876         /*
7877          * When a printer is created, the drivername bound to the printer is used
7878          * to lookup previously saved driver initialization info, which is then
7879          * bound to the new printer, simulating what happens in the Windows arch.
7880          */
7881
7882         if (!devmode)
7883         {
7884                 set_driver_init(printer, 2);
7885         }
7886         else
7887         {
7888                 /* A valid devmode was included, convert and link it
7889                 */
7890                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7891
7892                 if (!convert_devicemode(printer->info_2->printername, devmode,
7893                                 &printer->info_2->devmode))
7894                         return  WERR_NOMEM;
7895         }
7896
7897         /* write the ASCII on disk */
7898         err = mod_a_printer(printer, 2);
7899         if (!W_ERROR_IS_OK(err)) {
7900                 free_a_printer(&printer,2);
7901                 return err;
7902         }
7903
7904         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7905                 /* Handle open failed - remove addition. */
7906                 del_a_printer(printer->info_2->sharename);
7907                 free_a_printer(&printer,2);
7908                 return WERR_ACCESS_DENIED;
7909         }
7910
7911         update_c_setprinter(False);
7912         free_a_printer(&printer,2);
7913
7914         return WERR_OK;
7915 }
7916
7917 /****************************************************************************
7918 ****************************************************************************/
7919
7920 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7921 {
7922         UNISTR2 *uni_srv_name = q_u->server_name;
7923         uint32 level = q_u->level;
7924         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7925         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7926         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7927         uint32 user_switch = q_u->user_switch;
7928         SPOOL_USER_CTR *user = &q_u->user_ctr;
7929         POLICY_HND *handle = &r_u->handle;
7930
7931         switch (level) {
7932                 case 1:
7933                         /* we don't handle yet */
7934                         /* but I know what to do ... */
7935                         return WERR_UNKNOWN_LEVEL;
7936                 case 2:
7937                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7938                                                             devmode, sdb,
7939                                                             user_switch, user, handle);
7940                 default:
7941                         return WERR_UNKNOWN_LEVEL;
7942         }
7943 }
7944
7945 /****************************************************************************
7946 ****************************************************************************/
7947
7948 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7949 {
7950         uint32 level = q_u->level;
7951         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7952         WERROR err = WERR_OK;
7953         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7954         fstring driver_name;
7955         uint32 version;
7956
7957         ZERO_STRUCT(driver);
7958
7959         if (!convert_printer_driver_info(info, &driver, level)) {
7960                 err = WERR_NOMEM;
7961                 goto done;
7962         }
7963
7964         DEBUG(5,("Cleaning driver's information\n"));
7965         err = clean_up_driver_struct(p, driver, level);
7966         if (!W_ERROR_IS_OK(err))
7967                 goto done;
7968
7969         DEBUG(5,("Moving driver to final destination\n"));
7970         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7971                                                               &err)) ) {
7972                 goto done;
7973         }
7974
7975         if (add_a_printer_driver(driver, level)!=0) {
7976                 err = WERR_ACCESS_DENIED;
7977                 goto done;
7978         }
7979
7980         switch(level) {
7981         case 3:
7982                 fstrcpy(driver_name,
7983                         driver.info_3->name ? driver.info_3->name : "");
7984                 break;
7985         case 6:
7986                 fstrcpy(driver_name,
7987                         driver.info_6->name ?  driver.info_6->name : "");
7988                 break;
7989         }
7990
7991         /*
7992          * I think this is where he DrvUpgradePrinter() hook would be
7993          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7994          * server.  Right now, we just need to send ourselves a message
7995          * to update each printer bound to this driver.   --jerry
7996          */
7997
7998         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7999                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
8000                         driver_name));
8001         }
8002
8003         /*
8004          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
8005          * decide if the driver init data should be deleted. The rules are:
8006          *  1) never delete init data if it is a 9x driver, they don't use it anyway
8007          *  2) delete init data only if there is no 2k/Xp driver
8008          *  3) always delete init data
8009          * The generalized rule is always use init data from the highest order driver.
8010          * It is necessary to follow the driver install by an initialization step to
8011          * finish off this process.
8012         */
8013         if (level == 3)
8014                 version = driver.info_3->cversion;
8015         else if (level == 6)
8016                 version = driver.info_6->version;
8017         else
8018                 version = -1;
8019         switch (version) {
8020                 /*
8021                  * 9x printer driver - never delete init data
8022                 */
8023                 case 0:
8024                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
8025                                         driver_name));
8026                         break;
8027
8028                 /*
8029                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
8030                  * there is no 2k/Xp driver init data for this driver name.
8031                 */
8032                 case 2:
8033                 {
8034                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
8035
8036                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
8037                                 /*
8038                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8039                                 */
8040                                 if (!del_driver_init(driver_name))
8041                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
8042                         } else {
8043                                 /*
8044                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8045                                 */
8046                                 free_a_printer_driver(driver1,3);
8047                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
8048                                                 driver_name));
8049                         }
8050                 }
8051                 break;
8052
8053                 /*
8054                  * 2k or Xp printer driver - always delete init data
8055                 */
8056                 case 3:
8057                         if (!del_driver_init(driver_name))
8058                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
8059                         break;
8060
8061                 default:
8062                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
8063                         break;
8064         }
8065
8066
8067 done:
8068         free_a_printer_driver(driver, level);
8069         return err;
8070 }
8071
8072 /********************************************************************
8073  * spoolss_addprinterdriverex
8074  ********************************************************************/
8075
8076 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
8077 {
8078         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
8079         SPOOL_R_ADDPRINTERDRIVER r_u_local;
8080
8081         /*
8082          * we only support the semantics of AddPrinterDriver()
8083          * i.e. only copy files that are newer than existing ones
8084          */
8085
8086         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
8087                 return WERR_ACCESS_DENIED;
8088
8089         ZERO_STRUCT(q_u_local);
8090         ZERO_STRUCT(r_u_local);
8091
8092         /* just pass the information off to _spoolss_addprinterdriver() */
8093         q_u_local.server_name_ptr = q_u->server_name_ptr;
8094         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
8095         q_u_local.level = q_u->level;
8096         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
8097
8098         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
8099 }
8100
8101 /****************************************************************************
8102 ****************************************************************************/
8103
8104 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
8105 {
8106         init_unistr(&info->name, name);
8107 }
8108
8109 /****************************************************************************
8110 ****************************************************************************/
8111
8112 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8113 {
8114         char *path = NULL;
8115         char *long_archi = NULL;
8116         char *servername = NULL;
8117         const char *pservername = NULL;
8118         const char *short_archi;
8119         DRIVER_DIRECTORY_1 *info=NULL;
8120         WERROR result = WERR_OK;
8121         TALLOC_CTX *ctx = talloc_tos();
8122
8123         servername = unistr2_to_ascii_talloc(ctx, name);
8124         if (!servername) {
8125                 return WERR_NOMEM;
8126         }
8127         long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8128         if (!long_archi) {
8129                 return WERR_NOMEM;
8130         }
8131
8132         pservername = canon_servername(servername);
8133
8134         if ( !is_myname_or_ipaddr(pservername))
8135                 return WERR_INVALID_PARAM;
8136
8137         if (!(short_archi = get_short_archi(long_archi)))
8138                 return WERR_INVALID_ENVIRONMENT;
8139
8140         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8141                 return WERR_NOMEM;
8142
8143         path = talloc_asprintf(ctx,
8144                         "\\\\%s\\print$\\%s", pservername, short_archi);
8145         if (!path) {
8146                 result = WERR_NOMEM;
8147                 goto out;
8148         }
8149
8150         DEBUG(4,("printer driver directory: [%s]\n", path));
8151
8152         fill_driverdir_1(info, path);
8153
8154         *needed += spoolss_size_driverdir_info_1(info);
8155
8156         if (*needed > offered) {
8157                 result = WERR_INSUFFICIENT_BUFFER;
8158                 goto out;
8159         }
8160
8161         if (!rpcbuf_alloc_size(buffer, *needed)) {
8162                 result = WERR_NOMEM;
8163                 goto out;
8164         }
8165
8166         smb_io_driverdir_1("", buffer, info, 0);
8167
8168 out:
8169         SAFE_FREE(info);
8170
8171         return result;
8172 }
8173
8174 /****************************************************************************
8175 ****************************************************************************/
8176
8177 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8178 {
8179         UNISTR2 *name = &q_u->name;
8180         UNISTR2 *uni_environment = &q_u->environment;
8181         uint32 level = q_u->level;
8182         RPC_BUFFER *buffer = NULL;
8183         uint32 offered = q_u->offered;
8184         uint32 *needed = &r_u->needed;
8185
8186         /* that's an [in out] buffer */
8187
8188         if (!q_u->buffer && (offered!=0)) {
8189                 return WERR_INVALID_PARAM;
8190         }
8191
8192         rpcbuf_move(q_u->buffer, &r_u->buffer);
8193         buffer = r_u->buffer;
8194
8195         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8196
8197         *needed=0;
8198
8199         switch(level) {
8200         case 1:
8201                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8202         default:
8203                 return WERR_UNKNOWN_LEVEL;
8204         }
8205 }
8206
8207 /****************************************************************************
8208 ****************************************************************************/
8209
8210 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8211 {
8212         POLICY_HND *handle = &q_u->handle;
8213         uint32 idx               = q_u->index;
8214         uint32 in_value_len      = q_u->valuesize;
8215         uint32 in_data_len       = q_u->datasize;
8216         uint32 *out_max_value_len = &r_u->valuesize;
8217         uint16 **out_value       = &r_u->value;
8218         uint32 *out_value_len    = &r_u->realvaluesize;
8219         uint32 *out_type         = &r_u->type;
8220         uint32 *out_max_data_len = &r_u->datasize;
8221         uint8  **data_out        = &r_u->data;
8222         uint32 *out_data_len     = &r_u->realdatasize;
8223
8224         NT_PRINTER_INFO_LEVEL *printer = NULL;
8225
8226         uint32          biggest_valuesize;
8227         uint32          biggest_datasize;
8228         uint32          data_len;
8229         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8230         int             snum;
8231         WERROR          result;
8232         REGISTRY_VALUE  *val = NULL;
8233         NT_PRINTER_DATA *p_data;
8234         int             i, key_index, num_values;
8235         int             name_length;
8236
8237         *out_type = 0;
8238
8239         *out_max_data_len = 0;
8240         *data_out         = NULL;
8241         *out_data_len     = 0;
8242
8243         DEBUG(5,("spoolss_enumprinterdata\n"));
8244
8245         if (!Printer) {
8246                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8247                 return WERR_BADFID;
8248         }
8249
8250         if (!get_printer_snum(p,handle, &snum, NULL))
8251                 return WERR_BADFID;
8252
8253         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8254         if (!W_ERROR_IS_OK(result))
8255                 return result;
8256
8257         p_data = printer->info_2->data;
8258         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8259
8260         result = WERR_OK;
8261
8262         /*
8263          * The NT machine wants to know the biggest size of value and data
8264          *
8265          * cf: MSDN EnumPrinterData remark section
8266          */
8267
8268         if ( !in_value_len && !in_data_len && (key_index != -1) )
8269         {
8270                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8271
8272                 biggest_valuesize = 0;
8273                 biggest_datasize  = 0;
8274
8275                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8276
8277                 for ( i=0; i<num_values; i++ )
8278                 {
8279                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8280
8281                         name_length = strlen(val->valuename);
8282                         if ( strlen(val->valuename) > biggest_valuesize )
8283                                 biggest_valuesize = name_length;
8284
8285                         if ( val->size > biggest_datasize )
8286                                 biggest_datasize = val->size;
8287
8288                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8289                                 biggest_datasize));
8290                 }
8291
8292                 /* the value is an UNICODE string but real_value_size is the length
8293                    in bytes including the trailing 0 */
8294
8295                 *out_value_len = 2 * (1+biggest_valuesize);
8296                 *out_data_len  = biggest_datasize;
8297
8298                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8299
8300                 goto done;
8301         }
8302
8303         /*
8304          * the value len is wrong in NT sp3
8305          * that's the number of bytes not the number of unicode chars
8306          */
8307
8308         if ( key_index != -1 )
8309                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8310
8311         if ( !val )
8312         {
8313
8314                 /* out_value should default to "" or else NT4 has
8315                    problems unmarshalling the response */
8316
8317                 *out_max_value_len=(in_value_len/sizeof(uint16));
8318
8319                 if (in_value_len) {
8320                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8321                         {
8322                                 result = WERR_NOMEM;
8323                                 goto done;
8324                         }
8325                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8326                 } else {
8327                         *out_value=NULL;
8328                         *out_value_len = 0;
8329                 }
8330
8331                 /* the data is counted in bytes */
8332
8333                 *out_max_data_len = in_data_len;
8334                 *out_data_len     = in_data_len;
8335
8336                 /* only allocate when given a non-zero data_len */
8337
8338                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8339                 {
8340                         result = WERR_NOMEM;
8341                         goto done;
8342                 }
8343
8344                 result = WERR_NO_MORE_ITEMS;
8345         }
8346         else
8347         {
8348                 /*
8349                  * the value is:
8350                  * - counted in bytes in the request
8351                  * - counted in UNICODE chars in the max reply
8352                  * - counted in bytes in the real size
8353                  *
8354                  * take a pause *before* coding not *during* coding
8355                  */
8356
8357                 /* name */
8358                 *out_max_value_len=(in_value_len/sizeof(uint16));
8359                 if (in_value_len) {
8360                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8361                         {
8362                                 result = WERR_NOMEM;
8363                                 goto done;
8364                         }
8365
8366                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8367                 } else {
8368                         *out_value = NULL;
8369                         *out_value_len = 0;
8370                 }
8371
8372                 /* type */
8373
8374                 *out_type = regval_type( val );
8375
8376                 /* data - counted in bytes */
8377
8378                 *out_max_data_len = in_data_len;
8379                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8380                 {
8381                         result = WERR_NOMEM;
8382                         goto done;
8383                 }
8384                 data_len = regval_size(val);
8385                 if ( *data_out && data_len )
8386                         memcpy( *data_out, regval_data_p(val), data_len );
8387                 *out_data_len = data_len;
8388         }
8389
8390 done:
8391         free_a_printer(&printer, 2);
8392         return result;
8393 }
8394
8395 /****************************************************************************
8396 ****************************************************************************/
8397
8398 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8399 {
8400         POLICY_HND              *handle = &q_u->handle;
8401         UNISTR2                 *value = &q_u->value;
8402         uint32                  type = q_u->type;
8403         uint8                   *data = q_u->data;
8404         uint32                  real_len = q_u->real_len;
8405
8406         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8407         int                     snum=0;
8408         WERROR                  status = WERR_OK;
8409         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8410         fstring                 valuename;
8411
8412         DEBUG(5,("spoolss_setprinterdata\n"));
8413
8414         if (!Printer) {
8415                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8416                 return WERR_BADFID;
8417         }
8418
8419         if ( Printer->printer_type == SPLHND_SERVER ) {
8420                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8421                 return WERR_INVALID_PARAM;
8422         }
8423
8424         if (!get_printer_snum(p,handle, &snum, NULL))
8425                 return WERR_BADFID;
8426
8427         /*
8428          * Access check : NT returns "access denied" if you make a
8429          * SetPrinterData call without the necessary privildge.
8430          * we were originally returning OK if nothing changed
8431          * which made Win2k issue **a lot** of SetPrinterData
8432          * when connecting to a printer  --jerry
8433          */
8434
8435         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8436         {
8437                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8438                 status = WERR_ACCESS_DENIED;
8439                 goto done;
8440         }
8441
8442         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8443         if (!W_ERROR_IS_OK(status))
8444                 return status;
8445
8446         unistr2_to_ascii(valuename, value, sizeof(valuename));
8447
8448         /*
8449          * When client side code sets a magic printer data key, detect it and save
8450          * the current printer data and the magic key's data (its the DEVMODE) for
8451          * future printer/driver initializations.
8452          */
8453         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8454         {
8455                 /* Set devmode and printer initialization info */
8456                 status = save_driver_init( printer, 2, data, real_len );
8457
8458                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8459         }
8460         else
8461         {
8462         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8463                                         type, data, real_len );
8464                 if ( W_ERROR_IS_OK(status) )
8465                         status = mod_a_printer(printer, 2);
8466         }
8467
8468 done:
8469         free_a_printer(&printer, 2);
8470
8471         return status;
8472 }
8473
8474 /****************************************************************************
8475 ****************************************************************************/
8476
8477 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8478 {
8479         POLICY_HND      *handle = &q_u->handle;
8480         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8481         int             snum;
8482
8483         DEBUG(5,("_spoolss_resetprinter\n"));
8484
8485         /*
8486          * All we do is to check to see if the handle and queue is valid.
8487          * This call really doesn't mean anything to us because we only
8488          * support RAW printing.   --jerry
8489          */
8490
8491         if (!Printer) {
8492                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8493                 return WERR_BADFID;
8494         }
8495
8496         if (!get_printer_snum(p,handle, &snum, NULL))
8497                 return WERR_BADFID;
8498
8499
8500         /* blindly return success */
8501         return WERR_OK;
8502 }
8503
8504 /****************************************************************
8505  _spoolss_DeletePrinterData
8506 ****************************************************************/
8507
8508 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8509                                   struct spoolss_DeletePrinterData *r)
8510 {
8511         POLICY_HND      *handle = r->in.handle;
8512         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8513         int             snum=0;
8514         WERROR          status = WERR_OK;
8515         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8516
8517         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8518
8519         if (!Printer) {
8520                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8521                         OUR_HANDLE(handle)));
8522                 return WERR_BADFID;
8523         }
8524
8525         if (!get_printer_snum(p, handle, &snum, NULL))
8526                 return WERR_BADFID;
8527
8528         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8529                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8530                         "printer properties change denied by handle\n"));
8531                 return WERR_ACCESS_DENIED;
8532         }
8533
8534         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8535         if (!W_ERROR_IS_OK(status))
8536                 return status;
8537
8538         if (!r->in.value_name) {
8539                 free_a_printer(&printer, 2);
8540                 return WERR_NOMEM;
8541         }
8542
8543         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8544                                         r->in.value_name );
8545
8546         if ( W_ERROR_IS_OK(status) )
8547                 mod_a_printer( printer, 2 );
8548
8549         free_a_printer(&printer, 2);
8550
8551         return status;
8552 }
8553
8554 /****************************************************************
8555  _spoolss_AddForm
8556 ****************************************************************/
8557
8558 WERROR _spoolss_AddForm(pipes_struct *p,
8559                         struct spoolss_AddForm *r)
8560 {
8561         POLICY_HND *handle = r->in.handle;
8562         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8563         nt_forms_struct tmpForm;
8564         int snum;
8565         WERROR status = WERR_OK;
8566         NT_PRINTER_INFO_LEVEL *printer = NULL;
8567
8568         int count=0;
8569         nt_forms_struct *list=NULL;
8570         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8571
8572         DEBUG(5,("_spoolss_AddForm\n"));
8573
8574         if (!Printer) {
8575                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8576                         OUR_HANDLE(handle)));
8577                 return WERR_BADFID;
8578         }
8579
8580
8581         /* forms can be added on printer of on the print server handle */
8582
8583         if ( Printer->printer_type == SPLHND_PRINTER )
8584         {
8585                 if (!get_printer_snum(p,handle, &snum, NULL))
8586                         return WERR_BADFID;
8587
8588                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8589                 if (!W_ERROR_IS_OK(status))
8590                         goto done;
8591         }
8592
8593         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8594                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8595                 status = WERR_ACCESS_DENIED;
8596                 goto done;
8597         }
8598
8599         /* can't add if builtin */
8600
8601         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8602                 status = WERR_FILE_EXISTS;
8603                 goto done;
8604         }
8605
8606         count = get_ntforms(&list);
8607
8608         if(!add_a_form(&list, form, &count)) {
8609                 status =  WERR_NOMEM;
8610                 goto done;
8611         }
8612
8613         write_ntforms(&list, count);
8614
8615         /*
8616          * ChangeID must always be set if this is a printer
8617          */
8618
8619         if ( Printer->printer_type == SPLHND_PRINTER )
8620                 status = mod_a_printer(printer, 2);
8621
8622 done:
8623         if ( printer )
8624                 free_a_printer(&printer, 2);
8625         SAFE_FREE(list);
8626
8627         return status;
8628 }
8629
8630 /****************************************************************
8631  _spoolss_DeleteForm
8632 ****************************************************************/
8633
8634 WERROR _spoolss_DeleteForm(pipes_struct *p,
8635                            struct spoolss_DeleteForm *r)
8636 {
8637         POLICY_HND *handle = r->in.handle;
8638         const char *form_name = r->in.form_name;
8639         nt_forms_struct tmpForm;
8640         int count=0;
8641         nt_forms_struct *list=NULL;
8642         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8643         int snum;
8644         WERROR status = WERR_OK;
8645         NT_PRINTER_INFO_LEVEL *printer = NULL;
8646
8647         DEBUG(5,("_spoolss_DeleteForm\n"));
8648
8649         if (!Printer) {
8650                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8651                         OUR_HANDLE(handle)));
8652                 return WERR_BADFID;
8653         }
8654
8655         /* forms can be deleted on printer of on the print server handle */
8656
8657         if ( Printer->printer_type == SPLHND_PRINTER )
8658         {
8659                 if (!get_printer_snum(p,handle, &snum, NULL))
8660                         return WERR_BADFID;
8661
8662                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8663                 if (!W_ERROR_IS_OK(status))
8664                         goto done;
8665         }
8666
8667         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8668                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8669                 status = WERR_ACCESS_DENIED;
8670                 goto done;
8671         }
8672
8673         /* can't delete if builtin */
8674
8675         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8676                 status = WERR_INVALID_PARAM;
8677                 goto done;
8678         }
8679
8680         count = get_ntforms(&list);
8681
8682         if ( !delete_a_form(&list, form_name, &count, &status ))
8683                 goto done;
8684
8685         /*
8686          * ChangeID must always be set if this is a printer
8687          */
8688
8689         if ( Printer->printer_type == SPLHND_PRINTER )
8690                 status = mod_a_printer(printer, 2);
8691
8692 done:
8693         if ( printer )
8694                 free_a_printer(&printer, 2);
8695         SAFE_FREE(list);
8696
8697         return status;
8698 }
8699
8700 /****************************************************************
8701  _spoolss_SetForm
8702 ****************************************************************/
8703
8704 WERROR _spoolss_SetForm(pipes_struct *p,
8705                         struct spoolss_SetForm *r)
8706 {
8707         POLICY_HND *handle = r->in.handle;
8708         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8709         nt_forms_struct tmpForm;
8710         int snum;
8711         WERROR status = WERR_OK;
8712         NT_PRINTER_INFO_LEVEL *printer = NULL;
8713
8714         int count=0;
8715         nt_forms_struct *list=NULL;
8716         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8717
8718         DEBUG(5,("_spoolss_SetForm\n"));
8719
8720         if (!Printer) {
8721                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8722                         OUR_HANDLE(handle)));
8723                 return WERR_BADFID;
8724         }
8725
8726         /* forms can be modified on printer of on the print server handle */
8727
8728         if ( Printer->printer_type == SPLHND_PRINTER )
8729         {
8730                 if (!get_printer_snum(p,handle, &snum, NULL))
8731                         return WERR_BADFID;
8732
8733                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8734                 if (!W_ERROR_IS_OK(status))
8735                         goto done;
8736         }
8737
8738         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8739                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8740                 status = WERR_ACCESS_DENIED;
8741                 goto done;
8742         }
8743
8744         /* can't set if builtin */
8745         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8746                 status = WERR_INVALID_PARAM;
8747                 goto done;
8748         }
8749
8750         count = get_ntforms(&list);
8751         update_a_form(&list, form, count);
8752         write_ntforms(&list, count);
8753
8754         /*
8755          * ChangeID must always be set if this is a printer
8756          */
8757
8758         if ( Printer->printer_type == SPLHND_PRINTER )
8759                 status = mod_a_printer(printer, 2);
8760
8761
8762 done:
8763         if ( printer )
8764                 free_a_printer(&printer, 2);
8765         SAFE_FREE(list);
8766
8767         return status;
8768 }
8769
8770 /****************************************************************************
8771  enumprintprocessors level 1.
8772 ****************************************************************************/
8773
8774 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8775 {
8776         PRINTPROCESSOR_1 *info_1=NULL;
8777         WERROR result = WERR_OK;
8778
8779         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8780                 return WERR_NOMEM;
8781
8782         (*returned) = 0x1;
8783
8784         init_unistr(&info_1->name, "winprint");
8785
8786         *needed += spoolss_size_printprocessor_info_1(info_1);
8787
8788         if (*needed > offered) {
8789                 result = WERR_INSUFFICIENT_BUFFER;
8790                 goto out;
8791         }
8792
8793         if (!rpcbuf_alloc_size(buffer, *needed)) {
8794                 result = WERR_NOMEM;
8795                 goto out;
8796         }
8797
8798         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8799
8800 out:
8801         SAFE_FREE(info_1);
8802
8803         if ( !W_ERROR_IS_OK(result) )
8804                 *returned = 0;
8805
8806         return result;
8807 }
8808
8809 /****************************************************************************
8810 ****************************************************************************/
8811
8812 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8813 {
8814         uint32 level = q_u->level;
8815         RPC_BUFFER *buffer = NULL;
8816         uint32 offered = q_u->offered;
8817         uint32 *needed = &r_u->needed;
8818         uint32 *returned = &r_u->returned;
8819
8820         /* that's an [in out] buffer */
8821
8822         if (!q_u->buffer && (offered!=0)) {
8823                 return WERR_INVALID_PARAM;
8824         }
8825
8826         rpcbuf_move(q_u->buffer, &r_u->buffer);
8827         buffer = r_u->buffer;
8828
8829         DEBUG(5,("spoolss_enumprintprocessors\n"));
8830
8831         /*
8832          * Enumerate the print processors ...
8833          *
8834          * Just reply with "winprint", to keep NT happy
8835          * and I can use my nice printer checker.
8836          */
8837
8838         *returned=0;
8839         *needed=0;
8840
8841         switch (level) {
8842         case 1:
8843                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8844         default:
8845                 return WERR_UNKNOWN_LEVEL;
8846         }
8847 }
8848
8849 /****************************************************************************
8850  enumprintprocdatatypes level 1.
8851 ****************************************************************************/
8852
8853 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8854 {
8855         PRINTPROCDATATYPE_1 *info_1=NULL;
8856         WERROR result = WERR_OK;
8857
8858         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8859                 return WERR_NOMEM;
8860
8861         (*returned) = 0x1;
8862
8863         init_unistr(&info_1->name, "RAW");
8864
8865         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8866
8867         if (*needed > offered) {
8868                 result = WERR_INSUFFICIENT_BUFFER;
8869                 goto out;
8870         }
8871
8872         if (!rpcbuf_alloc_size(buffer, *needed)) {
8873                 result = WERR_NOMEM;
8874                 goto out;
8875         }
8876
8877         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8878
8879 out:
8880         SAFE_FREE(info_1);
8881
8882         if ( !W_ERROR_IS_OK(result) )
8883                 *returned = 0;
8884
8885         return result;
8886 }
8887
8888 /****************************************************************************
8889 ****************************************************************************/
8890
8891 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8892 {
8893         uint32 level = q_u->level;
8894         RPC_BUFFER *buffer = NULL;
8895         uint32 offered = q_u->offered;
8896         uint32 *needed = &r_u->needed;
8897         uint32 *returned = &r_u->returned;
8898
8899         /* that's an [in out] buffer */
8900
8901         if (!q_u->buffer && (offered!=0)) {
8902                 return WERR_INVALID_PARAM;
8903         }
8904
8905         rpcbuf_move(q_u->buffer, &r_u->buffer);
8906         buffer = r_u->buffer;
8907
8908         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8909
8910         *returned=0;
8911         *needed=0;
8912
8913         switch (level) {
8914         case 1:
8915                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8916         default:
8917                 return WERR_UNKNOWN_LEVEL;
8918         }
8919 }
8920
8921 /****************************************************************************
8922  enumprintmonitors level 1.
8923 ****************************************************************************/
8924
8925 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8926 {
8927         PRINTMONITOR_1 *info_1;
8928         WERROR result = WERR_OK;
8929         int i;
8930
8931         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8932                 return WERR_NOMEM;
8933
8934         *returned = 2;
8935
8936         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8937         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8938
8939         for ( i=0; i<*returned; i++ ) {
8940                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8941         }
8942
8943         if (*needed > offered) {
8944                 result = WERR_INSUFFICIENT_BUFFER;
8945                 goto out;
8946         }
8947
8948         if (!rpcbuf_alloc_size(buffer, *needed)) {
8949                 result = WERR_NOMEM;
8950                 goto out;
8951         }
8952
8953         for ( i=0; i<*returned; i++ ) {
8954                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8955         }
8956
8957 out:
8958         SAFE_FREE(info_1);
8959
8960         if ( !W_ERROR_IS_OK(result) )
8961                 *returned = 0;
8962
8963         return result;
8964 }
8965
8966 /****************************************************************************
8967  enumprintmonitors level 2.
8968 ****************************************************************************/
8969
8970 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8971 {
8972         PRINTMONITOR_2 *info_2;
8973         WERROR result = WERR_OK;
8974         int i;
8975
8976         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8977                 return WERR_NOMEM;
8978
8979         *returned = 2;
8980
8981         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8982         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8983         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8984
8985         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8986         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8987         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8988
8989         for ( i=0; i<*returned; i++ ) {
8990                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8991         }
8992
8993         if (*needed > offered) {
8994                 result = WERR_INSUFFICIENT_BUFFER;
8995                 goto out;
8996         }
8997
8998         if (!rpcbuf_alloc_size(buffer, *needed)) {
8999                 result = WERR_NOMEM;
9000                 goto out;
9001         }
9002
9003         for ( i=0; i<*returned; i++ ) {
9004                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
9005         }
9006
9007 out:
9008         SAFE_FREE(info_2);
9009
9010         if ( !W_ERROR_IS_OK(result) )
9011                 *returned = 0;
9012
9013         return result;
9014 }
9015
9016 /****************************************************************************
9017 ****************************************************************************/
9018
9019 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
9020 {
9021         uint32 level = q_u->level;
9022         RPC_BUFFER *buffer = NULL;
9023         uint32 offered = q_u->offered;
9024         uint32 *needed = &r_u->needed;
9025         uint32 *returned = &r_u->returned;
9026
9027         /* that's an [in out] buffer */
9028
9029         if (!q_u->buffer && (offered!=0)) {
9030                 return WERR_INVALID_PARAM;
9031         }
9032
9033         rpcbuf_move(q_u->buffer, &r_u->buffer);
9034         buffer = r_u->buffer;
9035
9036         DEBUG(5,("spoolss_enumprintmonitors\n"));
9037
9038         /*
9039          * Enumerate the print monitors ...
9040          *
9041          * Just reply with "Local Port", to keep NT happy
9042          * and I can use my nice printer checker.
9043          */
9044
9045         *returned=0;
9046         *needed=0;
9047
9048         switch (level) {
9049         case 1:
9050                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9051         case 2:
9052                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9053         default:
9054                 return WERR_UNKNOWN_LEVEL;
9055         }
9056 }
9057
9058 /****************************************************************************
9059 ****************************************************************************/
9060
9061 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9062                              NT_PRINTER_INFO_LEVEL *ntprinter,
9063                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9064                              uint32 *needed)
9065 {
9066         int i=0;
9067         bool found=False;
9068         JOB_INFO_1 *info_1=NULL;
9069         WERROR result = WERR_OK;
9070
9071         info_1=SMB_MALLOC_P(JOB_INFO_1);
9072
9073         if (info_1 == NULL) {
9074                 return WERR_NOMEM;
9075         }
9076
9077         for (i=0; i<count && found==False; i++) {
9078                 if ((*queue)[i].job==(int)jobid)
9079                         found=True;
9080         }
9081
9082         if (found==False) {
9083                 SAFE_FREE(info_1);
9084                 /* NT treats not found as bad param... yet another bad choice */
9085                 return WERR_INVALID_PARAM;
9086         }
9087
9088         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9089
9090         *needed += spoolss_size_job_info_1(info_1);
9091
9092         if (*needed > offered) {
9093                 result = WERR_INSUFFICIENT_BUFFER;
9094                 goto out;
9095         }
9096
9097         if (!rpcbuf_alloc_size(buffer, *needed)) {
9098                 result = WERR_NOMEM;
9099                 goto out;
9100         }
9101
9102         smb_io_job_info_1("", buffer, info_1, 0);
9103
9104 out:
9105         SAFE_FREE(info_1);
9106
9107         return result;
9108 }
9109
9110 /****************************************************************************
9111 ****************************************************************************/
9112
9113 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9114                              NT_PRINTER_INFO_LEVEL *ntprinter,
9115                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9116                              uint32 *needed)
9117 {
9118         int             i = 0;
9119         bool            found = False;
9120         JOB_INFO_2      *info_2;
9121         WERROR          result;
9122         DEVICEMODE      *devmode = NULL;
9123         NT_DEVICEMODE   *nt_devmode = NULL;
9124
9125         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9126                 return WERR_NOMEM;
9127
9128         ZERO_STRUCTP(info_2);
9129
9130         for ( i=0; i<count && found==False; i++ )
9131         {
9132                 if ((*queue)[i].job == (int)jobid)
9133                         found = True;
9134         }
9135
9136         if ( !found ) {
9137                 /* NT treats not found as bad param... yet another bad
9138                    choice */
9139                 result = WERR_INVALID_PARAM;
9140                 goto done;
9141         }
9142
9143         /*
9144          * if the print job does not have a DEVMODE associated with it,
9145          * just use the one for the printer. A NULL devicemode is not
9146          *  a failure condition
9147          */
9148
9149         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9150                 devmode = construct_dev_mode(lp_const_servicename(snum));
9151         else {
9152                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9153                         ZERO_STRUCTP( devmode );
9154                         convert_nt_devicemode( devmode, nt_devmode );
9155                 }
9156         }
9157
9158         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9159
9160         *needed += spoolss_size_job_info_2(info_2);
9161
9162         if (*needed > offered) {
9163                 result = WERR_INSUFFICIENT_BUFFER;
9164                 goto done;
9165         }
9166
9167         if (!rpcbuf_alloc_size(buffer, *needed)) {
9168                 result = WERR_NOMEM;
9169                 goto done;
9170         }
9171
9172         smb_io_job_info_2("", buffer, info_2, 0);
9173
9174         result = WERR_OK;
9175
9176  done:
9177         /* Cleanup allocated memory */
9178
9179         free_job_info_2(info_2);        /* Also frees devmode */
9180         SAFE_FREE(info_2);
9181
9182         return result;
9183 }
9184
9185 /****************************************************************************
9186 ****************************************************************************/
9187
9188 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9189 {
9190         POLICY_HND *handle = &q_u->handle;
9191         uint32 jobid = q_u->jobid;
9192         uint32 level = q_u->level;
9193         RPC_BUFFER *buffer = NULL;
9194         uint32 offered = q_u->offered;
9195         uint32 *needed = &r_u->needed;
9196         WERROR          wstatus = WERR_OK;
9197         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9198         int snum;
9199         int count;
9200         print_queue_struct      *queue = NULL;
9201         print_status_struct prt_status;
9202
9203         /* that's an [in out] buffer */
9204
9205         if (!q_u->buffer && (offered!=0)) {
9206                 return WERR_INVALID_PARAM;
9207         }
9208
9209         rpcbuf_move(q_u->buffer, &r_u->buffer);
9210         buffer = r_u->buffer;
9211
9212         DEBUG(5,("spoolss_getjob\n"));
9213
9214         *needed = 0;
9215
9216         if (!get_printer_snum(p, handle, &snum, NULL))
9217                 return WERR_BADFID;
9218
9219         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9220         if ( !W_ERROR_IS_OK(wstatus) )
9221                 return wstatus;
9222
9223         count = print_queue_status(snum, &queue, &prt_status);
9224
9225         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9226                      count, prt_status.status, prt_status.message));
9227
9228         switch ( level ) {
9229         case 1:
9230                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9231                                 buffer, offered, needed);
9232                         break;
9233         case 2:
9234                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9235                                 buffer, offered, needed);
9236                         break;
9237         default:
9238                         wstatus = WERR_UNKNOWN_LEVEL;
9239                         break;
9240         }
9241
9242         SAFE_FREE(queue);
9243         free_a_printer( &ntprinter, 2 );
9244
9245         return wstatus;
9246 }
9247
9248 /********************************************************************
9249  spoolss_getprinterdataex
9250
9251  From MSDN documentation of GetPrinterDataEx: pass request
9252  to GetPrinterData if key is "PrinterDriverData".
9253  ********************************************************************/
9254
9255 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9256 {
9257         POLICY_HND      *handle = &q_u->handle;
9258         uint32          in_size = q_u->size;
9259         uint32          *type = &r_u->type;
9260         uint32          *out_size = &r_u->size;
9261         uint8           **data = &r_u->data;
9262         uint32          *needed = &r_u->needed;
9263         fstring         keyname, valuename;
9264
9265         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9266
9267         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9268         int                     snum = 0;
9269         WERROR                  status = WERR_OK;
9270
9271         DEBUG(4,("_spoolss_getprinterdataex\n"));
9272
9273         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9274         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9275
9276         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9277                 keyname, valuename));
9278
9279         /* in case of problem, return some default values */
9280
9281         *needed   = 0;
9282         *type     = 0;
9283         *out_size = in_size;
9284
9285         if (!Printer) {
9286                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9287                 status = WERR_BADFID;
9288                 goto done;
9289         }
9290
9291         /* Is the handle to a printer or to the server? */
9292
9293         if (Printer->printer_type == SPLHND_SERVER) {
9294                 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9295                 status = WERR_INVALID_PARAM;
9296                 goto done;
9297         }
9298
9299         if ( !get_printer_snum(p,handle, &snum, NULL) )
9300                 return WERR_BADFID;
9301
9302         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9303         if ( !W_ERROR_IS_OK(status) )
9304                 goto done;
9305
9306         /* check to see if the keyname is valid */
9307         if ( !strlen(keyname) ) {
9308                 status = WERR_INVALID_PARAM;
9309                 goto done;
9310         }
9311
9312         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9313                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9314                 free_a_printer( &printer, 2 );
9315                 status = WERR_BADFILE;
9316                 goto done;
9317         }
9318
9319         /* When given a new keyname, we should just create it */
9320
9321         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9322
9323         if (*needed > *out_size)
9324                 status = WERR_MORE_DATA;
9325
9326 done:
9327         if ( !W_ERROR_IS_OK(status) )
9328         {
9329                 DEBUG(5, ("error: allocating %d\n", *out_size));
9330
9331                 /* reply this param doesn't exist */
9332
9333                 if ( *out_size )
9334                 {
9335                         if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9336                                 status = WERR_NOMEM;
9337                                 goto done;
9338                         }
9339                 } else {
9340                         *data = NULL;
9341                 }
9342         }
9343
9344         if ( printer )
9345         free_a_printer( &printer, 2 );
9346
9347         return status;
9348 }
9349
9350 /********************************************************************
9351  * spoolss_setprinterdataex
9352  ********************************************************************/
9353
9354 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9355 {
9356         POLICY_HND              *handle = &q_u->handle;
9357         uint32                  type = q_u->type;
9358         uint8                   *data = q_u->data;
9359         uint32                  real_len = q_u->real_len;
9360
9361         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9362         int                     snum = 0;
9363         WERROR                  status = WERR_OK;
9364         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9365         fstring                 valuename;
9366         fstring                 keyname;
9367         char                    *oid_string;
9368
9369         DEBUG(4,("_spoolss_setprinterdataex\n"));
9370
9371         /* From MSDN documentation of SetPrinterDataEx: pass request to
9372            SetPrinterData if key is "PrinterDriverData" */
9373
9374         if (!Printer) {
9375                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9376                 return WERR_BADFID;
9377         }
9378
9379         if ( Printer->printer_type == SPLHND_SERVER ) {
9380                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9381                 return WERR_INVALID_PARAM;
9382         }
9383
9384         if ( !get_printer_snum(p,handle, &snum, NULL) )
9385                 return WERR_BADFID;
9386
9387         /*
9388          * Access check : NT returns "access denied" if you make a
9389          * SetPrinterData call without the necessary privildge.
9390          * we were originally returning OK if nothing changed
9391          * which made Win2k issue **a lot** of SetPrinterData
9392          * when connecting to a printer  --jerry
9393          */
9394
9395         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9396         {
9397                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9398                 return WERR_ACCESS_DENIED;
9399         }
9400
9401         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9402         if (!W_ERROR_IS_OK(status))
9403                 return status;
9404
9405         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9406         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9407
9408         /* check for OID in valuename */
9409
9410         if ( (oid_string = strchr( valuename, ',' )) != NULL )
9411         {
9412                 *oid_string = '\0';
9413                 oid_string++;
9414         }
9415
9416         /* save the registry data */
9417
9418         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9419
9420         if ( W_ERROR_IS_OK(status) )
9421         {
9422                 /* save the OID if one was specified */
9423                 if ( oid_string ) {
9424                         fstrcat( keyname, "\\" );
9425                         fstrcat( keyname, SPOOL_OID_KEY );
9426
9427                         /*
9428                          * I'm not checking the status here on purpose.  Don't know
9429                          * if this is right, but I'm returning the status from the
9430                          * previous set_printer_dataex() call.  I have no idea if
9431                          * this is right.    --jerry
9432                          */
9433
9434                         set_printer_dataex( printer, keyname, valuename,
9435                                             REG_SZ, (uint8 *)oid_string,
9436                                             strlen(oid_string)+1 );
9437                 }
9438
9439                 status = mod_a_printer(printer, 2);
9440         }
9441
9442         free_a_printer(&printer, 2);
9443
9444         return status;
9445 }
9446
9447 /****************************************************************
9448  _spoolss_DeletePrinterDataEx
9449 ****************************************************************/
9450
9451 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9452                                     struct spoolss_DeletePrinterDataEx *r)
9453 {
9454         POLICY_HND      *handle = r->in.handle;
9455         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9456         int             snum=0;
9457         WERROR          status = WERR_OK;
9458         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9459
9460         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9461
9462         if (!Printer) {
9463                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9464                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9465                 return WERR_BADFID;
9466         }
9467
9468         if (!get_printer_snum(p, handle, &snum, NULL))
9469                 return WERR_BADFID;
9470
9471         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9472                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9473                         "printer properties change denied by handle\n"));
9474                 return WERR_ACCESS_DENIED;
9475         }
9476
9477         if (!r->in.value_name || !r->in.key_name) {
9478                 return WERR_NOMEM;
9479         }
9480
9481         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9482         if (!W_ERROR_IS_OK(status))
9483                 return status;
9484
9485         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9486
9487         if ( W_ERROR_IS_OK(status) )
9488                 mod_a_printer( printer, 2 );
9489
9490         free_a_printer(&printer, 2);
9491
9492         return status;
9493 }
9494
9495 /********************************************************************
9496  * spoolss_enumprinterkey
9497  ********************************************************************/
9498
9499
9500 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9501 {
9502         fstring         key;
9503         fstring         *keynames = NULL;
9504         uint16          *enumkeys = NULL;
9505         int             num_keys;
9506         int             printerkey_len;
9507         POLICY_HND      *handle = &q_u->handle;
9508         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9509         NT_PRINTER_DATA *data;
9510         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9511         int             snum = 0;
9512         WERROR          status = WERR_BADFILE;
9513
9514
9515         DEBUG(4,("_spoolss_enumprinterkey\n"));
9516
9517         if (!Printer) {
9518                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9519                 return WERR_BADFID;
9520         }
9521
9522         if ( !get_printer_snum(p,handle, &snum, NULL) )
9523                 return WERR_BADFID;
9524
9525         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9526         if (!W_ERROR_IS_OK(status))
9527                 return status;
9528
9529         /* get the list of subkey names */
9530
9531         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9532         data = printer->info_2->data;
9533
9534         num_keys = get_printer_subkeys( data, key, &keynames );
9535
9536         if ( num_keys == -1 ) {
9537                 status = WERR_BADFILE;
9538                 goto done;
9539         }
9540
9541         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9542
9543         r_u->needed = printerkey_len*2;
9544
9545         if ( q_u->size < r_u->needed ) {
9546                 status = WERR_MORE_DATA;
9547                 goto done;
9548         }
9549
9550         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9551                 status = WERR_NOMEM;
9552                 goto done;
9553         }
9554
9555         status = WERR_OK;
9556
9557         if ( q_u->size < r_u->needed )
9558                 status = WERR_MORE_DATA;
9559
9560 done:
9561         free_a_printer( &printer, 2 );
9562         SAFE_FREE( keynames );
9563
9564         return status;
9565 }
9566
9567 /****************************************************************
9568  _spoolss_DeletePrinterKey
9569 ****************************************************************/
9570
9571 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9572                                  struct spoolss_DeletePrinterKey *r)
9573 {
9574         POLICY_HND              *handle = r->in.handle;
9575         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9576         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9577         int                     snum=0;
9578         WERROR                  status;
9579
9580         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9581
9582         if (!Printer) {
9583                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9584                         OUR_HANDLE(handle)));
9585                 return WERR_BADFID;
9586         }
9587
9588         /* if keyname == NULL, return error */
9589
9590         if ( !r->in.key_name )
9591                 return WERR_INVALID_PARAM;
9592
9593         if (!get_printer_snum(p, handle, &snum, NULL))
9594                 return WERR_BADFID;
9595
9596         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9597                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9598                         "printer properties change denied by handle\n"));
9599                 return WERR_ACCESS_DENIED;
9600         }
9601
9602         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9603         if (!W_ERROR_IS_OK(status))
9604                 return status;
9605
9606         /* delete the key and all subneys */
9607
9608         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9609
9610         if ( W_ERROR_IS_OK(status) )
9611                 status = mod_a_printer(printer, 2);
9612
9613         free_a_printer( &printer, 2 );
9614
9615         return status;
9616 }
9617
9618
9619 /********************************************************************
9620  * spoolss_enumprinterdataex
9621  ********************************************************************/
9622
9623 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9624 {
9625         POLICY_HND      *handle = &q_u->handle;
9626         uint32          in_size = q_u->size;
9627         uint32          num_entries,
9628                         needed;
9629         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9630         PRINTER_ENUM_VALUES     *enum_values = NULL;
9631         NT_PRINTER_DATA         *p_data;
9632         fstring         key;
9633         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9634         int             snum;
9635         WERROR          result;
9636         int             key_index;
9637         int             i;
9638         REGISTRY_VALUE  *val;
9639         char            *value_name;
9640         uint32          data_len;
9641
9642
9643         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9644
9645         if (!Printer) {
9646                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9647                 return WERR_BADFID;
9648         }
9649
9650         /*
9651          * first check for a keyname of NULL or "".  Win2k seems to send
9652          * this a lot and we should send back WERR_INVALID_PARAM
9653          * no need to spend time looking up the printer in this case.
9654          * --jerry
9655          */
9656
9657         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9658         if ( !strlen(key) ) {
9659                 result = WERR_INVALID_PARAM;
9660                 goto done;
9661         }
9662
9663         /* get the printer off of disk */
9664
9665         if (!get_printer_snum(p,handle, &snum, NULL))
9666                 return WERR_BADFID;
9667
9668         ZERO_STRUCT(printer);
9669         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9670         if (!W_ERROR_IS_OK(result))
9671                 return result;
9672
9673         /* now look for a match on the key name */
9674
9675         p_data = printer->info_2->data;
9676
9677         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9678         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9679         {
9680                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9681                 result = WERR_INVALID_PARAM;
9682                 goto done;
9683         }
9684
9685         result = WERR_OK;
9686         needed = 0;
9687
9688         /* allocate the memory for the array of pointers -- if necessary */
9689
9690         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9691         if ( num_entries )
9692         {
9693                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9694                 {
9695                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9696                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9697                         result = WERR_NOMEM;
9698                         goto done;
9699                 }
9700
9701                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9702         }
9703
9704         /*
9705          * loop through all params and build the array to pass
9706          * back to the  client
9707          */
9708
9709         for ( i=0; i<num_entries; i++ )
9710         {
9711                 /* lookup the registry value */
9712
9713                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9714                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9715
9716                 /* copy the data */
9717
9718                 value_name = regval_name( val );
9719                 init_unistr( &enum_values[i].valuename, value_name );
9720                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9721                 enum_values[i].type      = regval_type( val );
9722
9723                 data_len = regval_size( val );
9724                 if ( data_len ) {
9725                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9726                         {
9727                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9728                                         data_len ));
9729                                 result = WERR_NOMEM;
9730                                 goto done;
9731                         }
9732                 }
9733                 enum_values[i].data_len = data_len;
9734
9735                 /* keep track of the size of the array in bytes */
9736
9737                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9738         }
9739
9740         /* housekeeping information in the reply */
9741
9742         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9743          * the hand marshalled container size is a multiple
9744          * of 4 bytes for RPC alignment.
9745          */
9746
9747         if (needed % 4) {
9748                 needed += 4-(needed % 4);
9749         }
9750
9751         r_u->needed     = needed;
9752         r_u->returned   = num_entries;
9753
9754         if (needed > in_size) {
9755                 result = WERR_MORE_DATA;
9756                 goto done;
9757         }
9758
9759         /* copy data into the reply */
9760
9761         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9762            response buffer size is != the offered buffer size
9763
9764                 r_u->ctr.size           = r_u->needed;
9765         */
9766         r_u->ctr.size           = in_size;
9767
9768         r_u->ctr.size_of_array  = r_u->returned;
9769         r_u->ctr.values         = enum_values;
9770
9771 done:
9772         if ( printer )
9773         free_a_printer(&printer, 2);
9774
9775         return result;
9776 }
9777
9778 /****************************************************************************
9779 ****************************************************************************/
9780
9781 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9782 {
9783         init_unistr(&info->name, name);
9784 }
9785
9786 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9787                                                  UNISTR2 *environment,
9788                                                  RPC_BUFFER *buffer,
9789                                                  uint32 offered,
9790                                                  uint32 *needed)
9791 {
9792         char *long_archi = NULL;
9793         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9794         WERROR result = WERR_OK;
9795         TALLOC_CTX *ctx = talloc_tos();
9796
9797         long_archi = unistr2_to_ascii_talloc(ctx, environment);
9798         if (!long_archi) {
9799                 return WERR_NOMEM;
9800         }
9801
9802         if (!get_short_archi(long_archi))
9803                 return WERR_INVALID_ENVIRONMENT;
9804
9805         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9806                 return WERR_NOMEM;
9807
9808         fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9809
9810         *needed += spoolss_size_printprocessordirectory_info_1(info);
9811
9812         if (*needed > offered) {
9813                 result = WERR_INSUFFICIENT_BUFFER;
9814                 goto out;
9815         }
9816
9817         if (!rpcbuf_alloc_size(buffer, *needed)) {
9818                 result = WERR_INSUFFICIENT_BUFFER;
9819                 goto out;
9820         }
9821
9822         smb_io_printprocessordirectory_1("", buffer, info, 0);
9823
9824 out:
9825         SAFE_FREE(info);
9826
9827         return result;
9828 }
9829
9830 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9831 {
9832         uint32 level = q_u->level;
9833         RPC_BUFFER *buffer = NULL;
9834         uint32 offered = q_u->offered;
9835         uint32 *needed = &r_u->needed;
9836         WERROR result;
9837
9838         /* that's an [in out] buffer */
9839
9840         if (!q_u->buffer && (offered!=0)) {
9841                 return WERR_INVALID_PARAM;
9842         }
9843
9844         rpcbuf_move(q_u->buffer, &r_u->buffer);
9845         buffer = r_u->buffer;
9846
9847         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9848
9849         *needed=0;
9850
9851         switch(level) {
9852         case 1:
9853                 result = getprintprocessordirectory_level_1
9854                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9855                 break;
9856         default:
9857                 result = WERR_UNKNOWN_LEVEL;
9858         }
9859
9860         return result;
9861 }
9862
9863 /*******************************************************************
9864  Streams the monitor UI DLL name in UNICODE
9865 *******************************************************************/
9866
9867 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9868                                 RPC_BUFFER *out, uint32 *needed )
9869 {
9870         const char *dllname = "tcpmonui.dll";
9871
9872         *needed = (strlen(dllname)+1) * 2;
9873
9874         if ( rpcbuf_get_size(out) < *needed ) {
9875                 return WERR_INSUFFICIENT_BUFFER;
9876         }
9877
9878         if ( !make_monitorui_buf( out, dllname ) ) {
9879                 return WERR_NOMEM;
9880         }
9881
9882         return WERR_OK;
9883 }
9884
9885 /*******************************************************************
9886  Create a new TCP/IP port
9887 *******************************************************************/
9888
9889 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9890                               RPC_BUFFER *out, uint32 *needed )
9891 {
9892         NT_PORT_DATA_1 port1;
9893         TALLOC_CTX *ctx = talloc_tos();
9894         char *device_uri = NULL;
9895
9896         ZERO_STRUCT( port1 );
9897
9898         /* convert to our internal port data structure */
9899
9900         if ( !convert_port_data_1( &port1, in ) ) {
9901                 return WERR_NOMEM;
9902         }
9903
9904         /* create the device URI and call the add_port_hook() */
9905
9906         switch ( port1.protocol ) {
9907         case PORT_PROTOCOL_DIRECT:
9908                 device_uri = talloc_asprintf(ctx,
9909                                 "socket://%s:%d/", port1.hostaddr, port1.port );
9910                 break;
9911
9912         case PORT_PROTOCOL_LPR:
9913                 device_uri = talloc_asprintf(ctx,
9914                         "lpr://%s/%s", port1.hostaddr, port1.queue );
9915                 break;
9916
9917         default:
9918                 return WERR_UNKNOWN_PORT;
9919         }
9920
9921         if (!device_uri) {
9922                 return WERR_NOMEM;
9923         }
9924
9925         return add_port_hook(ctx, token, port1.name, device_uri );
9926 }
9927
9928 /*******************************************************************
9929 *******************************************************************/
9930
9931 struct xcv_api_table xcvtcp_cmds[] = {
9932         { "MonitorUI",  xcvtcp_monitorui },
9933         { "AddPort",    xcvtcp_addport},
9934         { NULL,         NULL }
9935 };
9936
9937 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9938                                       RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9939                                       uint32 *needed )
9940 {
9941         int i;
9942
9943         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9944
9945         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9946                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9947                         return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9948         }
9949
9950         return WERR_BADFUNC;
9951 }
9952
9953 /*******************************************************************
9954 *******************************************************************/
9955 #if 0   /* don't support management using the "Local Port" monitor */
9956
9957 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9958                                   RPC_BUFFER *out, uint32 *needed )
9959 {
9960         const char *dllname = "localui.dll";
9961
9962         *needed = (strlen(dllname)+1) * 2;
9963
9964         if ( rpcbuf_get_size(out) < *needed ) {
9965                 return WERR_INSUFFICIENT_BUFFER;
9966         }
9967
9968         if ( !make_monitorui_buf( out, dllname )) {
9969                 return WERR_NOMEM;
9970         }
9971
9972         return WERR_OK;
9973 }
9974
9975 /*******************************************************************
9976 *******************************************************************/
9977
9978 struct xcv_api_table xcvlocal_cmds[] = {
9979         { "MonitorUI",  xcvlocal_monitorui },
9980         { NULL,         NULL }
9981 };
9982 #else
9983 struct xcv_api_table xcvlocal_cmds[] = {
9984         { NULL,         NULL }
9985 };
9986 #endif
9987
9988
9989
9990 /*******************************************************************
9991 *******************************************************************/
9992
9993 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9994                                         RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9995                                         uint32 *needed )
9996 {
9997         int i;
9998
9999         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10000
10001         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10002                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10003                         return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
10004         }
10005         return WERR_BADFUNC;
10006 }
10007
10008 /*******************************************************************
10009 *******************************************************************/
10010
10011 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
10012 {
10013         Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
10014         fstring command;
10015
10016         if (!Printer) {
10017                 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
10018                 return WERR_BADFID;
10019         }
10020
10021         /* Has to be a handle to the TCP/IP port monitor */
10022
10023         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10024                 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
10025                 return WERR_BADFID;
10026         }
10027
10028         /* requires administrative access to the server */
10029
10030         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10031                 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
10032                 return WERR_ACCESS_DENIED;
10033         }
10034
10035         /* Get the command name.  There's numerous commands supported by the
10036            TCPMON interface. */
10037
10038         rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
10039                 q_u->dataname.uni_str_len*2, 0);
10040
10041         /* Allocate the outgoing buffer */
10042
10043         if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
10044                 return WERR_NOMEM;
10045
10046         switch ( Printer->printer_type ) {
10047         case SPLHND_PORTMON_TCP:
10048                 return process_xcvtcp_command( p->server_info->ptok, command,
10049                         &q_u->indata, &r_u->outdata, &r_u->needed );
10050         case SPLHND_PORTMON_LOCAL:
10051                 return process_xcvlocal_command( p->server_info->ptok, command,
10052                         &q_u->indata, &r_u->outdata, &r_u->needed );
10053         }
10054
10055         return WERR_INVALID_PRINT_MONITOR;
10056 }
10057
10058 /****************************************************************
10059  _spoolss_AddPrintProcessor
10060 ****************************************************************/
10061
10062 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10063                                   struct spoolss_AddPrintProcessor *r)
10064 {
10065         /* for now, just indicate success and ignore the add.  We'll
10066            automatically set the winprint processor for printer
10067            entries later.  Used to debug the LexMark Optra S 1855 PCL
10068            driver --jerry */
10069
10070         return WERR_OK;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_EnumPrinters
10075 ****************************************************************/
10076
10077 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10078                              struct spoolss_EnumPrinters *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_OpenPrinter
10086 ****************************************************************/
10087
10088 WERROR _spoolss_OpenPrinter(pipes_struct *p,
10089                             struct spoolss_OpenPrinter *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_GetJob
10097 ****************************************************************/
10098
10099 WERROR _spoolss_GetJob(pipes_struct *p,
10100                        struct spoolss_GetJob *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_EnumJobs
10108 ****************************************************************/
10109
10110 WERROR _spoolss_EnumJobs(pipes_struct *p,
10111                          struct spoolss_EnumJobs *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_AddPrinter
10119 ****************************************************************/
10120
10121 WERROR _spoolss_AddPrinter(pipes_struct *p,
10122                            struct spoolss_AddPrinter *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_SetPrinter
10130 ****************************************************************/
10131
10132 WERROR _spoolss_SetPrinter(pipes_struct *p,
10133                            struct spoolss_SetPrinter *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_GetPrinter
10141 ****************************************************************/
10142
10143 WERROR _spoolss_GetPrinter(pipes_struct *p,
10144                            struct spoolss_GetPrinter *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_AddPrinterDriver
10152 ****************************************************************/
10153
10154 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10155                                  struct spoolss_AddPrinterDriver *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_EnumPrinterDrivers
10163 ****************************************************************/
10164
10165 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10166                                    struct spoolss_EnumPrinterDrivers *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_GetPrinterDriver
10174 ****************************************************************/
10175
10176 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10177                                  struct spoolss_GetPrinterDriver *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_GetPrinterDriverDirectory
10185 ****************************************************************/
10186
10187 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
10188                                           struct spoolss_GetPrinterDriverDirectory *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_EnumPrintProcessors
10196 ****************************************************************/
10197
10198 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10199                                     struct spoolss_EnumPrintProcessors *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_GetPrintProcessorDirectory
10207 ****************************************************************/
10208
10209 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10210                                            struct spoolss_GetPrintProcessorDirectory *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_ReadPrinter
10218 ****************************************************************/
10219
10220 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10221                             struct spoolss_ReadPrinter *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_GetPrinterData
10229 ****************************************************************/
10230
10231 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10232                                struct spoolss_GetPrinterData *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_SetPrinterData
10240 ****************************************************************/
10241
10242 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10243                                struct spoolss_SetPrinterData *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_WaitForPrinterChange
10251 ****************************************************************/
10252
10253 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10254                                      struct spoolss_WaitForPrinterChange *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_EnumForms
10262 ****************************************************************/
10263
10264 WERROR _spoolss_EnumForms(pipes_struct *p,
10265                           struct spoolss_EnumForms *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_EnumPorts
10273 ****************************************************************/
10274
10275 WERROR _spoolss_EnumPorts(pipes_struct *p,
10276                           struct spoolss_EnumPorts *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_EnumMonitors
10284 ****************************************************************/
10285
10286 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10287                              struct spoolss_EnumMonitors *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_AddPort
10295 ****************************************************************/
10296
10297 WERROR _spoolss_AddPort(pipes_struct *p,
10298                         struct spoolss_AddPort *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_ConfigurePort
10306 ****************************************************************/
10307
10308 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10309                               struct spoolss_ConfigurePort *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_DeletePort
10317 ****************************************************************/
10318
10319 WERROR _spoolss_DeletePort(pipes_struct *p,
10320                            struct spoolss_DeletePort *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_CreatePrinterIC
10328 ****************************************************************/
10329
10330 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10331                                 struct spoolss_CreatePrinterIC *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_PlayGDIScriptOnPrinterIC
10339 ****************************************************************/
10340
10341 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10342                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347
10348 /****************************************************************
10349  _spoolss_DeletePrinterIC
10350 ****************************************************************/
10351
10352 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10353                                 struct spoolss_DeletePrinterIC *r)
10354 {
10355         p->rng_fault_state = true;
10356         return WERR_NOT_SUPPORTED;
10357 }
10358
10359 /****************************************************************
10360  _spoolss_AddPrinterConnection
10361 ****************************************************************/
10362
10363 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10364                                      struct spoolss_AddPrinterConnection *r)
10365 {
10366         p->rng_fault_state = true;
10367         return WERR_NOT_SUPPORTED;
10368 }
10369
10370 /****************************************************************
10371  _spoolss_DeletePrinterConnection
10372 ****************************************************************/
10373
10374 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10375                                         struct spoolss_DeletePrinterConnection *r)
10376 {
10377         p->rng_fault_state = true;
10378         return WERR_NOT_SUPPORTED;
10379 }
10380
10381 /****************************************************************
10382  _spoolss_PrinterMessageBox
10383 ****************************************************************/
10384
10385 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10386                                   struct spoolss_PrinterMessageBox *r)
10387 {
10388         p->rng_fault_state = true;
10389         return WERR_NOT_SUPPORTED;
10390 }
10391
10392 /****************************************************************
10393  _spoolss_AddMonitor
10394 ****************************************************************/
10395
10396 WERROR _spoolss_AddMonitor(pipes_struct *p,
10397                            struct spoolss_AddMonitor *r)
10398 {
10399         p->rng_fault_state = true;
10400         return WERR_NOT_SUPPORTED;
10401 }
10402
10403 /****************************************************************
10404  _spoolss_DeleteMonitor
10405 ****************************************************************/
10406
10407 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10408                               struct spoolss_DeleteMonitor *r)
10409 {
10410         p->rng_fault_state = true;
10411         return WERR_NOT_SUPPORTED;
10412 }
10413
10414 /****************************************************************
10415  _spoolss_DeletePrintProcessor
10416 ****************************************************************/
10417
10418 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10419                                      struct spoolss_DeletePrintProcessor *r)
10420 {
10421         p->rng_fault_state = true;
10422         return WERR_NOT_SUPPORTED;
10423 }
10424
10425 /****************************************************************
10426  _spoolss_AddPrintProvidor
10427 ****************************************************************/
10428
10429 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10430                                  struct spoolss_AddPrintProvidor *r)
10431 {
10432         p->rng_fault_state = true;
10433         return WERR_NOT_SUPPORTED;
10434 }
10435
10436 /****************************************************************
10437  _spoolss_DeletePrintProvidor
10438 ****************************************************************/
10439
10440 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10441                                     struct spoolss_DeletePrintProvidor *r)
10442 {
10443         p->rng_fault_state = true;
10444         return WERR_NOT_SUPPORTED;
10445 }
10446
10447 /****************************************************************
10448  _spoolss_EnumPrintProcDataTypes
10449 ****************************************************************/
10450
10451 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10452                                        struct spoolss_EnumPrintProcDataTypes *r)
10453 {
10454         p->rng_fault_state = true;
10455         return WERR_NOT_SUPPORTED;
10456 }
10457
10458 /****************************************************************
10459  _spoolss_ResetPrinter
10460 ****************************************************************/
10461
10462 WERROR _spoolss_ResetPrinter(pipes_struct *p,
10463                              struct spoolss_ResetPrinter *r)
10464 {
10465         p->rng_fault_state = true;
10466         return WERR_NOT_SUPPORTED;
10467 }
10468
10469 /****************************************************************
10470  _spoolss_GetPrinterDriver2
10471 ****************************************************************/
10472
10473 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10474                                   struct spoolss_GetPrinterDriver2 *r)
10475 {
10476         p->rng_fault_state = true;
10477         return WERR_NOT_SUPPORTED;
10478 }
10479
10480 /****************************************************************
10481  _spoolss_FindFirstPrinterChangeNotification
10482 ****************************************************************/
10483
10484 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10485                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10486 {
10487         p->rng_fault_state = true;
10488         return WERR_NOT_SUPPORTED;
10489 }
10490
10491 /****************************************************************
10492  _spoolss_FindNextPrinterChangeNotification
10493 ****************************************************************/
10494
10495 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10496                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10497 {
10498         p->rng_fault_state = true;
10499         return WERR_NOT_SUPPORTED;
10500 }
10501
10502 /****************************************************************
10503  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10504 ****************************************************************/
10505
10506 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10507                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10508 {
10509         p->rng_fault_state = true;
10510         return WERR_NOT_SUPPORTED;
10511 }
10512
10513 /****************************************************************
10514  _spoolss_ReplyOpenPrinter
10515 ****************************************************************/
10516
10517 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10518                                  struct spoolss_ReplyOpenPrinter *r)
10519 {
10520         p->rng_fault_state = true;
10521         return WERR_NOT_SUPPORTED;
10522 }
10523
10524 /****************************************************************
10525  _spoolss_RouterReplyPrinter
10526 ****************************************************************/
10527
10528 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10529                                    struct spoolss_RouterReplyPrinter *r)
10530 {
10531         p->rng_fault_state = true;
10532         return WERR_NOT_SUPPORTED;
10533 }
10534
10535 /****************************************************************
10536  _spoolss_ReplyClosePrinter
10537 ****************************************************************/
10538
10539 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10540                                   struct spoolss_ReplyClosePrinter *r)
10541 {
10542         p->rng_fault_state = true;
10543         return WERR_NOT_SUPPORTED;
10544 }
10545
10546 /****************************************************************
10547  _spoolss_AddPortEx
10548 ****************************************************************/
10549
10550 WERROR _spoolss_AddPortEx(pipes_struct *p,
10551                           struct spoolss_AddPortEx *r)
10552 {
10553         p->rng_fault_state = true;
10554         return WERR_NOT_SUPPORTED;
10555 }
10556
10557 /****************************************************************
10558  _spoolss_RouterFindFirstPrinterChangeNotification
10559 ****************************************************************/
10560
10561 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10562                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10563 {
10564         p->rng_fault_state = true;
10565         return WERR_NOT_SUPPORTED;
10566 }
10567
10568 /****************************************************************
10569  _spoolss_SpoolerInit
10570 ****************************************************************/
10571
10572 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10573                             struct spoolss_SpoolerInit *r)
10574 {
10575         p->rng_fault_state = true;
10576         return WERR_NOT_SUPPORTED;
10577 }
10578
10579 /****************************************************************
10580  _spoolss_ResetPrinterEx
10581 ****************************************************************/
10582
10583 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10584                                struct spoolss_ResetPrinterEx *r)
10585 {
10586         p->rng_fault_state = true;
10587         return WERR_NOT_SUPPORTED;
10588 }
10589
10590 /****************************************************************
10591  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10592 ****************************************************************/
10593
10594 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10595                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10596 {
10597         p->rng_fault_state = true;
10598         return WERR_NOT_SUPPORTED;
10599 }
10600
10601 /****************************************************************
10602  _spoolss_RouterRefreshPrinterChangeNotification
10603 ****************************************************************/
10604
10605 WERROR _spoolss_RouterRefreshPrinterChangeNotification(pipes_struct *p,
10606                                                        struct spoolss_RouterRefreshPrinterChangeNotification *r)
10607 {
10608         p->rng_fault_state = true;
10609         return WERR_NOT_SUPPORTED;
10610 }
10611
10612 /****************************************************************
10613  _spoolss_RemoteFindNextPrinterChangeNotifyEx
10614 ****************************************************************/
10615
10616 WERROR _spoolss_RemoteFindNextPrinterChangeNotifyEx(pipes_struct *p,
10617                                                     struct spoolss_RemoteFindNextPrinterChangeNotifyEx *r)
10618 {
10619         p->rng_fault_state = true;
10620         return WERR_NOT_SUPPORTED;
10621 }
10622
10623 /****************************************************************
10624  _spoolss_44
10625 ****************************************************************/
10626
10627 WERROR _spoolss_44(pipes_struct *p,
10628                    struct spoolss_44 *r)
10629 {
10630         p->rng_fault_state = true;
10631         return WERR_NOT_SUPPORTED;
10632 }
10633
10634 /****************************************************************
10635  _spoolss_OpenPrinterEx
10636 ****************************************************************/
10637
10638 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
10639                               struct spoolss_OpenPrinterEx *r)
10640 {
10641         p->rng_fault_state = true;
10642         return WERR_NOT_SUPPORTED;
10643 }
10644
10645 /****************************************************************
10646  _spoolss_AddPrinterEx
10647 ****************************************************************/
10648
10649 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
10650                              struct spoolss_AddPrinterEx *r)
10651 {
10652         p->rng_fault_state = true;
10653         return WERR_NOT_SUPPORTED;
10654 }
10655
10656 /****************************************************************
10657  _spoolss_47
10658 ****************************************************************/
10659
10660 WERROR _spoolss_47(pipes_struct *p,
10661                    struct spoolss_47 *r)
10662 {
10663         p->rng_fault_state = true;
10664         return WERR_NOT_SUPPORTED;
10665 }
10666
10667 /****************************************************************
10668  _spoolss_EnumPrinterData
10669 ****************************************************************/
10670
10671 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10672                                 struct spoolss_EnumPrinterData *r)
10673 {
10674         p->rng_fault_state = true;
10675         return WERR_NOT_SUPPORTED;
10676 }
10677
10678 /****************************************************************
10679  _spoolss_4a
10680 ****************************************************************/
10681
10682 WERROR _spoolss_4a(pipes_struct *p,
10683                    struct spoolss_4a *r)
10684 {
10685         p->rng_fault_state = true;
10686         return WERR_NOT_SUPPORTED;
10687 }
10688
10689 /****************************************************************
10690  _spoolss_4b
10691 ****************************************************************/
10692
10693 WERROR _spoolss_4b(pipes_struct *p,
10694                    struct spoolss_4b *r)
10695 {
10696         p->rng_fault_state = true;
10697         return WERR_NOT_SUPPORTED;
10698 }
10699
10700 /****************************************************************
10701  _spoolss_4c
10702 ****************************************************************/
10703
10704 WERROR _spoolss_4c(pipes_struct *p,
10705                    struct spoolss_4c *r)
10706 {
10707         p->rng_fault_state = true;
10708         return WERR_NOT_SUPPORTED;
10709 }
10710
10711 /****************************************************************
10712  _spoolss_SetPrinterDataEx
10713 ****************************************************************/
10714
10715 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
10716                                  struct spoolss_SetPrinterDataEx *r)
10717 {
10718         p->rng_fault_state = true;
10719         return WERR_NOT_SUPPORTED;
10720 }
10721
10722 /****************************************************************
10723  _spoolss_GetPrinterDataEx
10724 ****************************************************************/
10725
10726 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
10727                                  struct spoolss_GetPrinterDataEx *r)
10728 {
10729         p->rng_fault_state = true;
10730         return WERR_NOT_SUPPORTED;
10731 }
10732
10733 /****************************************************************
10734  _spoolss_EnumPrinterDataEx
10735 ****************************************************************/
10736
10737 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10738                                   struct spoolss_EnumPrinterDataEx *r)
10739 {
10740         p->rng_fault_state = true;
10741         return WERR_NOT_SUPPORTED;
10742 }
10743
10744 /****************************************************************
10745  _spoolss_EnumPrinterKey
10746 ****************************************************************/
10747
10748 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10749                                struct spoolss_EnumPrinterKey *r)
10750 {
10751         p->rng_fault_state = true;
10752         return WERR_NOT_SUPPORTED;
10753 }
10754
10755 /****************************************************************
10756  _spoolss_53
10757 ****************************************************************/
10758
10759 WERROR _spoolss_53(pipes_struct *p,
10760                    struct spoolss_53 *r)
10761 {
10762         p->rng_fault_state = true;
10763         return WERR_NOT_SUPPORTED;
10764 }
10765
10766 /****************************************************************
10767  _spoolss_55
10768 ****************************************************************/
10769
10770 WERROR _spoolss_55(pipes_struct *p,
10771                    struct spoolss_55 *r)
10772 {
10773         p->rng_fault_state = true;
10774         return WERR_NOT_SUPPORTED;
10775 }
10776
10777 /****************************************************************
10778  _spoolss_56
10779 ****************************************************************/
10780
10781 WERROR _spoolss_56(pipes_struct *p,
10782                    struct spoolss_56 *r)
10783 {
10784         p->rng_fault_state = true;
10785         return WERR_NOT_SUPPORTED;
10786 }
10787
10788 /****************************************************************
10789  _spoolss_57
10790 ****************************************************************/
10791
10792 WERROR _spoolss_57(pipes_struct *p,
10793                    struct spoolss_57 *r)
10794 {
10795         p->rng_fault_state = true;
10796         return WERR_NOT_SUPPORTED;
10797 }
10798
10799 /****************************************************************
10800  _spoolss_XcvData
10801 ****************************************************************/
10802
10803 WERROR _spoolss_XcvData(pipes_struct *p,
10804                         struct spoolss_XcvData *r)
10805 {
10806         p->rng_fault_state = true;
10807         return WERR_NOT_SUPPORTED;
10808 }
10809
10810 /****************************************************************
10811  _spoolss_AddPrinterDriverEx
10812 ****************************************************************/
10813
10814 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10815                                    struct spoolss_AddPrinterDriverEx *r)
10816 {
10817         p->rng_fault_state = true;
10818         return WERR_NOT_SUPPORTED;
10819 }
10820
10821 /****************************************************************
10822  _spoolss_5a
10823 ****************************************************************/
10824
10825 WERROR _spoolss_5a(pipes_struct *p,
10826                    struct spoolss_5a *r)
10827 {
10828         p->rng_fault_state = true;
10829         return WERR_NOT_SUPPORTED;
10830 }
10831
10832 /****************************************************************
10833  _spoolss_5b
10834 ****************************************************************/
10835
10836 WERROR _spoolss_5b(pipes_struct *p,
10837                    struct spoolss_5b *r)
10838 {
10839         p->rng_fault_state = true;
10840         return WERR_NOT_SUPPORTED;
10841 }
10842
10843 /****************************************************************
10844  _spoolss_5c
10845 ****************************************************************/
10846
10847 WERROR _spoolss_5c(pipes_struct *p,
10848                    struct spoolss_5c *r)
10849 {
10850         p->rng_fault_state = true;
10851         return WERR_NOT_SUPPORTED;
10852 }
10853
10854 /****************************************************************
10855  _spoolss_5d
10856 ****************************************************************/
10857
10858 WERROR _spoolss_5d(pipes_struct *p,
10859                    struct spoolss_5d *r)
10860 {
10861         p->rng_fault_state = true;
10862         return WERR_NOT_SUPPORTED;
10863 }
10864
10865 /****************************************************************
10866  _spoolss_5e
10867 ****************************************************************/
10868
10869 WERROR _spoolss_5e(pipes_struct *p,
10870                    struct spoolss_5e *r)
10871 {
10872         p->rng_fault_state = true;
10873         return WERR_NOT_SUPPORTED;
10874 }
10875
10876 /****************************************************************
10877  _spoolss_5f
10878 ****************************************************************/
10879
10880 WERROR _spoolss_5f(pipes_struct *p,
10881                    struct spoolss_5f *r)
10882 {
10883         p->rng_fault_state = true;
10884         return WERR_NOT_SUPPORTED;
10885 }
10886