aec5e66a1524bde1dcf02777df2d4d0839853d10
[tprouty/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (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  _spoolss_OpenPrinter
1404 ****************************************************************/
1405
1406 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1407                             struct spoolss_OpenPrinter *r)
1408 {
1409         struct spoolss_OpenPrinterEx e;
1410         WERROR werr;
1411
1412         ZERO_STRUCT(e.in.userlevel);
1413
1414         e.in.printername        = r->in.printername;
1415         e.in.datatype           = r->in.datatype;
1416         e.in.devmode_ctr        = r->in.devmode_ctr;
1417         e.in.access_mask        = r->in.access_mask;
1418         e.in.level              = 0;
1419
1420         e.out.handle            = r->out.handle;
1421
1422         werr = _spoolss_OpenPrinterEx(p, &e);
1423
1424         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1425                 /* OpenPrinterEx returns this for a bad
1426                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1427                  * instead.
1428                  */
1429                 werr = WERR_INVALID_PRINTER_NAME;
1430         }
1431
1432         return werr;
1433 }
1434
1435 /********************************************************************
1436  FIXME: temporary convert_devicemode_new function
1437  ********************************************************************/
1438
1439 static bool convert_devicemode_new(const char *printername,
1440                                    struct spoolss_DeviceMode *devmode,
1441                                    NT_DEVICEMODE **pp_nt_devmode)
1442 {
1443         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1444
1445         /*
1446          * Ensure nt_devmode is a valid pointer
1447          * as we will be overwriting it.
1448          */
1449
1450         if (nt_devmode == NULL) {
1451                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1452                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1453                         return false;
1454         }
1455
1456         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1457         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1458
1459         nt_devmode->specversion         = devmode->specversion;
1460         nt_devmode->driverversion       = devmode->driverversion;
1461         nt_devmode->size                = devmode->size;
1462         nt_devmode->fields              = devmode->fields;
1463         nt_devmode->orientation         = devmode->orientation;
1464         nt_devmode->papersize           = devmode->papersize;
1465         nt_devmode->paperlength         = devmode->paperlength;
1466         nt_devmode->paperwidth          = devmode->paperwidth;
1467         nt_devmode->scale               = devmode->scale;
1468         nt_devmode->copies              = devmode->copies;
1469         nt_devmode->defaultsource       = devmode->defaultsource;
1470         nt_devmode->printquality        = devmode->printquality;
1471         nt_devmode->color               = devmode->color;
1472         nt_devmode->duplex              = devmode->duplex;
1473         nt_devmode->yresolution         = devmode->yresolution;
1474         nt_devmode->ttoption            = devmode->ttoption;
1475         nt_devmode->collate             = devmode->collate;
1476
1477         nt_devmode->logpixels           = devmode->logpixels;
1478         nt_devmode->bitsperpel          = devmode->bitsperpel;
1479         nt_devmode->pelswidth           = devmode->pelswidth;
1480         nt_devmode->pelsheight          = devmode->pelsheight;
1481         nt_devmode->displayflags        = devmode->displayflags;
1482         nt_devmode->displayfrequency    = devmode->displayfrequency;
1483         nt_devmode->icmmethod           = devmode->icmmethod;
1484         nt_devmode->icmintent           = devmode->icmintent;
1485         nt_devmode->mediatype           = devmode->mediatype;
1486         nt_devmode->dithertype          = devmode->dithertype;
1487         nt_devmode->reserved1           = devmode->reserved1;
1488         nt_devmode->reserved2           = devmode->reserved2;
1489         nt_devmode->panningwidth        = devmode->panningwidth;
1490         nt_devmode->panningheight       = devmode->panningheight;
1491
1492         /*
1493          * Only change private and driverextra if the incoming devmode
1494          * has a new one. JRA.
1495          */
1496
1497         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1498                 SAFE_FREE(nt_devmode->nt_dev_private);
1499                 nt_devmode->driverextra = devmode->__driverextra_length;
1500                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1501                         return false;
1502                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1503         }
1504
1505         *pp_nt_devmode = nt_devmode;
1506
1507         return true;
1508 }
1509
1510 /****************************************************************
1511  _spoolss_OpenPrinterEx
1512 ****************************************************************/
1513
1514 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1515                               struct spoolss_OpenPrinterEx *r)
1516 {
1517         POLICY_HND              *handle = r->out.handle;
1518         char *name = CONST_DISCARD(char *, r->in.printername);
1519         int snum;
1520         Printer_entry *Printer=NULL;
1521
1522         if (!name) {
1523                 return WERR_INVALID_PARAM;
1524         }
1525
1526         /* some sanity check because you can open a printer or a print server */
1527         /* aka: \\server\printer or \\server */
1528
1529         DEBUGADD(3,("checking name: %s\n",name));
1530
1531         if (!open_printer_hnd(p, handle, name, 0)) {
1532                 return WERR_INVALID_PARAM;
1533         }
1534
1535         Printer=find_printer_index_by_hnd(p, handle);
1536         if ( !Printer ) {
1537                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1538                         "handle we created for printer %s\n", name ));
1539                 close_printer_handle(p,handle);
1540                 return WERR_INVALID_PARAM;
1541         }
1542
1543         /*
1544          * First case: the user is opening the print server:
1545          *
1546          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1547          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1548          *
1549          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1550          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1551          * or if the user is listed in the smb.conf printer admin parameter.
1552          *
1553          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1554          * client view printer folder, but does not show the MSAPW.
1555          *
1556          * Note: this test needs code to check access rights here too. Jeremy
1557          * could you look at this?
1558          *
1559          * Second case: the user is opening a printer:
1560          * NT doesn't let us connect to a printer if the connecting user
1561          * doesn't have print permission.
1562          *
1563          * Third case: user is opening a Port Monitor
1564          * access checks same as opening a handle to the print server.
1565          */
1566
1567         switch (Printer->printer_type )
1568         {
1569         case SPLHND_SERVER:
1570         case SPLHND_PORTMON_TCP:
1571         case SPLHND_PORTMON_LOCAL:
1572                 /* Printserver handles use global struct... */
1573
1574                 snum = -1;
1575
1576                 /* Map standard access rights to object specific access rights */
1577
1578                 se_map_standard(&r->in.access_mask,
1579                                 &printserver_std_mapping);
1580
1581                 /* Deny any object specific bits that don't apply to print
1582                    servers (i.e printer and job specific bits) */
1583
1584                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1585
1586                 if (r->in.access_mask &
1587                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1588                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1589                         close_printer_handle(p, handle);
1590                         return WERR_ACCESS_DENIED;
1591                 }
1592
1593                 /* Allow admin access */
1594
1595                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1596                 {
1597                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1598
1599                         if (!lp_ms_add_printer_wizard()) {
1600                                 close_printer_handle(p, handle);
1601                                 return WERR_ACCESS_DENIED;
1602                         }
1603
1604                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1605                            and not a printer admin, then fail */
1606
1607                         if ((p->server_info->utok.uid != 0) &&
1608                             !user_has_privileges(p->server_info->ptok,
1609                                                  &se_printop ) &&
1610                             !token_contains_name_in_list(
1611                                     uidtoname(p->server_info->utok.uid),
1612                                     NULL, NULL,
1613                                     p->server_info->ptok,
1614                                     lp_printer_admin(snum))) {
1615                                 close_printer_handle(p, handle);
1616                                 return WERR_ACCESS_DENIED;
1617                         }
1618
1619                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1620                 }
1621                 else
1622                 {
1623                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1624                 }
1625
1626                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1627                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1628
1629                 /* We fall through to return WERR_OK */
1630                 break;
1631
1632         case SPLHND_PRINTER:
1633                 /* NT doesn't let us connect to a printer if the connecting user
1634                    doesn't have print permission.  */
1635
1636                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1637                         close_printer_handle(p, handle);
1638                         return WERR_BADFID;
1639                 }
1640
1641                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1642
1643                 /* map an empty access mask to the minimum access mask */
1644                 if (r->in.access_mask == 0x0)
1645                         r->in.access_mask = PRINTER_ACCESS_USE;
1646
1647                 /*
1648                  * If we are not serving the printer driver for this printer,
1649                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1650                  * will keep NT clients happy  --jerry
1651                  */
1652
1653                 if (lp_use_client_driver(snum)
1654                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1655                 {
1656                         r->in.access_mask = PRINTER_ACCESS_USE;
1657                 }
1658
1659                 /* check smb.conf parameters and the the sec_desc */
1660
1661                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1662                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1663                         return WERR_ACCESS_DENIED;
1664                 }
1665
1666                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1667                                    p->server_info->ptok, snum) ||
1668                     !print_access_check(p->server_info, snum,
1669                                         r->in.access_mask)) {
1670                         DEBUG(3, ("access DENIED for printer open\n"));
1671                         close_printer_handle(p, handle);
1672                         return WERR_ACCESS_DENIED;
1673                 }
1674
1675                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1676                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1677                         close_printer_handle(p, handle);
1678                         return WERR_ACCESS_DENIED;
1679                 }
1680
1681                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1682                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1683                 else
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685
1686                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1688
1689                 break;
1690
1691         default:
1692                 /* sanity check to prevent programmer error */
1693                 return WERR_BADFID;
1694         }
1695
1696         Printer->access_granted = r->in.access_mask;
1697
1698         /*
1699          * If the client sent a devmode in the OpenPrinter() call, then
1700          * save it here in case we get a job submission on this handle
1701          */
1702
1703          if ( (Printer->printer_type != SPLHND_SERVER)
1704                 && r->in.devmode_ctr.devmode )
1705          {
1706                 convert_devicemode_new(Printer->sharename,
1707                                        r->in.devmode_ctr.devmode,
1708                                        &Printer->nt_devmode);
1709          }
1710
1711 #if 0   /* JERRY -- I'm doubtful this is really effective */
1712         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713            optimization in Windows 2000 clients  --jerry */
1714
1715         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1716                 && (RA_WIN2K == get_remote_arch()) )
1717         {
1718                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1719                 sys_usleep( 500000 );
1720         }
1721 #endif
1722
1723         return WERR_OK;
1724 }
1725
1726 /****************************************************************************
1727 ****************************************************************************/
1728
1729 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1731 {
1732         bool ret;
1733
1734         switch (level) {
1735                 case 2:
1736                         /* allocate memory if needed.  Messy because
1737                            convert_printer_info is used to update an existing
1738                            printer or build a new one */
1739
1740                         if ( !printer->info_2 ) {
1741                                 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742                                 if ( !printer->info_2 ) {
1743                                         DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744                                         return False;
1745                                 }
1746                         }
1747
1748                         ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749                         printer->info_2->setuptime = time(NULL);
1750
1751                         return ret;
1752         }
1753
1754         return False;
1755 }
1756
1757 /****************************************************************************
1758 ****************************************************************************/
1759
1760 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1761                                               NT_PRINTER_INFO_LEVEL_2 *d)
1762 {
1763         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1764
1765         if (!r || !d) {
1766                 return false;
1767         }
1768
1769         d->attributes           = r->attributes;
1770         d->priority             = r->priority;
1771         d->default_priority     = r->defaultpriority;
1772         d->starttime            = r->starttime;
1773         d->untiltime            = r->untiltime;
1774         d->status               = r->status;
1775         d->cjobs                = r->cjobs;
1776
1777         fstrcpy(d->servername,  r->servername);
1778         fstrcpy(d->printername, r->printername);
1779         fstrcpy(d->sharename,   r->sharename);
1780         fstrcpy(d->portname,    r->portname);
1781         fstrcpy(d->drivername,  r->drivername);
1782         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1783         fstrcpy(d->location,    r->location);
1784         fstrcpy(d->sepfile,     r->sepfile);
1785         fstrcpy(d->printprocessor, r->printprocessor);
1786         fstrcpy(d->datatype,    r->datatype);
1787         fstrcpy(d->parameters,  r->parameters);
1788
1789         return true;
1790 }
1791
1792 /****************************************************************************
1793 ****************************************************************************/
1794
1795 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1796                                      NT_PRINTER_INFO_LEVEL *printer)
1797 {
1798         bool ret;
1799
1800         switch (info_ctr->level) {
1801         case 2:
1802                 /* allocate memory if needed.  Messy because
1803                    convert_printer_info is used to update an existing
1804                    printer or build a new one */
1805
1806                 if (!printer->info_2) {
1807                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1808                         if (!printer->info_2) {
1809                                 DEBUG(0,("convert_printer_info_new: "
1810                                         "talloc() failed!\n"));
1811                                 return false;
1812                         }
1813                 }
1814
1815                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1816                                                         printer->info_2);
1817                 printer->info_2->setuptime = time(NULL);
1818                 return ret;
1819         }
1820
1821         return false;
1822 }
1823
1824 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1825                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1826 {
1827         bool result = True;
1828
1829         switch (level) {
1830                 case 3:
1831                         printer->info_3=NULL;
1832                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1833                                 result = False;
1834                         break;
1835                 case 6:
1836                         printer->info_6=NULL;
1837                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1838                                 result = False;
1839                         break;
1840                 default:
1841                         break;
1842         }
1843
1844         return result;
1845 }
1846
1847 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1848                                 NT_DEVICEMODE **pp_nt_devmode)
1849 {
1850         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1851
1852         /*
1853          * Ensure nt_devmode is a valid pointer
1854          * as we will be overwriting it.
1855          */
1856
1857         if (nt_devmode == NULL) {
1858                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1859                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1860                         return False;
1861         }
1862
1863         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1864         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1865
1866         nt_devmode->specversion=devmode->specversion;
1867         nt_devmode->driverversion=devmode->driverversion;
1868         nt_devmode->size=devmode->size;
1869         nt_devmode->fields=devmode->fields;
1870         nt_devmode->orientation=devmode->orientation;
1871         nt_devmode->papersize=devmode->papersize;
1872         nt_devmode->paperlength=devmode->paperlength;
1873         nt_devmode->paperwidth=devmode->paperwidth;
1874         nt_devmode->scale=devmode->scale;
1875         nt_devmode->copies=devmode->copies;
1876         nt_devmode->defaultsource=devmode->defaultsource;
1877         nt_devmode->printquality=devmode->printquality;
1878         nt_devmode->color=devmode->color;
1879         nt_devmode->duplex=devmode->duplex;
1880         nt_devmode->yresolution=devmode->yresolution;
1881         nt_devmode->ttoption=devmode->ttoption;
1882         nt_devmode->collate=devmode->collate;
1883
1884         nt_devmode->logpixels=devmode->logpixels;
1885         nt_devmode->bitsperpel=devmode->bitsperpel;
1886         nt_devmode->pelswidth=devmode->pelswidth;
1887         nt_devmode->pelsheight=devmode->pelsheight;
1888         nt_devmode->displayflags=devmode->displayflags;
1889         nt_devmode->displayfrequency=devmode->displayfrequency;
1890         nt_devmode->icmmethod=devmode->icmmethod;
1891         nt_devmode->icmintent=devmode->icmintent;
1892         nt_devmode->mediatype=devmode->mediatype;
1893         nt_devmode->dithertype=devmode->dithertype;
1894         nt_devmode->reserved1=devmode->reserved1;
1895         nt_devmode->reserved2=devmode->reserved2;
1896         nt_devmode->panningwidth=devmode->panningwidth;
1897         nt_devmode->panningheight=devmode->panningheight;
1898
1899         /*
1900          * Only change private and driverextra if the incoming devmode
1901          * has a new one. JRA.
1902          */
1903
1904         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1905                 SAFE_FREE(nt_devmode->nt_dev_private);
1906                 nt_devmode->driverextra=devmode->driverextra;
1907                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1908                         return False;
1909                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1910         }
1911
1912         *pp_nt_devmode = nt_devmode;
1913
1914         return True;
1915 }
1916
1917 /********************************************************************
1918  * _spoolss_enddocprinter_internal.
1919  ********************************************************************/
1920
1921 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1922 {
1923         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1924         int snum;
1925
1926         if (!Printer) {
1927                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1928                 return WERR_BADFID;
1929         }
1930
1931         if (!get_printer_snum(p, handle, &snum, NULL))
1932                 return WERR_BADFID;
1933
1934         Printer->document_started=False;
1935         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1936         /* error codes unhandled so far ... */
1937
1938         return WERR_OK;
1939 }
1940
1941 /****************************************************************
1942  _spoolss_ClosePrinter
1943 ****************************************************************/
1944
1945 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1946                              struct spoolss_ClosePrinter *r)
1947 {
1948         POLICY_HND *handle = r->in.handle;
1949
1950         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1951
1952         if (Printer && Printer->document_started)
1953                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1954
1955         if (!close_printer_handle(p, handle))
1956                 return WERR_BADFID;
1957
1958         /* clear the returned printer handle.  Observed behavior
1959            from Win2k server.  Don't think this really matters.
1960            Previous code just copied the value of the closed
1961            handle.    --jerry */
1962
1963         ZERO_STRUCTP(r->out.handle);
1964
1965         return WERR_OK;
1966 }
1967
1968 /****************************************************************
1969  _spoolss_DeletePrinter
1970 ****************************************************************/
1971
1972 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1973                               struct spoolss_DeletePrinter *r)
1974 {
1975         POLICY_HND *handle = r->in.handle;
1976         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1977         WERROR result;
1978
1979         if (Printer && Printer->document_started)
1980                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1981
1982         result = delete_printer_handle(p, handle);
1983
1984         update_c_setprinter(False);
1985
1986         return result;
1987 }
1988
1989 /*******************************************************************
1990  * static function to lookup the version id corresponding to an
1991  * long architecture string
1992  ******************************************************************/
1993
1994 static int get_version_id (char * arch)
1995 {
1996         int i;
1997         struct table_node archi_table[]= {
1998
1999                 {"Windows 4.0",          "WIN40",       0 },
2000                 {"Windows NT x86",       "W32X86",      2 },
2001                 {"Windows NT R4000",     "W32MIPS",     2 },
2002                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2003                 {"Windows NT PowerPC",   "W32PPC",      2 },
2004                 {"Windows IA64",         "IA64",        3 },
2005                 {"Windows x64",          "x64",         3 },
2006                 {NULL,                   "",            -1 }
2007         };
2008
2009         for (i=0; archi_table[i].long_archi != NULL; i++)
2010         {
2011                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2012                         return (archi_table[i].version);
2013         }
2014
2015         return -1;
2016 }
2017
2018 /****************************************************************
2019  _spoolss_DeletePrinterDriver
2020 ****************************************************************/
2021
2022 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2023                                     struct spoolss_DeletePrinterDriver *r)
2024 {
2025         char *driver;
2026         char *arch;
2027         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2028         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2029         int                             version;
2030         WERROR                          status;
2031         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2032         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2033
2034         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2035            and not a printer admin, then fail */
2036
2037         if ( (p->server_info->utok.uid != 0)
2038                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2039                 && !token_contains_name_in_list(
2040                         uidtoname(p->server_info->utok.uid), NULL,
2041                         NULL, p->server_info->ptok,
2042                         lp_printer_admin(-1)) )
2043         {
2044                 return WERR_ACCESS_DENIED;
2045         }
2046
2047         driver = CONST_DISCARD(char *, r->in.driver);
2048         arch   = CONST_DISCARD(char *, r->in.architecture);
2049
2050         /* check that we have a valid driver name first */
2051
2052         if ((version=get_version_id(arch)) == -1)
2053                 return WERR_INVALID_ENVIRONMENT;
2054
2055         ZERO_STRUCT(info);
2056         ZERO_STRUCT(info_win2k);
2057
2058         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2059         {
2060                 /* try for Win2k driver if "Windows NT x86" */
2061
2062                 if ( version == 2 ) {
2063                         version = 3;
2064                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2065                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2066                                 goto done;
2067                         }
2068                 }
2069                 /* otherwise it was a failure */
2070                 else {
2071                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2072                         goto done;
2073                 }
2074
2075         }
2076
2077         if (printer_driver_in_use(info.info_3)) {
2078                 status = WERR_PRINTER_DRIVER_IN_USE;
2079                 goto done;
2080         }
2081
2082         if ( version == 2 )
2083         {
2084                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2085                 {
2086                         /* if we get to here, we now have 2 driver info structures to remove */
2087                         /* remove the Win2k driver first*/
2088
2089                         status_win2k = delete_printer_driver(
2090                                 p, info_win2k.info_3, 3, False );
2091                         free_a_printer_driver( info_win2k, 3 );
2092
2093                         /* this should not have failed---if it did, report to client */
2094                         if ( !W_ERROR_IS_OK(status_win2k) )
2095                         {
2096                                 status = status_win2k;
2097                                 goto done;
2098                         }
2099                 }
2100         }
2101
2102         status = delete_printer_driver(p, info.info_3, version, False);
2103
2104         /* if at least one of the deletes succeeded return OK */
2105
2106         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2107                 status = WERR_OK;
2108
2109 done:
2110         free_a_printer_driver( info, 3 );
2111
2112         return status;
2113 }
2114
2115 /****************************************************************
2116  _spoolss_DeletePrinterDriverEx
2117 ****************************************************************/
2118
2119 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2120                                       struct spoolss_DeletePrinterDriverEx *r)
2121 {
2122         char *driver;
2123         char *arch;
2124         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2125         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2126         int                             version;
2127         uint32_t                        flags = r->in.delete_flags;
2128         bool                            delete_files;
2129         WERROR                          status;
2130         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2131         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2132
2133         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2134            and not a printer admin, then fail */
2135
2136         if ( (p->server_info->utok.uid != 0)
2137                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2138                 && !token_contains_name_in_list(
2139                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2140                         p->server_info->ptok, lp_printer_admin(-1)) )
2141         {
2142                 return WERR_ACCESS_DENIED;
2143         }
2144
2145         driver = CONST_DISCARD(char *, r->in.driver);
2146         arch   = CONST_DISCARD(char *, r->in.architecture);
2147
2148         /* check that we have a valid driver name first */
2149         if ((version=get_version_id(arch)) == -1) {
2150                 /* this is what NT returns */
2151                 return WERR_INVALID_ENVIRONMENT;
2152         }
2153
2154         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2155                 version = r->in.version;
2156
2157         ZERO_STRUCT(info);
2158         ZERO_STRUCT(info_win2k);
2159
2160         status = get_a_printer_driver(&info, 3, driver, arch, version);
2161
2162         if ( !W_ERROR_IS_OK(status) )
2163         {
2164                 /*
2165                  * if the client asked for a specific version,
2166                  * or this is something other than Windows NT x86,
2167                  * then we've failed
2168                  */
2169
2170                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2171                         goto done;
2172
2173                 /* try for Win2k driver if "Windows NT x86" */
2174
2175                 version = 3;
2176                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2177                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2178                         goto done;
2179                 }
2180         }
2181
2182         if ( printer_driver_in_use(info.info_3) ) {
2183                 status = WERR_PRINTER_DRIVER_IN_USE;
2184                 goto done;
2185         }
2186
2187         /*
2188          * we have a couple of cases to consider.
2189          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2190          *     then the delete should fail if **any** files overlap with
2191          *     other drivers
2192          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2193          *     non-overlapping files
2194          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2195          *     is set, the do not delete any files
2196          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2197          */
2198
2199         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2200
2201         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2202
2203         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2204                 /* no idea of the correct error here */
2205                 status = WERR_ACCESS_DENIED;
2206                 goto done;
2207         }
2208
2209
2210         /* also check for W32X86/3 if necessary; maybe we already have? */
2211
2212         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2213                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2214                 {
2215
2216                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2217                                 /* no idea of the correct error here */
2218                                 free_a_printer_driver( info_win2k, 3 );
2219                                 status = WERR_ACCESS_DENIED;
2220                                 goto done;
2221                         }
2222
2223                         /* if we get to here, we now have 2 driver info structures to remove */
2224                         /* remove the Win2k driver first*/
2225
2226                         status_win2k = delete_printer_driver(
2227                                 p, info_win2k.info_3, 3, delete_files);
2228                         free_a_printer_driver( info_win2k, 3 );
2229
2230                         /* this should not have failed---if it did, report to client */
2231
2232                         if ( !W_ERROR_IS_OK(status_win2k) )
2233                                 goto done;
2234                 }
2235         }
2236
2237         status = delete_printer_driver(p, info.info_3, version, delete_files);
2238
2239         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2240                 status = WERR_OK;
2241 done:
2242         free_a_printer_driver( info, 3 );
2243
2244         return status;
2245 }
2246
2247
2248 /****************************************************************************
2249  Internal routine for retreiving printerdata
2250  ***************************************************************************/
2251
2252 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2253                                   const char *key, const char *value, uint32 *type, uint8 **data,
2254                                   uint32 *needed, uint32 in_size  )
2255 {
2256         REGISTRY_VALUE          *val;
2257         uint32                  size;
2258         int                     data_len;
2259
2260         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2261                 return WERR_BADFILE;
2262
2263         *type = regval_type( val );
2264
2265         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2266
2267         size = regval_size( val );
2268
2269         /* copy the min(in_size, len) */
2270
2271         if ( in_size ) {
2272                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2273
2274                 /* special case for 0 length values */
2275                 if ( data_len ) {
2276                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2277                                 return WERR_NOMEM;
2278                 }
2279                 else {
2280                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2281                                 return WERR_NOMEM;
2282                 }
2283         }
2284         else
2285                 *data = NULL;
2286
2287         *needed = size;
2288
2289         DEBUG(5,("get_printer_dataex: copy done\n"));
2290
2291         return WERR_OK;
2292 }
2293
2294 /****************************************************************************
2295  Internal routine for removing printerdata
2296  ***************************************************************************/
2297
2298 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2299 {
2300         return delete_printer_data( printer->info_2, key, value );
2301 }
2302
2303 /****************************************************************************
2304  Internal routine for storing printerdata
2305  ***************************************************************************/
2306
2307 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2308                                   uint32 type, uint8 *data, int real_len  )
2309 {
2310         /* the registry objects enforce uniqueness based on value name */
2311
2312         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2313 }
2314
2315 /********************************************************************
2316  GetPrinterData on a printer server Handle.
2317 ********************************************************************/
2318
2319 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2320 {
2321         int i;
2322
2323         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2324
2325         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2326                 *type = REG_DWORD;
2327                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2328                         return WERR_NOMEM;
2329                 SIVAL(*data, 0, 0x00);
2330                 *needed = 0x4;
2331                 return WERR_OK;
2332         }
2333
2334         if (!StrCaseCmp(value, "BeepEnabled")) {
2335                 *type = REG_DWORD;
2336                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2337                         return WERR_NOMEM;
2338                 SIVAL(*data, 0, 0x00);
2339                 *needed = 0x4;
2340                 return WERR_OK;
2341         }
2342
2343         if (!StrCaseCmp(value, "EventLog")) {
2344                 *type = REG_DWORD;
2345                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2346                         return WERR_NOMEM;
2347                 /* formally was 0x1b */
2348                 SIVAL(*data, 0, 0x0);
2349                 *needed = 0x4;
2350                 return WERR_OK;
2351         }
2352
2353         if (!StrCaseCmp(value, "NetPopup")) {
2354                 *type = REG_DWORD;
2355                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2356                         return WERR_NOMEM;
2357                 SIVAL(*data, 0, 0x00);
2358                 *needed = 0x4;
2359                 return WERR_OK;
2360         }
2361
2362         if (!StrCaseCmp(value, "MajorVersion")) {
2363                 *type = REG_DWORD;
2364                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2365                         return WERR_NOMEM;
2366
2367                 /* Windows NT 4.0 seems to not allow uploading of drivers
2368                    to a server that reports 0x3 as the MajorVersion.
2369                    need to investigate more how Win2k gets around this .
2370                    -- jerry */
2371
2372                 if ( RA_WINNT == get_remote_arch() )
2373                         SIVAL(*data, 0, 2);
2374                 else
2375                         SIVAL(*data, 0, 3);
2376
2377                 *needed = 0x4;
2378                 return WERR_OK;
2379         }
2380
2381         if (!StrCaseCmp(value, "MinorVersion")) {
2382                 *type = REG_DWORD;
2383                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2384                         return WERR_NOMEM;
2385                 SIVAL(*data, 0, 0);
2386                 *needed = 0x4;
2387                 return WERR_OK;
2388         }
2389
2390         /* REG_BINARY
2391          *  uint32 size          = 0x114
2392          *  uint32 major         = 5
2393          *  uint32 minor         = [0|1]
2394          *  uint32 build         = [2195|2600]
2395          *  extra unicode string = e.g. "Service Pack 3"
2396          */
2397         if (!StrCaseCmp(value, "OSVersion")) {
2398                 *type = REG_BINARY;
2399                 *needed = 0x114;
2400
2401                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2402                         return WERR_NOMEM;
2403
2404                 SIVAL(*data, 0, *needed);       /* size */
2405                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2406                 SIVAL(*data, 8, 0);
2407                 SIVAL(*data, 12, 2195);         /* build */
2408
2409                 /* leave extra string empty */
2410
2411                 return WERR_OK;
2412         }
2413
2414
2415         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2416                 const char *string="C:\\PRINTERS";
2417                 *type = REG_SZ;
2418                 *needed = 2*(strlen(string)+1);
2419                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2420                         return WERR_NOMEM;
2421                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2422
2423                 /* it's done by hand ready to go on the wire */
2424                 for (i=0; i<strlen(string); i++) {
2425                         (*data)[2*i]=string[i];
2426                         (*data)[2*i+1]='\0';
2427                 }
2428                 return WERR_OK;
2429         }
2430
2431         if (!StrCaseCmp(value, "Architecture")) {
2432                 const char *string="Windows NT x86";
2433                 *type = REG_SZ;
2434                 *needed = 2*(strlen(string)+1);
2435                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2436                         return WERR_NOMEM;
2437                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2438                 for (i=0; i<strlen(string); i++) {
2439                         (*data)[2*i]=string[i];
2440                         (*data)[2*i+1]='\0';
2441                 }
2442                 return WERR_OK;
2443         }
2444
2445         if (!StrCaseCmp(value, "DsPresent")) {
2446                 *type = REG_DWORD;
2447                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2448                         return WERR_NOMEM;
2449
2450                 /* only show the publish check box if we are a
2451                    memeber of a AD domain */
2452
2453                 if ( lp_security() == SEC_ADS )
2454                         SIVAL(*data, 0, 0x01);
2455                 else
2456                         SIVAL(*data, 0, 0x00);
2457
2458                 *needed = 0x4;
2459                 return WERR_OK;
2460         }
2461
2462         if (!StrCaseCmp(value, "DNSMachineName")) {
2463                 const char *hostname = get_mydnsfullname();
2464
2465                 if (!hostname)
2466                         return WERR_BADFILE;
2467                 *type = REG_SZ;
2468                 *needed = 2*(strlen(hostname)+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                 for (i=0; i<strlen(hostname); i++) {
2473                         (*data)[2*i]=hostname[i];
2474                         (*data)[2*i+1]='\0';
2475                 }
2476                 return WERR_OK;
2477         }
2478
2479
2480         return WERR_BADFILE;
2481 }
2482
2483 /********************************************************************
2484  * spoolss_getprinterdata
2485  ********************************************************************/
2486
2487 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2488 {
2489         POLICY_HND      *handle = &q_u->handle;
2490         UNISTR2         *valuename = &q_u->valuename;
2491         uint32          in_size = q_u->size;
2492         uint32          *type = &r_u->type;
2493         uint32          *out_size = &r_u->size;
2494         uint8           **data = &r_u->data;
2495         uint32          *needed = &r_u->needed;
2496         WERROR          status;
2497         fstring         value;
2498         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2499         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2500         int             snum = 0;
2501
2502         /*
2503          * Reminder: when it's a string, the length is in BYTES
2504          * even if UNICODE is negociated.
2505          *
2506          * JFM, 4/19/1999
2507          */
2508
2509         *out_size = in_size;
2510
2511         /* in case of problem, return some default values */
2512
2513         *needed = 0;
2514         *type   = 0;
2515
2516         DEBUG(4,("_spoolss_getprinterdata\n"));
2517
2518         if ( !Printer ) {
2519                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2520                 status = WERR_BADFID;
2521                 goto done;
2522         }
2523
2524         unistr2_to_ascii(value, valuename, sizeof(value));
2525
2526         if ( Printer->printer_type == SPLHND_SERVER )
2527                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2528         else
2529         {
2530                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2531                         status = WERR_BADFID;
2532                         goto done;
2533                 }
2534
2535                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2536                 if ( !W_ERROR_IS_OK(status) )
2537                         goto done;
2538
2539                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2540
2541                 if ( strequal(value, "ChangeId") ) {
2542                         *type = REG_DWORD;
2543                         *needed = sizeof(uint32);
2544                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2545                                 status = WERR_NOMEM;
2546                                 goto done;
2547                         }
2548                         SIVAL( *data, 0, printer->info_2->changeid );
2549                         status = WERR_OK;
2550                 }
2551                 else
2552                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2553         }
2554
2555         if (*needed > *out_size)
2556                 status = WERR_MORE_DATA;
2557
2558 done:
2559         if ( !W_ERROR_IS_OK(status) )
2560         {
2561                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2562
2563                 /* reply this param doesn't exist */
2564
2565                 if ( *out_size ) {
2566                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2567                                 if ( printer )
2568                                         free_a_printer( &printer, 2 );
2569                                 return WERR_NOMEM;
2570                         }
2571                 } else {
2572                         *data = NULL;
2573                 }
2574         }
2575
2576         /* cleanup & exit */
2577
2578         if ( printer )
2579                 free_a_printer( &printer, 2 );
2580
2581         return status;
2582 }
2583
2584 /*********************************************************
2585  Connect to the client machine.
2586 **********************************************************/
2587
2588 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2589                         struct sockaddr_storage *client_ss, const char *remote_machine)
2590 {
2591         NTSTATUS ret;
2592         struct cli_state *the_cli;
2593         struct sockaddr_storage rm_addr;
2594
2595         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2596                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2597                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2598                         return False;
2599                 }
2600
2601                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2602                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2603                         return False;
2604                 }
2605         } else {
2606                 char addr[INET6_ADDRSTRLEN];
2607                 rm_addr = *client_ss;
2608                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2609                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2610                         addr));
2611         }
2612
2613         /* setup the connection */
2614
2615         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2616                 &rm_addr, 0, "IPC$", "IPC",
2617                 "", /* username */
2618                 "", /* domain */
2619                 "", /* password */
2620                 0, lp_client_signing(), NULL );
2621
2622         if ( !NT_STATUS_IS_OK( ret ) ) {
2623                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2624                         remote_machine ));
2625                 return False;
2626         }
2627
2628         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2629                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2630                 cli_shutdown(the_cli);
2631                 return False;
2632         }
2633
2634         /*
2635          * Ok - we have an anonymous connection to the IPC$ share.
2636          * Now start the NT Domain stuff :-).
2637          */
2638
2639         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2640         if (!NT_STATUS_IS_OK(ret)) {
2641                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2642                         remote_machine, nt_errstr(ret)));
2643                 cli_shutdown(the_cli);
2644                 return False;
2645         }
2646
2647         return True;
2648 }
2649
2650 /***************************************************************************
2651  Connect to the client.
2652 ****************************************************************************/
2653
2654 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2655                                         uint32 localprinter, uint32 type,
2656                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2657 {
2658         WERROR result;
2659         NTSTATUS status;
2660
2661         /*
2662          * If it's the first connection, contact the client
2663          * and connect to the IPC$ share anonymously
2664          */
2665         if (smb_connections==0) {
2666                 fstring unix_printer;
2667
2668                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2669
2670                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2671                         return False;
2672
2673                 messaging_register(smbd_messaging_context(), NULL,
2674                                    MSG_PRINTER_NOTIFY2,
2675                                    receive_notify2_message_list);
2676                 /* Tell the connections db we're now interested in printer
2677                  * notify messages. */
2678                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2679         }
2680
2681         /*
2682          * Tell the specific printing tdb we want messages for this printer
2683          * by registering our PID.
2684          */
2685
2686         if (!print_notify_register_pid(snum))
2687                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2688
2689         smb_connections++;
2690
2691         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2692                                                  printer,
2693                                                  localprinter,
2694                                                  type,
2695                                                  0,
2696                                                  NULL,
2697                                                  handle,
2698                                                  &result);
2699         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2700                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2701                         win_errstr(result)));
2702
2703         return (W_ERROR_IS_OK(result));
2704 }
2705
2706 /********************************************************************
2707  * _spoolss_rffpcnex
2708  * ReplyFindFirstPrinterChangeNotifyEx
2709  *
2710  * before replying OK: status=0 a rpc call is made to the workstation
2711  * asking ReplyOpenPrinter
2712  *
2713  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2714  * called from api_spoolss_rffpcnex
2715  ********************************************************************/
2716
2717 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2718 {
2719         POLICY_HND *handle = &q_u->handle;
2720         uint32 flags = q_u->flags;
2721         uint32 options = q_u->options;
2722         UNISTR2 *localmachine = &q_u->localmachine;
2723         uint32 printerlocal = q_u->printerlocal;
2724         int snum = -1;
2725         SPOOL_NOTIFY_OPTION *option = q_u->option;
2726         struct sockaddr_storage client_ss;
2727
2728         /* store the notify value in the printer struct */
2729
2730         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2731
2732         if (!Printer) {
2733                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2734                 return WERR_BADFID;
2735         }
2736
2737         Printer->notify.flags=flags;
2738         Printer->notify.options=options;
2739         Printer->notify.printerlocal=printerlocal;
2740
2741         if (Printer->notify.option)
2742                 free_spool_notify_option(&Printer->notify.option);
2743
2744         Printer->notify.option=dup_spool_notify_option(option);
2745
2746         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2747                        sizeof(Printer->notify.localmachine));
2748
2749         /* Connect to the client machine and send a ReplyOpenPrinter */
2750
2751         if ( Printer->printer_type == SPLHND_SERVER)
2752                 snum = -1;
2753         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2754                         !get_printer_snum(p, handle, &snum, NULL) )
2755                 return WERR_BADFID;
2756
2757         if (!interpret_string_addr(&client_ss, p->client_address,
2758                                    AI_NUMERICHOST)) {
2759                 return WERR_SERVER_UNAVAILABLE;
2760         }
2761
2762         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2763                                         Printer->notify.printerlocal, 1,
2764                                         &Printer->notify.client_hnd, &client_ss))
2765                 return WERR_SERVER_UNAVAILABLE;
2766
2767         Printer->notify.client_connected=True;
2768
2769         return WERR_OK;
2770 }
2771
2772 /*******************************************************************
2773  * fill a notify_info_data with the servername
2774  ********************************************************************/
2775
2776 void spoolss_notify_server_name(int snum,
2777                                        SPOOL_NOTIFY_INFO_DATA *data,
2778                                        print_queue_struct *queue,
2779                                        NT_PRINTER_INFO_LEVEL *printer,
2780                                        TALLOC_CTX *mem_ctx)
2781 {
2782         smb_ucs2_t *temp = NULL;
2783         uint32 len;
2784
2785         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2786         if (len == (uint32)-1) {
2787                 len = 0;
2788         }
2789
2790         data->notify_data.data.length = len;
2791         if (len) {
2792                 data->notify_data.data.string = (uint16 *)temp;
2793         } else {
2794                 data->notify_data.data.string = NULL;
2795         }
2796 }
2797
2798 /*******************************************************************
2799  * fill a notify_info_data with the printername (not including the servername).
2800  ********************************************************************/
2801
2802 void spoolss_notify_printer_name(int snum,
2803                                         SPOOL_NOTIFY_INFO_DATA *data,
2804                                         print_queue_struct *queue,
2805                                         NT_PRINTER_INFO_LEVEL *printer,
2806                                         TALLOC_CTX *mem_ctx)
2807 {
2808         smb_ucs2_t *temp = NULL;
2809         uint32 len;
2810
2811         /* the notify name should not contain the \\server\ part */
2812         char *p = strrchr(printer->info_2->printername, '\\');
2813
2814         if (!p) {
2815                 p = printer->info_2->printername;
2816         } else {
2817                 p++;
2818         }
2819
2820         len = rpcstr_push_talloc(mem_ctx, &temp, p);
2821         if (len == (uint32)-1) {
2822                 len = 0;
2823         }
2824
2825         data->notify_data.data.length = len;
2826         if (len) {
2827                 data->notify_data.data.string = (uint16 *)temp;
2828         } else {
2829                 data->notify_data.data.string = NULL;
2830         }
2831 }
2832
2833 /*******************************************************************
2834  * fill a notify_info_data with the servicename
2835  ********************************************************************/
2836
2837 void spoolss_notify_share_name(int snum,
2838                                       SPOOL_NOTIFY_INFO_DATA *data,
2839                                       print_queue_struct *queue,
2840                                       NT_PRINTER_INFO_LEVEL *printer,
2841                                       TALLOC_CTX *mem_ctx)
2842 {
2843         smb_ucs2_t *temp = NULL;
2844         uint32 len;
2845
2846         len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2847         if (len == (uint32)-1) {
2848                 len = 0;
2849         }
2850
2851         data->notify_data.data.length = len;
2852         if (len) {
2853                 data->notify_data.data.string = (uint16 *)temp;
2854         } else {
2855                 data->notify_data.data.string = NULL;
2856         }
2857
2858 }
2859
2860 /*******************************************************************
2861  * fill a notify_info_data with the port name
2862  ********************************************************************/
2863
2864 void spoolss_notify_port_name(int snum,
2865                                      SPOOL_NOTIFY_INFO_DATA *data,
2866                                      print_queue_struct *queue,
2867                                      NT_PRINTER_INFO_LEVEL *printer,
2868                                      TALLOC_CTX *mem_ctx)
2869 {
2870         smb_ucs2_t *temp = NULL;
2871         uint32 len;
2872
2873         /* even if it's strange, that's consistant in all the code */
2874
2875         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2876         if (len == (uint32)-1) {
2877                 len = 0;
2878         }
2879
2880         data->notify_data.data.length = len;
2881         if (len) {
2882                 data->notify_data.data.string = (uint16 *)temp;
2883         } else {
2884                 data->notify_data.data.string = NULL;
2885         }
2886 }
2887
2888 /*******************************************************************
2889  * fill a notify_info_data with the printername
2890  * but it doesn't exist, have to see what to do
2891  ********************************************************************/
2892
2893 void spoolss_notify_driver_name(int snum,
2894                                        SPOOL_NOTIFY_INFO_DATA *data,
2895                                        print_queue_struct *queue,
2896                                        NT_PRINTER_INFO_LEVEL *printer,
2897                                        TALLOC_CTX *mem_ctx)
2898 {
2899         smb_ucs2_t *temp = NULL;
2900         uint32 len;
2901
2902         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2903         if (len == (uint32)-1) {
2904                 len = 0;
2905         }
2906
2907         data->notify_data.data.length = len;
2908         if (len) {
2909                 data->notify_data.data.string = (uint16 *)temp;
2910         } else {
2911                 data->notify_data.data.string = NULL;
2912         }
2913 }
2914
2915 /*******************************************************************
2916  * fill a notify_info_data with the comment
2917  ********************************************************************/
2918
2919 void spoolss_notify_comment(int snum,
2920                                    SPOOL_NOTIFY_INFO_DATA *data,
2921                                    print_queue_struct *queue,
2922                                    NT_PRINTER_INFO_LEVEL *printer,
2923                                    TALLOC_CTX *mem_ctx)
2924 {
2925         smb_ucs2_t *temp = NULL;
2926         uint32 len;
2927
2928         if (*printer->info_2->comment == '\0')
2929                 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2930         else
2931                 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2932
2933         if (len == (uint32)-1) {
2934                 len = 0;
2935         }
2936         data->notify_data.data.length = len;
2937         if (len) {
2938                 data->notify_data.data.string = (uint16 *)temp;
2939         } else {
2940                 data->notify_data.data.string = NULL;
2941         }
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the comment
2946  * location = "Room 1, floor 2, building 3"
2947  ********************************************************************/
2948
2949 void spoolss_notify_location(int snum,
2950                                     SPOOL_NOTIFY_INFO_DATA *data,
2951                                     print_queue_struct *queue,
2952                                     NT_PRINTER_INFO_LEVEL *printer,
2953                                     TALLOC_CTX *mem_ctx)
2954 {
2955         smb_ucs2_t *temp = NULL;
2956         uint32 len;
2957
2958         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2959         if (len == (uint32)-1) {
2960                 len = 0;
2961         }
2962
2963         data->notify_data.data.length = len;
2964         if (len) {
2965                 data->notify_data.data.string = (uint16 *)temp;
2966         } else {
2967                 data->notify_data.data.string = NULL;
2968         }
2969 }
2970
2971 /*******************************************************************
2972  * fill a notify_info_data with the device mode
2973  * jfm:xxxx don't to it for know but that's a real problem !!!
2974  ********************************************************************/
2975
2976 static void spoolss_notify_devmode(int snum,
2977                                    SPOOL_NOTIFY_INFO_DATA *data,
2978                                    print_queue_struct *queue,
2979                                    NT_PRINTER_INFO_LEVEL *printer,
2980                                    TALLOC_CTX *mem_ctx)
2981 {
2982         /* for a dummy implementation we have to zero the fields */
2983         data->notify_data.data.length = 0;
2984         data->notify_data.data.string = NULL;
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the separator file name
2989  ********************************************************************/
2990
2991 void spoolss_notify_sepfile(int snum,
2992                                    SPOOL_NOTIFY_INFO_DATA *data,
2993                                    print_queue_struct *queue,
2994                                    NT_PRINTER_INFO_LEVEL *printer,
2995                                    TALLOC_CTX *mem_ctx)
2996 {
2997         smb_ucs2_t *temp = NULL;
2998         uint32 len;
2999
3000         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
3001         if (len == (uint32)-1) {
3002                 len = 0;
3003         }
3004
3005         data->notify_data.data.length = len;
3006         if (len) {
3007                 data->notify_data.data.string = (uint16 *)temp;
3008         } else {
3009                 data->notify_data.data.string = NULL;
3010         }
3011 }
3012
3013 /*******************************************************************
3014  * fill a notify_info_data with the print processor
3015  * jfm:xxxx return always winprint to indicate we don't do anything to it
3016  ********************************************************************/
3017
3018 void spoolss_notify_print_processor(int snum,
3019                                            SPOOL_NOTIFY_INFO_DATA *data,
3020                                            print_queue_struct *queue,
3021                                            NT_PRINTER_INFO_LEVEL *printer,
3022                                            TALLOC_CTX *mem_ctx)
3023 {
3024         smb_ucs2_t *temp = NULL;
3025         uint32 len;
3026
3027         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3028         if (len == (uint32)-1) {
3029                 len = 0;
3030         }
3031
3032         data->notify_data.data.length = len;
3033         if (len) {
3034                 data->notify_data.data.string = (uint16 *)temp;
3035         } else {
3036                 data->notify_data.data.string = NULL;
3037         }
3038 }
3039
3040 /*******************************************************************
3041  * fill a notify_info_data with the print processor options
3042  * jfm:xxxx send an empty string
3043  ********************************************************************/
3044
3045 void spoolss_notify_parameters(int snum,
3046                                       SPOOL_NOTIFY_INFO_DATA *data,
3047                                       print_queue_struct *queue,
3048                                       NT_PRINTER_INFO_LEVEL *printer,
3049                                       TALLOC_CTX *mem_ctx)
3050 {
3051         smb_ucs2_t *temp = NULL;
3052         uint32 len;
3053
3054         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3055         if (len == (uint32)-1) {
3056                 len = 0;
3057         }
3058
3059         data->notify_data.data.length = len;
3060         if (len) {
3061                 data->notify_data.data.string = (uint16 *)temp;
3062         } else {
3063                 data->notify_data.data.string = NULL;
3064         }
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with the data type
3069  * jfm:xxxx always send RAW as data type
3070  ********************************************************************/
3071
3072 void spoolss_notify_datatype(int snum,
3073                                     SPOOL_NOTIFY_INFO_DATA *data,
3074                                     print_queue_struct *queue,
3075                                     NT_PRINTER_INFO_LEVEL *printer,
3076                                     TALLOC_CTX *mem_ctx)
3077 {
3078         smb_ucs2_t *temp = NULL;
3079         uint32 len;
3080
3081         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3082         if (len == (uint32)-1) {
3083                 len = 0;
3084         }
3085
3086         data->notify_data.data.length = len;
3087         if (len) {
3088                 data->notify_data.data.string = (uint16 *)temp;
3089         } else {
3090                 data->notify_data.data.string = NULL;
3091         }
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the security descriptor
3096  * jfm:xxxx send an null pointer to say no security desc
3097  * have to implement security before !
3098  ********************************************************************/
3099
3100 static void spoolss_notify_security_desc(int snum,
3101                                          SPOOL_NOTIFY_INFO_DATA *data,
3102                                          print_queue_struct *queue,
3103                                          NT_PRINTER_INFO_LEVEL *printer,
3104                                          TALLOC_CTX *mem_ctx)
3105 {
3106         data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3107         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3108 }
3109
3110 /*******************************************************************
3111  * fill a notify_info_data with the attributes
3112  * jfm:xxxx a samba printer is always shared
3113  ********************************************************************/
3114
3115 void spoolss_notify_attributes(int snum,
3116                                       SPOOL_NOTIFY_INFO_DATA *data,
3117                                       print_queue_struct *queue,
3118                                       NT_PRINTER_INFO_LEVEL *printer,
3119                                       TALLOC_CTX *mem_ctx)
3120 {
3121         data->notify_data.value[0] = printer->info_2->attributes;
3122         data->notify_data.value[1] = 0;
3123 }
3124
3125 /*******************************************************************
3126  * fill a notify_info_data with the priority
3127  ********************************************************************/
3128
3129 static void spoolss_notify_priority(int snum,
3130                                     SPOOL_NOTIFY_INFO_DATA *data,
3131                                     print_queue_struct *queue,
3132                                     NT_PRINTER_INFO_LEVEL *printer,
3133                                     TALLOC_CTX *mem_ctx)
3134 {
3135         data->notify_data.value[0] = printer->info_2->priority;
3136         data->notify_data.value[1] = 0;
3137 }
3138
3139 /*******************************************************************
3140  * fill a notify_info_data with the default priority
3141  ********************************************************************/
3142
3143 static void spoolss_notify_default_priority(int snum,
3144                                             SPOOL_NOTIFY_INFO_DATA *data,
3145                                             print_queue_struct *queue,
3146                                             NT_PRINTER_INFO_LEVEL *printer,
3147                                             TALLOC_CTX *mem_ctx)
3148 {
3149         data->notify_data.value[0] = printer->info_2->default_priority;
3150         data->notify_data.value[1] = 0;
3151 }
3152
3153 /*******************************************************************
3154  * fill a notify_info_data with the start time
3155  ********************************************************************/
3156
3157 static void spoolss_notify_start_time(int snum,
3158                                       SPOOL_NOTIFY_INFO_DATA *data,
3159                                       print_queue_struct *queue,
3160                                       NT_PRINTER_INFO_LEVEL *printer,
3161                                       TALLOC_CTX *mem_ctx)
3162 {
3163         data->notify_data.value[0] = printer->info_2->starttime;
3164         data->notify_data.value[1] = 0;
3165 }
3166
3167 /*******************************************************************
3168  * fill a notify_info_data with the until time
3169  ********************************************************************/
3170
3171 static void spoolss_notify_until_time(int snum,
3172                                       SPOOL_NOTIFY_INFO_DATA *data,
3173                                       print_queue_struct *queue,
3174                                       NT_PRINTER_INFO_LEVEL *printer,
3175                                       TALLOC_CTX *mem_ctx)
3176 {
3177         data->notify_data.value[0] = printer->info_2->untiltime;
3178         data->notify_data.value[1] = 0;
3179 }
3180
3181 /*******************************************************************
3182  * fill a notify_info_data with the status
3183  ********************************************************************/
3184
3185 static void spoolss_notify_status(int snum,
3186                                   SPOOL_NOTIFY_INFO_DATA *data,
3187                                   print_queue_struct *queue,
3188                                   NT_PRINTER_INFO_LEVEL *printer,
3189                                   TALLOC_CTX *mem_ctx)
3190 {
3191         print_status_struct status;
3192
3193         print_queue_length(snum, &status);
3194         data->notify_data.value[0]=(uint32) status.status;
3195         data->notify_data.value[1] = 0;
3196 }
3197
3198 /*******************************************************************
3199  * fill a notify_info_data with the number of jobs queued
3200  ********************************************************************/
3201
3202 void spoolss_notify_cjobs(int snum,
3203                                  SPOOL_NOTIFY_INFO_DATA *data,
3204                                  print_queue_struct *queue,
3205                                  NT_PRINTER_INFO_LEVEL *printer,
3206                                  TALLOC_CTX *mem_ctx)
3207 {
3208         data->notify_data.value[0] = print_queue_length(snum, NULL);
3209         data->notify_data.value[1] = 0;
3210 }
3211
3212 /*******************************************************************
3213  * fill a notify_info_data with the average ppm
3214  ********************************************************************/
3215
3216 static void spoolss_notify_average_ppm(int snum,
3217                                        SPOOL_NOTIFY_INFO_DATA *data,
3218                                        print_queue_struct *queue,
3219                                        NT_PRINTER_INFO_LEVEL *printer,
3220                                        TALLOC_CTX *mem_ctx)
3221 {
3222         /* always respond 8 pages per minutes */
3223         /* a little hard ! */
3224         data->notify_data.value[0] = printer->info_2->averageppm;
3225         data->notify_data.value[1] = 0;
3226 }
3227
3228 /*******************************************************************
3229  * fill a notify_info_data with username
3230  ********************************************************************/
3231
3232 static void spoolss_notify_username(int snum,
3233                                     SPOOL_NOTIFY_INFO_DATA *data,
3234                                     print_queue_struct *queue,
3235                                     NT_PRINTER_INFO_LEVEL *printer,
3236                                     TALLOC_CTX *mem_ctx)
3237 {
3238         smb_ucs2_t *temp = NULL;
3239         uint32 len;
3240
3241         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3242         if (len == (uint32)-1) {
3243                 len = 0;
3244         }
3245
3246         data->notify_data.data.length = len;
3247         if (len) {
3248                 data->notify_data.data.string = (uint16 *)temp;
3249         } else {
3250                 data->notify_data.data.string = NULL;
3251         }
3252 }
3253
3254 /*******************************************************************
3255  * fill a notify_info_data with job status
3256  ********************************************************************/
3257
3258 static void spoolss_notify_job_status(int snum,
3259                                       SPOOL_NOTIFY_INFO_DATA *data,
3260                                       print_queue_struct *queue,
3261                                       NT_PRINTER_INFO_LEVEL *printer,
3262                                       TALLOC_CTX *mem_ctx)
3263 {
3264         data->notify_data.value[0]=nt_printj_status(queue->status);
3265         data->notify_data.value[1] = 0;
3266 }
3267
3268 /*******************************************************************
3269  * fill a notify_info_data with job name
3270  ********************************************************************/
3271
3272 static void spoolss_notify_job_name(int snum,
3273                                     SPOOL_NOTIFY_INFO_DATA *data,
3274                                     print_queue_struct *queue,
3275                                     NT_PRINTER_INFO_LEVEL *printer,
3276                                     TALLOC_CTX *mem_ctx)
3277 {
3278         smb_ucs2_t *temp = NULL;
3279         uint32 len;
3280
3281         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3282         if (len == (uint32)-1) {
3283                 len = 0;
3284         }
3285
3286         data->notify_data.data.length = len;
3287         if (len) {
3288                 data->notify_data.data.string = (uint16 *)temp;
3289         } else {
3290                 data->notify_data.data.string = NULL;
3291         }
3292 }
3293
3294 /*******************************************************************
3295  * fill a notify_info_data with job status
3296  ********************************************************************/
3297
3298 static void spoolss_notify_job_status_string(int snum,
3299                                              SPOOL_NOTIFY_INFO_DATA *data,
3300                                              print_queue_struct *queue,
3301                                              NT_PRINTER_INFO_LEVEL *printer,
3302                                              TALLOC_CTX *mem_ctx)
3303 {
3304         /*
3305          * Now we're returning job status codes we just return a "" here. JRA.
3306          */
3307
3308         const char *p = "";
3309         smb_ucs2_t *temp = NULL;
3310         uint32 len;
3311
3312 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3313         p = "unknown";
3314
3315         switch (queue->status) {
3316         case LPQ_QUEUED:
3317                 p = "Queued";
3318                 break;
3319         case LPQ_PAUSED:
3320                 p = "";    /* NT provides the paused string */
3321                 break;
3322         case LPQ_SPOOLING:
3323                 p = "Spooling";
3324                 break;
3325         case LPQ_PRINTING:
3326                 p = "Printing";
3327                 break;
3328         }
3329 #endif /* NO LONGER NEEDED. */
3330
3331         len = rpcstr_push_talloc(mem_ctx, &temp, p);
3332         if (len == (uint32)-1) {
3333                 len = 0;
3334         }
3335
3336         data->notify_data.data.length = len;
3337         if (len) {
3338                 data->notify_data.data.string = (uint16 *)temp;
3339         } else {
3340                 data->notify_data.data.string = NULL;
3341         }
3342 }
3343
3344 /*******************************************************************
3345  * fill a notify_info_data with job time
3346  ********************************************************************/
3347
3348 static void spoolss_notify_job_time(int snum,
3349                                     SPOOL_NOTIFY_INFO_DATA *data,
3350                                     print_queue_struct *queue,
3351                                     NT_PRINTER_INFO_LEVEL *printer,
3352                                     TALLOC_CTX *mem_ctx)
3353 {
3354         data->notify_data.value[0]=0x0;
3355         data->notify_data.value[1]=0;
3356 }
3357
3358 /*******************************************************************
3359  * fill a notify_info_data with job size
3360  ********************************************************************/
3361
3362 static void spoolss_notify_job_size(int snum,
3363                                     SPOOL_NOTIFY_INFO_DATA *data,
3364                                     print_queue_struct *queue,
3365                                     NT_PRINTER_INFO_LEVEL *printer,
3366                                     TALLOC_CTX *mem_ctx)
3367 {
3368         data->notify_data.value[0]=queue->size;
3369         data->notify_data.value[1]=0;
3370 }
3371
3372 /*******************************************************************
3373  * fill a notify_info_data with page info
3374  ********************************************************************/
3375 static void spoolss_notify_total_pages(int snum,
3376                                 SPOOL_NOTIFY_INFO_DATA *data,
3377                                 print_queue_struct *queue,
3378                                 NT_PRINTER_INFO_LEVEL *printer,
3379                                 TALLOC_CTX *mem_ctx)
3380 {
3381         data->notify_data.value[0]=queue->page_count;
3382         data->notify_data.value[1]=0;
3383 }
3384
3385 /*******************************************************************
3386  * fill a notify_info_data with pages printed info.
3387  ********************************************************************/
3388 static void spoolss_notify_pages_printed(int snum,
3389                                 SPOOL_NOTIFY_INFO_DATA *data,
3390                                 print_queue_struct *queue,
3391                                 NT_PRINTER_INFO_LEVEL *printer,
3392                                 TALLOC_CTX *mem_ctx)
3393 {
3394         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3395         data->notify_data.value[1]=0;
3396 }
3397
3398 /*******************************************************************
3399  Fill a notify_info_data with job position.
3400  ********************************************************************/
3401
3402 static void spoolss_notify_job_position(int snum,
3403                                         SPOOL_NOTIFY_INFO_DATA *data,
3404                                         print_queue_struct *queue,
3405                                         NT_PRINTER_INFO_LEVEL *printer,
3406                                         TALLOC_CTX *mem_ctx)
3407 {
3408         data->notify_data.value[0]=queue->job;
3409         data->notify_data.value[1]=0;
3410 }
3411
3412 /*******************************************************************
3413  Fill a notify_info_data with submitted time.
3414  ********************************************************************/
3415
3416 static void spoolss_notify_submitted_time(int snum,
3417                                           SPOOL_NOTIFY_INFO_DATA *data,
3418                                           print_queue_struct *queue,
3419                                           NT_PRINTER_INFO_LEVEL *printer,
3420                                           TALLOC_CTX *mem_ctx)
3421 {
3422         struct tm *t;
3423         uint32 len;
3424         SYSTEMTIME st;
3425         char *p;
3426
3427         t=gmtime(&queue->time);
3428
3429         len = sizeof(SYSTEMTIME);
3430
3431         data->notify_data.data.length = len;
3432         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3433
3434         if (!data->notify_data.data.string) {
3435                 data->notify_data.data.length = 0;
3436                 return;
3437         }
3438
3439         make_systemtime(&st, t);
3440
3441         /*
3442          * Systemtime must be linearized as a set of UINT16's.
3443          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3444          */
3445
3446         p = (char *)data->notify_data.data.string;
3447         SSVAL(p, 0, st.year);
3448         SSVAL(p, 2, st.month);
3449         SSVAL(p, 4, st.dayofweek);
3450         SSVAL(p, 6, st.day);
3451         SSVAL(p, 8, st.hour);
3452         SSVAL(p, 10, st.minute);
3453         SSVAL(p, 12, st.second);
3454         SSVAL(p, 14, st.milliseconds);
3455 }
3456
3457 struct s_notify_info_data_table
3458 {
3459         uint16 type;
3460         uint16 field;
3461         const char *name;
3462         uint32 size;
3463         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3464                     print_queue_struct *queue,
3465                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3466 };
3467
3468 /* A table describing the various print notification constants and
3469    whether the notification data is a pointer to a variable sized
3470    buffer, a one value uint32 or a two value uint32. */
3471
3472 static const struct s_notify_info_data_table notify_info_data_table[] =
3473 {
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3494 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3495 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3496 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3497 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3498 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3499 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3500 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3501 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3502 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3503 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3504 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3505 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3506 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3507 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3508 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3509 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3510 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3511 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3512 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3513 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3514 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3515 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3516 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3517 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3518 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3519 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3520 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3521 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3522 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3523 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3524 };
3525
3526 /*******************************************************************
3527  Return the size of info_data structure.
3528 ********************************************************************/
3529
3530 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3531 {
3532         int i=0;
3533
3534         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3535                 if ( (notify_info_data_table[i].type == type)
3536                         && (notify_info_data_table[i].field == field) ) {
3537                         switch(notify_info_data_table[i].size) {
3538                                 case NOTIFY_ONE_VALUE:
3539                                 case NOTIFY_TWO_VALUE:
3540                                         return 1;
3541                                 case NOTIFY_STRING:
3542                                         return 2;
3543
3544                                 /* The only pointer notify data I have seen on
3545                                    the wire is the submitted time and this has
3546                                    the notify size set to 4. -tpot */
3547
3548                                 case NOTIFY_POINTER:
3549                                         return 4;
3550
3551                                 case NOTIFY_SECDESC:
3552                                         return 5;
3553                         }
3554                 }
3555         }
3556
3557         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3558
3559         return 0;
3560 }
3561
3562 /*******************************************************************
3563  Return the type of notify_info_data.
3564 ********************************************************************/
3565
3566 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3567 {
3568         uint32 i=0;
3569
3570         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3571                 if (notify_info_data_table[i].type == type &&
3572                     notify_info_data_table[i].field == field)
3573                         return notify_info_data_table[i].size;
3574         }
3575
3576         return 0;
3577 }
3578
3579 /****************************************************************************
3580 ****************************************************************************/
3581
3582 static bool search_notify(uint16 type, uint16 field, int *value)
3583 {
3584         int i;
3585
3586         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3587                 if (notify_info_data_table[i].type == type &&
3588                     notify_info_data_table[i].field == field &&
3589                     notify_info_data_table[i].fn != NULL) {
3590                         *value = i;
3591                         return True;
3592                 }
3593         }
3594
3595         return False;
3596 }
3597
3598 /****************************************************************************
3599 ****************************************************************************/
3600
3601 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3602 {
3603         info_data->type     = type;
3604         info_data->field    = field;
3605         info_data->reserved = 0;
3606
3607         info_data->size     = size_of_notify_info_data(type, field);
3608         info_data->enc_type = type_of_notify_info_data(type, field);
3609
3610         info_data->id = id;
3611 }
3612
3613 /*******************************************************************
3614  *
3615  * fill a notify_info struct with info asked
3616  *
3617  ********************************************************************/
3618
3619 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3620                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3621                                           *option_type, uint32 id,
3622                                           TALLOC_CTX *mem_ctx)
3623 {
3624         int field_num,j;
3625         uint16 type;
3626         uint16 field;
3627
3628         SPOOL_NOTIFY_INFO_DATA *current_data;
3629         NT_PRINTER_INFO_LEVEL *printer = NULL;
3630         print_queue_struct *queue=NULL;
3631
3632         type=option_type->type;
3633
3634         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3635                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3636                 option_type->count, lp_servicename(snum)));
3637
3638         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3639                 return False;
3640
3641         for(field_num=0; field_num<option_type->count; field_num++) {
3642                 field = option_type->fields[field_num];
3643
3644                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3645
3646                 if (!search_notify(type, field, &j) )
3647                         continue;
3648
3649                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3650                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3651                         free_a_printer(&printer, 2);
3652                         return False;
3653                 }
3654
3655                 current_data = &info->data[info->count];
3656
3657                 construct_info_data(current_data, type, field, id);
3658
3659                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3660                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3661
3662                 notify_info_data_table[j].fn(snum, current_data, queue,
3663                                              printer, mem_ctx);
3664
3665                 info->count++;
3666         }
3667
3668         free_a_printer(&printer, 2);
3669         return True;
3670 }
3671
3672 /*******************************************************************
3673  *
3674  * fill a notify_info struct with info asked
3675  *
3676  ********************************************************************/
3677
3678 static bool construct_notify_jobs_info(print_queue_struct *queue,
3679                                        SPOOL_NOTIFY_INFO *info,
3680                                        NT_PRINTER_INFO_LEVEL *printer,
3681                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3682                                        *option_type, uint32 id,
3683                                        TALLOC_CTX *mem_ctx)
3684 {
3685         int field_num,j;
3686         uint16 type;
3687         uint16 field;
3688
3689         SPOOL_NOTIFY_INFO_DATA *current_data;
3690
3691         DEBUG(4,("construct_notify_jobs_info\n"));
3692
3693         type = option_type->type;
3694
3695         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3696                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3697                 option_type->count));
3698
3699         for(field_num=0; field_num<option_type->count; field_num++) {
3700                 field = option_type->fields[field_num];
3701
3702                 if (!search_notify(type, field, &j) )
3703                         continue;
3704
3705                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3706                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3707                         return False;
3708                 }
3709
3710                 current_data=&(info->data[info->count]);
3711
3712                 construct_info_data(current_data, type, field, id);
3713                 notify_info_data_table[j].fn(snum, current_data, queue,
3714                                              printer, mem_ctx);
3715                 info->count++;
3716         }
3717
3718         return True;
3719 }
3720
3721 /*
3722  * JFM: The enumeration is not that simple, it's even non obvious.
3723  *
3724  * let's take an example: I want to monitor the PRINTER SERVER for
3725  * the printer's name and the number of jobs currently queued.
3726  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3727  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3728  *
3729  * I have 3 printers on the back of my server.
3730  *
3731  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3732  * structures.
3733  *   Number     Data                    Id
3734  *      1       printer 1 name          1
3735  *      2       printer 1 cjob          1
3736  *      3       printer 2 name          2
3737  *      4       printer 2 cjob          2
3738  *      5       printer 3 name          3
3739  *      6       printer 3 name          3
3740  *
3741  * that's the print server case, the printer case is even worse.
3742  */
3743
3744 /*******************************************************************
3745  *
3746  * enumerate all printers on the printserver
3747  * fill a notify_info struct with info asked
3748  *
3749  ********************************************************************/
3750
3751 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3752                                       SPOOL_NOTIFY_INFO *info,
3753                                       TALLOC_CTX *mem_ctx)
3754 {
3755         int snum;
3756         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3757         int n_services=lp_numservices();
3758         int i;
3759         SPOOL_NOTIFY_OPTION *option;
3760         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3761
3762         DEBUG(4,("printserver_notify_info\n"));
3763
3764         if (!Printer)
3765                 return WERR_BADFID;
3766
3767         option=Printer->notify.option;
3768         info->version=2;
3769         info->data=NULL;
3770         info->count=0;
3771
3772         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3773            sending a ffpcn() request first */
3774
3775         if ( !option )
3776                 return WERR_BADFID;
3777
3778         for (i=0; i<option->count; i++) {
3779                 option_type=&(option->ctr.type[i]);
3780
3781                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3782                         continue;
3783
3784                 for (snum=0; snum<n_services; snum++)
3785                 {
3786                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3787                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3788                 }
3789         }
3790
3791 #if 0
3792         /*
3793          * Debugging information, don't delete.
3794          */
3795
3796         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3797         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3798         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3799
3800         for (i=0; i<info->count; i++) {
3801                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3802                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3803                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3804         }
3805 #endif
3806
3807         return WERR_OK;
3808 }
3809
3810 /*******************************************************************
3811  *
3812  * fill a notify_info struct with info asked
3813  *
3814  ********************************************************************/
3815
3816 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3817                                   TALLOC_CTX *mem_ctx)
3818 {
3819         int snum;
3820         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3821         int i;
3822         uint32 id;
3823         SPOOL_NOTIFY_OPTION *option;
3824         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3825         int count,j;
3826         print_queue_struct *queue=NULL;
3827         print_status_struct status;
3828
3829         DEBUG(4,("printer_notify_info\n"));
3830
3831         if (!Printer)
3832                 return WERR_BADFID;
3833
3834         option=Printer->notify.option;
3835         id = 0x0;
3836         info->version=2;
3837         info->data=NULL;
3838         info->count=0;
3839
3840         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3841            sending a ffpcn() request first */
3842
3843         if ( !option )
3844                 return WERR_BADFID;
3845
3846         get_printer_snum(p, hnd, &snum, NULL);
3847
3848         for (i=0; i<option->count; i++) {
3849                 option_type=&option->ctr.type[i];
3850
3851                 switch ( option_type->type ) {
3852                 case PRINTER_NOTIFY_TYPE:
3853                         if(construct_notify_printer_info(Printer, info, snum,
3854                                                          option_type, id,
3855                                                          mem_ctx))
3856                                 id--;
3857                         break;
3858
3859                 case JOB_NOTIFY_TYPE: {
3860                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3861
3862                         count = print_queue_status(snum, &queue, &status);
3863
3864                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3865                                 goto done;
3866
3867                         for (j=0; j<count; j++) {
3868                                 construct_notify_jobs_info(&queue[j], info,
3869                                                            printer, snum,
3870                                                            option_type,
3871                                                            queue[j].job,
3872                                                            mem_ctx);
3873                         }
3874
3875                         free_a_printer(&printer, 2);
3876
3877                 done:
3878                         SAFE_FREE(queue);
3879                         break;
3880                 }
3881                 }
3882         }
3883
3884         /*
3885          * Debugging information, don't delete.
3886          */
3887         /*
3888         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3889         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3890         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3891
3892         for (i=0; i<info->count; i++) {
3893                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3894                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3895                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3896         }
3897         */
3898         return WERR_OK;
3899 }
3900
3901 /********************************************************************
3902  * spoolss_rfnpcnex
3903  ********************************************************************/
3904
3905 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3906 {
3907         POLICY_HND *handle = &q_u->handle;
3908         SPOOL_NOTIFY_INFO *info = &r_u->info;
3909
3910         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3911         WERROR result = WERR_BADFID;
3912
3913         /* we always have a NOTIFY_INFO struct */
3914         r_u->info_ptr=0x1;
3915
3916         if (!Printer) {
3917                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3918                          OUR_HANDLE(handle)));
3919                 goto done;
3920         }
3921
3922         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3923
3924         /*
3925          *      We are now using the change value, and
3926          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3927          *      I don't have a global notification system, I'm sending back all the
3928          *      informations even when _NOTHING_ has changed.
3929          */
3930
3931         /* We need to keep track of the change value to send back in
3932            RRPCN replies otherwise our updates are ignored. */
3933
3934         Printer->notify.fnpcn = True;
3935
3936         if (Printer->notify.client_connected) {
3937                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3938                 Printer->notify.change = q_u->change;
3939         }
3940
3941         /* just ignore the SPOOL_NOTIFY_OPTION */
3942
3943         switch (Printer->printer_type) {
3944                 case SPLHND_SERVER:
3945                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3946                         break;
3947
3948                 case SPLHND_PRINTER:
3949                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3950                         break;
3951         }
3952
3953         Printer->notify.fnpcn = False;
3954
3955 done:
3956         return result;
3957 }
3958
3959 /********************************************************************
3960  * construct_printer_info_0
3961  * fill a printer_info_0 struct
3962  ********************************************************************/
3963
3964 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3965 {
3966         char *chaine = NULL;
3967         int count;
3968         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3969         counter_printer_0 *session_counter;
3970         uint32 global_counter;
3971         struct tm *t;
3972         time_t setuptime;
3973         print_status_struct status;
3974         TALLOC_CTX *ctx = talloc_tos();
3975
3976         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3977                 return False;
3978
3979         init_unistr(&printer->printername, ntprinter->info_2->printername);
3980
3981         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3982         if (!chaine) {
3983                 free_a_printer(&ntprinter,2);
3984                 return false;
3985         }
3986
3987         count = print_queue_length(snum, &status);
3988
3989         /* check if we already have a counter for this printer */
3990         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3991                 if (session_counter->snum == snum)
3992                         break;
3993         }
3994
3995         init_unistr(&printer->servername, chaine);
3996
3997         /* it's the first time, add it to the list */
3998         if (session_counter==NULL) {
3999                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
4000                         free_a_printer(&ntprinter, 2);
4001                         return False;
4002                 }
4003                 ZERO_STRUCTP(session_counter);
4004                 session_counter->snum=snum;
4005                 session_counter->counter=0;
4006                 DLIST_ADD(counter_list, session_counter);
4007         }
4008
4009         /* increment it */
4010         session_counter->counter++;
4011
4012         /* JFM:
4013          * the global_counter should be stored in a TDB as it's common to all the clients
4014          * and should be zeroed on samba startup
4015          */
4016         global_counter=session_counter->counter;
4017         printer->cjobs = count;
4018         printer->total_jobs = 0;
4019         printer->total_bytes = 0;
4020
4021         setuptime = (time_t)ntprinter->info_2->setuptime;
4022         t=gmtime(&setuptime);
4023
4024         printer->year = t->tm_year+1900;
4025         printer->month = t->tm_mon+1;
4026         printer->dayofweek = t->tm_wday;
4027         printer->day = t->tm_mday;
4028         printer->hour = t->tm_hour;
4029         printer->minute = t->tm_min;
4030         printer->second = t->tm_sec;
4031         printer->milliseconds = 0;
4032
4033         printer->global_counter = global_counter;
4034         printer->total_pages = 0;
4035
4036         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4037         printer->major_version = 0x0005;        /* NT 5 */
4038         printer->build_version = 0x0893;        /* build 2195 */
4039
4040         printer->unknown7 = 0x1;
4041         printer->unknown8 = 0x0;
4042         printer->unknown9 = 0x0;
4043         printer->session_counter = session_counter->counter;
4044         printer->unknown11 = 0x0;
4045         printer->printer_errors = 0x0;          /* number of print failure */
4046         printer->unknown13 = 0x0;
4047         printer->unknown14 = 0x1;
4048         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4049         printer->unknown16 =  0x0;
4050         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4051         printer->unknown18 =  0x0;
4052         printer->status = nt_printq_status(status.status);
4053         printer->unknown20 =  0x0;
4054         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4055         printer->unknown22 = 0x0;
4056         printer->unknown23 = 0x6;               /* 6  ???*/
4057         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4058         printer->unknown25 = 0;
4059         printer->unknown26 = 0;
4060         printer->unknown27 = 0;
4061         printer->unknown28 = 0;
4062         printer->unknown29 = 0;
4063
4064         free_a_printer(&ntprinter,2);
4065         return (True);
4066 }
4067
4068 /********************************************************************
4069  * construct_printer_info_1
4070  * fill a printer_info_1 struct
4071  ********************************************************************/
4072 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4073 {
4074         char *chaine = NULL;
4075         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4076         TALLOC_CTX *ctx = talloc_tos();
4077
4078         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4079                 return false;
4080
4081         printer->flags=flags;
4082
4083         if (*ntprinter->info_2->comment == '\0') {
4084                 init_unistr(&printer->comment, lp_comment(snum));
4085                 chaine = talloc_asprintf(ctx,
4086                                 "%s,%s,%s", ntprinter->info_2->printername,
4087                                 ntprinter->info_2->drivername, lp_comment(snum));
4088         }
4089         else {
4090                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4091                 chaine = talloc_asprintf(ctx,
4092                                 "%s,%s,%s", ntprinter->info_2->printername,
4093                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4094         }
4095
4096         if (!chaine) {
4097                 free_a_printer(&ntprinter,2);
4098                 return false;
4099         }
4100
4101         init_unistr(&printer->description, chaine);
4102         init_unistr(&printer->name, ntprinter->info_2->printername);
4103
4104         free_a_printer(&ntprinter,2);
4105
4106         return True;
4107 }
4108
4109 /****************************************************************************
4110  Free a DEVMODE struct.
4111 ****************************************************************************/
4112
4113 static void free_dev_mode(DEVICEMODE *dev)
4114 {
4115         if (dev == NULL)
4116                 return;
4117
4118         SAFE_FREE(dev->dev_private);
4119         SAFE_FREE(dev);
4120 }
4121
4122
4123 /****************************************************************************
4124  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4125  should be valid upon entry
4126 ****************************************************************************/
4127
4128 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4129 {
4130         if ( !devmode || !ntdevmode )
4131                 return False;
4132
4133         init_unistr(&devmode->devicename, ntdevmode->devicename);
4134
4135         init_unistr(&devmode->formname, ntdevmode->formname);
4136
4137         devmode->specversion      = ntdevmode->specversion;
4138         devmode->driverversion    = ntdevmode->driverversion;
4139         devmode->size             = ntdevmode->size;
4140         devmode->driverextra      = ntdevmode->driverextra;
4141         devmode->fields           = ntdevmode->fields;
4142
4143         devmode->orientation      = ntdevmode->orientation;
4144         devmode->papersize        = ntdevmode->papersize;
4145         devmode->paperlength      = ntdevmode->paperlength;
4146         devmode->paperwidth       = ntdevmode->paperwidth;
4147         devmode->scale            = ntdevmode->scale;
4148         devmode->copies           = ntdevmode->copies;
4149         devmode->defaultsource    = ntdevmode->defaultsource;
4150         devmode->printquality     = ntdevmode->printquality;
4151         devmode->color            = ntdevmode->color;
4152         devmode->duplex           = ntdevmode->duplex;
4153         devmode->yresolution      = ntdevmode->yresolution;
4154         devmode->ttoption         = ntdevmode->ttoption;
4155         devmode->collate          = ntdevmode->collate;
4156         devmode->icmmethod        = ntdevmode->icmmethod;
4157         devmode->icmintent        = ntdevmode->icmintent;
4158         devmode->mediatype        = ntdevmode->mediatype;
4159         devmode->dithertype       = ntdevmode->dithertype;
4160
4161         if (ntdevmode->nt_dev_private != NULL) {
4162                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4163                         return False;
4164         }
4165
4166         return True;
4167 }
4168
4169 /****************************************************************************
4170  Create a DEVMODE struct. Returns malloced memory.
4171 ****************************************************************************/
4172
4173 DEVICEMODE *construct_dev_mode(const char *servicename)
4174 {
4175         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4176         DEVICEMODE              *devmode = NULL;
4177
4178         DEBUG(7,("construct_dev_mode\n"));
4179
4180         DEBUGADD(8,("getting printer characteristics\n"));
4181
4182         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4183                 return NULL;
4184
4185         if ( !printer->info_2->devmode ) {
4186                 DEBUG(5, ("BONG! There was no device mode!\n"));
4187                 goto done;
4188         }
4189
4190         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4191                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4192                 goto done;
4193         }
4194
4195         ZERO_STRUCTP(devmode);
4196
4197         DEBUGADD(8,("loading DEVICEMODE\n"));
4198
4199         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4200                 free_dev_mode( devmode );
4201                 devmode = NULL;
4202         }
4203
4204 done:
4205         free_a_printer(&printer,2);
4206
4207         return devmode;
4208 }
4209
4210 /********************************************************************
4211  * construct_printer_info_2
4212  * fill a printer_info_2 struct
4213  ********************************************************************/
4214
4215 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4216 {
4217         int count;
4218         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4219
4220         print_status_struct status;
4221
4222         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4223                 return False;
4224
4225         count = print_queue_length(snum, &status);
4226
4227         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4228         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4229         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4230         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4231         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4232
4233         if (*ntprinter->info_2->comment == '\0')
4234                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4235         else
4236                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4237
4238         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4239         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4240         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4241         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4242         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4243
4244         printer->attributes = ntprinter->info_2->attributes;
4245
4246         printer->priority = ntprinter->info_2->priority;                                /* priority */
4247         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4248         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4249         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4250         printer->status = nt_printq_status(status.status);                      /* status */
4251         printer->cjobs = count;                                                 /* jobs */
4252         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4253
4254         if ( !(printer->devmode = construct_dev_mode(
4255                        lp_const_servicename(snum))) )
4256                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4257
4258         printer->secdesc = NULL;
4259
4260         if ( ntprinter->info_2->secdesc_buf
4261                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4262         {
4263                 /* don't use talloc_steal() here unless you do a deep steal of all
4264                    the SEC_DESC members */
4265
4266                 printer->secdesc = dup_sec_desc( talloc_tos(),
4267                         ntprinter->info_2->secdesc_buf->sd );
4268         }
4269
4270         free_a_printer(&ntprinter, 2);
4271
4272         return True;
4273 }
4274
4275 /********************************************************************
4276  * construct_printer_info_3
4277  * fill a printer_info_3 struct
4278  ********************************************************************/
4279
4280 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4281 {
4282         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4283         PRINTER_INFO_3 *printer = NULL;
4284
4285         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4286                 return False;
4287
4288         *pp_printer = NULL;
4289         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4290                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4291                 free_a_printer(&ntprinter, 2);
4292                 return False;
4293         }
4294
4295         ZERO_STRUCTP(printer);
4296
4297         /* These are the components of the SD we are returning. */
4298
4299         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4300                 /* don't use talloc_steal() here unless you do a deep steal of all
4301                    the SEC_DESC members */
4302
4303                 printer->secdesc = dup_sec_desc( talloc_tos(),
4304                         ntprinter->info_2->secdesc_buf->sd );
4305         }
4306
4307         free_a_printer(&ntprinter, 2);
4308
4309         *pp_printer = printer;
4310         return True;
4311 }
4312
4313 /********************************************************************
4314  * construct_printer_info_4
4315  * fill a printer_info_4 struct
4316  ********************************************************************/
4317
4318 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4319 {
4320         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4321
4322         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323                 return False;
4324
4325         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4326         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4327         printer->attributes = ntprinter->info_2->attributes;
4328
4329         free_a_printer(&ntprinter, 2);
4330         return True;
4331 }
4332
4333 /********************************************************************
4334  * construct_printer_info_5
4335  * fill a printer_info_5 struct
4336  ********************************************************************/
4337
4338 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4339 {
4340         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4341
4342         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4343                 return False;
4344
4345         init_unistr(&printer->printername, ntprinter->info_2->printername);
4346         init_unistr(&printer->portname, ntprinter->info_2->portname);
4347         printer->attributes = ntprinter->info_2->attributes;
4348
4349         /* these two are not used by NT+ according to MSDN */
4350
4351         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4352         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4353
4354         free_a_printer(&ntprinter, 2);
4355
4356         return True;
4357 }
4358
4359 /********************************************************************
4360  * construct_printer_info_6
4361  * fill a printer_info_6 struct
4362  ********************************************************************/
4363
4364 static bool construct_printer_info_6(Printer_entry *print_hnd,
4365                                      PRINTER_INFO_6 *printer,
4366                                      int snum)
4367 {
4368         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4369         int count;
4370         print_status_struct status;
4371
4372         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4373                                          lp_const_servicename(snum))))
4374                 return False;
4375
4376         count = print_queue_length(snum, &status);
4377
4378         printer->status = nt_printq_status(status.status);
4379
4380         free_a_printer(&ntprinter, 2);
4381
4382         return True;
4383 }
4384
4385 /********************************************************************
4386  * construct_printer_info_7
4387  * fill a printer_info_7 struct
4388  ********************************************************************/
4389
4390 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4391 {
4392         char *guid_str = NULL;
4393         struct GUID guid;
4394
4395         if (is_printer_published(print_hnd, snum, &guid)) {
4396                 if (asprintf(&guid_str, "{%s}",
4397                              GUID_string(talloc_tos(), &guid)) == -1) {
4398                         return false;
4399                 }
4400                 strupper_m(guid_str);
4401                 init_unistr(&printer->guid, guid_str);
4402                 SAFE_FREE(guid_str);
4403                 printer->action = SPOOL_DS_PUBLISH;
4404         } else {
4405                 init_unistr(&printer->guid, "");
4406                 printer->action = SPOOL_DS_UNPUBLISH;
4407         }
4408
4409         return True;
4410 }
4411
4412 /********************************************************************
4413  Spoolss_enumprinters.
4414 ********************************************************************/
4415
4416 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4417 {
4418         int snum;
4419         int i;
4420         int n_services=lp_numservices();
4421         PRINTER_INFO_1 *printers=NULL;
4422         PRINTER_INFO_1 current_prt;
4423         WERROR result = WERR_OK;
4424
4425         DEBUG(4,("enum_all_printers_info_1\n"));
4426
4427         for (snum=0; snum<n_services; snum++) {
4428                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4429                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4430
4431                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4432                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4433                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4434                                         *returned=0;
4435                                         return WERR_NOMEM;
4436                                 }
4437                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4438
4439                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4440                                 (*returned)++;
4441                         }
4442                 }
4443         }
4444
4445         /* check the required size. */
4446         for (i=0; i<*returned; i++)
4447                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4448
4449         if (*needed > offered) {
4450                 result = WERR_INSUFFICIENT_BUFFER;
4451                 goto out;
4452         }
4453
4454         if (!rpcbuf_alloc_size(buffer, *needed)) {
4455                 result = WERR_NOMEM;
4456                 goto out;
4457         }
4458
4459         /* fill the buffer with the structures */
4460         for (i=0; i<*returned; i++)
4461                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4462
4463 out:
4464         /* clear memory */
4465
4466         SAFE_FREE(printers);
4467
4468         if ( !W_ERROR_IS_OK(result) )
4469                 *returned = 0;
4470
4471         return result;
4472 }
4473
4474 /********************************************************************
4475  enum_all_printers_info_1_local.
4476 *********************************************************************/
4477
4478 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4479 {
4480         DEBUG(4,("enum_all_printers_info_1_local\n"));
4481
4482         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4483 }
4484
4485 /********************************************************************
4486  enum_all_printers_info_1_name.
4487 *********************************************************************/
4488
4489 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4490 {
4491         char *s = name;
4492
4493         DEBUG(4,("enum_all_printers_info_1_name\n"));
4494
4495         if ((name[0] == '\\') && (name[1] == '\\'))
4496                 s = name + 2;
4497
4498         if (is_myname_or_ipaddr(s)) {
4499                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4500         }
4501         else
4502                 return WERR_INVALID_NAME;
4503 }
4504
4505 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4506 /********************************************************************
4507  enum_all_printers_info_1_remote.
4508 *********************************************************************/
4509
4510 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4511 {
4512         PRINTER_INFO_1 *printer;
4513         fstring printername;
4514         fstring desc;
4515         fstring comment;
4516         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4517         WERROR result = WERR_OK;
4518
4519         /* JFM: currently it's more a place holder than anything else.
4520          * In the spooler world there is a notion of server registration.
4521          * the print servers are registered on the PDC (in the same domain)
4522          *
4523          * We should have a TDB here. The registration is done thru an
4524          * undocumented RPC call.
4525          */
4526
4527         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4528                 return WERR_NOMEM;
4529
4530         *returned=1;
4531
4532         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4533         slprintf(desc, sizeof(desc)-1,"%s", name);
4534         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4535
4536         init_unistr(&printer->description, desc);
4537         init_unistr(&printer->name, printername);
4538         init_unistr(&printer->comment, comment);
4539         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4540
4541         /* check the required size. */
4542         *needed += spoolss_size_printer_info_1(printer);
4543
4544         if (*needed > offered) {
4545                 result = WERR_INSUFFICIENT_BUFFER;
4546                 goto out;
4547         }
4548
4549         if (!rpcbuf_alloc_size(buffer, *needed)) {
4550                 result = WERR_NOMEM;
4551                 goto out;
4552         }
4553
4554         /* fill the buffer with the structures */
4555         smb_io_printer_info_1("", buffer, printer, 0);
4556
4557 out:
4558         /* clear memory */
4559         SAFE_FREE(printer);
4560
4561         if ( !W_ERROR_IS_OK(result) )
4562                 *returned = 0;
4563
4564         return result;
4565 }
4566
4567 #endif
4568
4569 /********************************************************************
4570  enum_all_printers_info_1_network.
4571 *********************************************************************/
4572
4573 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4574 {
4575         char *s = name;
4576
4577         DEBUG(4,("enum_all_printers_info_1_network\n"));
4578
4579         /* If we respond to a enum_printers level 1 on our name with flags
4580            set to PRINTER_ENUM_REMOTE with a list of printers then these
4581            printers incorrectly appear in the APW browse list.
4582            Specifically the printers for the server appear at the workgroup
4583            level where all the other servers in the domain are
4584            listed. Windows responds to this call with a
4585            WERR_CAN_NOT_COMPLETE so we should do the same. */
4586
4587         if (name[0] == '\\' && name[1] == '\\')
4588                  s = name + 2;
4589
4590         if (is_myname_or_ipaddr(s))
4591                  return WERR_CAN_NOT_COMPLETE;
4592
4593         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4594 }
4595
4596 /********************************************************************
4597  * api_spoolss_enumprinters
4598  *
4599  * called from api_spoolss_enumprinters (see this to understand)
4600  ********************************************************************/
4601
4602 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4603 {
4604         int snum;
4605         int i;
4606         int n_services=lp_numservices();
4607         PRINTER_INFO_2 *printers=NULL;
4608         PRINTER_INFO_2 current_prt;
4609         WERROR result = WERR_OK;
4610
4611         *returned = 0;
4612
4613         for (snum=0; snum<n_services; snum++) {
4614                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4615                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4616
4617                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4618                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4619                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4620                                         *returned = 0;
4621                                         return WERR_NOMEM;
4622                                 }
4623
4624                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4625
4626                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4627
4628                                 (*returned)++;
4629                         }
4630                 }
4631         }
4632
4633         /* check the required size. */
4634         for (i=0; i<*returned; i++)
4635                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4636
4637         if (*needed > offered) {
4638                 result = WERR_INSUFFICIENT_BUFFER;
4639                 goto out;
4640         }
4641
4642         if (!rpcbuf_alloc_size(buffer, *needed)) {
4643                 result = WERR_NOMEM;
4644                 goto out;
4645         }
4646
4647         /* fill the buffer with the structures */
4648         for (i=0; i<*returned; i++)
4649                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4650
4651 out:
4652         /* clear memory */
4653
4654         for (i=0; i<*returned; i++)
4655                 free_devmode(printers[i].devmode);
4656
4657         SAFE_FREE(printers);
4658
4659         if ( !W_ERROR_IS_OK(result) )
4660                 *returned = 0;
4661
4662         return result;
4663 }
4664
4665 /********************************************************************
4666  * handle enumeration of printers at level 1
4667  ********************************************************************/
4668
4669 static WERROR enumprinters_level1( uint32 flags, fstring name,
4670                                  RPC_BUFFER *buffer, uint32 offered,
4671                                  uint32 *needed, uint32 *returned)
4672 {
4673         /* Not all the flags are equals */
4674
4675         if (flags & PRINTER_ENUM_LOCAL)
4676                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4677
4678         if (flags & PRINTER_ENUM_NAME)
4679                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4680
4681 #if 0   /* JERRY - disabled for now */
4682         if (flags & PRINTER_ENUM_REMOTE)
4683                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4684 #endif
4685
4686         if (flags & PRINTER_ENUM_NETWORK)
4687                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4688
4689         return WERR_OK; /* NT4sp5 does that */
4690 }
4691
4692 /********************************************************************
4693  * handle enumeration of printers at level 2
4694  ********************************************************************/
4695
4696 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4697                                  RPC_BUFFER *buffer, uint32 offered,
4698                                  uint32 *needed, uint32 *returned)
4699 {
4700         if (flags & PRINTER_ENUM_LOCAL) {
4701                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4702         }
4703
4704         if (flags & PRINTER_ENUM_NAME) {
4705                 if (is_myname_or_ipaddr(canon_servername(servername)))
4706                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4707                 else
4708                         return WERR_INVALID_NAME;
4709         }
4710
4711         if (flags & PRINTER_ENUM_REMOTE)
4712                 return WERR_UNKNOWN_LEVEL;
4713
4714         return WERR_OK;
4715 }
4716
4717 /********************************************************************
4718  * handle enumeration of printers at level 5
4719  ********************************************************************/
4720
4721 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4722                                  RPC_BUFFER *buffer, uint32 offered,
4723                                  uint32 *needed, uint32 *returned)
4724 {
4725 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4726         return WERR_OK;
4727 }
4728
4729 /********************************************************************
4730  * api_spoolss_enumprinters
4731  *
4732  * called from api_spoolss_enumprinters (see this to understand)
4733  ********************************************************************/
4734
4735 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4736 {
4737         uint32 flags = q_u->flags;
4738         UNISTR2 *servername = &q_u->servername;
4739         uint32 level = q_u->level;
4740         RPC_BUFFER *buffer = NULL;
4741         uint32 offered = q_u->offered;
4742         uint32 *needed = &r_u->needed;
4743         uint32 *returned = &r_u->returned;
4744
4745         fstring name;
4746
4747         /* that's an [in out] buffer */
4748
4749         if (!q_u->buffer && (offered!=0)) {
4750                 return WERR_INVALID_PARAM;
4751         }
4752
4753         if (offered > MAX_RPC_DATA_SIZE) {
4754                 return WERR_INVALID_PARAM;
4755         }
4756
4757         rpcbuf_move(q_u->buffer, &r_u->buffer);
4758         buffer = r_u->buffer;
4759
4760         DEBUG(4,("_spoolss_enumprinters\n"));
4761
4762         *needed=0;
4763         *returned=0;
4764
4765         /*
4766          * Level 1:
4767          *          flags==PRINTER_ENUM_NAME
4768          *           if name=="" then enumerates all printers
4769          *           if name!="" then enumerate the printer
4770          *          flags==PRINTER_ENUM_REMOTE
4771          *          name is NULL, enumerate printers
4772          * Level 2: name!="" enumerates printers, name can't be NULL
4773          * Level 3: doesn't exist
4774          * Level 4: does a local registry lookup
4775          * Level 5: same as Level 2
4776          */
4777
4778         unistr2_to_ascii(name, servername, sizeof(name));
4779         strupper_m(name);
4780
4781         switch (level) {
4782         case 1:
4783                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4784         case 2:
4785                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4786         case 5:
4787                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4788         case 3:
4789         case 4:
4790                 break;
4791         }
4792         return WERR_UNKNOWN_LEVEL;
4793 }
4794
4795 /****************************************************************************
4796 ****************************************************************************/
4797
4798 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4799 {
4800         PRINTER_INFO_0 *printer=NULL;
4801         WERROR result = WERR_OK;
4802
4803         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4804                 return WERR_NOMEM;
4805
4806         construct_printer_info_0(print_hnd, printer, snum);
4807
4808         /* check the required size. */
4809         *needed += spoolss_size_printer_info_0(printer);
4810
4811         if (*needed > offered) {
4812                 result = WERR_INSUFFICIENT_BUFFER;
4813                 goto out;
4814         }
4815
4816         if (!rpcbuf_alloc_size(buffer, *needed)) {
4817                 result = WERR_NOMEM;
4818                 goto out;
4819         }
4820
4821         /* fill the buffer with the structures */
4822         smb_io_printer_info_0("", buffer, printer, 0);
4823
4824 out:
4825         /* clear memory */
4826
4827         SAFE_FREE(printer);
4828
4829         return result;
4830 }
4831
4832 /****************************************************************************
4833 ****************************************************************************/
4834
4835 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4836 {
4837         PRINTER_INFO_1 *printer=NULL;
4838         WERROR result = WERR_OK;
4839
4840         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4841                 return WERR_NOMEM;
4842
4843         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4844
4845         /* check the required size. */
4846         *needed += spoolss_size_printer_info_1(printer);
4847
4848         if (*needed > offered) {
4849                 result = WERR_INSUFFICIENT_BUFFER;
4850                 goto out;
4851         }
4852
4853         if (!rpcbuf_alloc_size(buffer, *needed)) {
4854                 result = WERR_NOMEM;
4855                 goto out;
4856         }
4857
4858         /* fill the buffer with the structures */
4859         smb_io_printer_info_1("", buffer, printer, 0);
4860
4861 out:
4862         /* clear memory */
4863         SAFE_FREE(printer);
4864
4865         return result;
4866 }
4867
4868 /****************************************************************************
4869 ****************************************************************************/
4870
4871 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 {
4873         PRINTER_INFO_2 *printer=NULL;
4874         WERROR result = WERR_OK;
4875
4876         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4877                 return WERR_NOMEM;
4878
4879         construct_printer_info_2(print_hnd, printer, snum);
4880
4881         /* check the required size. */
4882         *needed += spoolss_size_printer_info_2(printer);
4883
4884         if (*needed > offered) {
4885                 result = WERR_INSUFFICIENT_BUFFER;
4886                 goto out;
4887         }
4888
4889         if (!rpcbuf_alloc_size(buffer, *needed)) {
4890                 result = WERR_NOMEM;
4891                 goto out;
4892         }
4893
4894         /* fill the buffer with the structures */
4895         if (!smb_io_printer_info_2("", buffer, printer, 0))
4896                 result = WERR_NOMEM;
4897
4898 out:
4899         /* clear memory */
4900         free_printer_info_2(printer);
4901
4902         return result;
4903 }
4904
4905 /****************************************************************************
4906 ****************************************************************************/
4907
4908 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4909 {
4910         PRINTER_INFO_3 *printer=NULL;
4911         WERROR result = WERR_OK;
4912
4913         if (!construct_printer_info_3(print_hnd, &printer, snum))
4914                 return WERR_NOMEM;
4915
4916         /* check the required size. */
4917         *needed += spoolss_size_printer_info_3(printer);
4918
4919         if (*needed > offered) {
4920                 result = WERR_INSUFFICIENT_BUFFER;
4921                 goto out;
4922         }
4923
4924         if (!rpcbuf_alloc_size(buffer, *needed)) {
4925                 result = WERR_NOMEM;
4926                 goto out;
4927         }
4928
4929         /* fill the buffer with the structures */
4930         smb_io_printer_info_3("", buffer, printer, 0);
4931
4932 out:
4933         /* clear memory */
4934         free_printer_info_3(printer);
4935
4936         return result;
4937 }
4938
4939 /****************************************************************************
4940 ****************************************************************************/
4941
4942 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4943 {
4944         PRINTER_INFO_4 *printer=NULL;
4945         WERROR result = WERR_OK;
4946
4947         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4948                 return WERR_NOMEM;
4949
4950         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4951                 SAFE_FREE(printer);
4952                 return WERR_NOMEM;
4953         }
4954
4955         /* check the required size. */
4956         *needed += spoolss_size_printer_info_4(printer);
4957
4958         if (*needed > offered) {
4959                 result = WERR_INSUFFICIENT_BUFFER;
4960                 goto out;
4961         }
4962
4963         if (!rpcbuf_alloc_size(buffer, *needed)) {
4964                 result = WERR_NOMEM;
4965                 goto out;
4966         }
4967
4968         /* fill the buffer with the structures */
4969         smb_io_printer_info_4("", buffer, printer, 0);
4970
4971 out:
4972         /* clear memory */
4973         free_printer_info_4(printer);
4974
4975         return result;
4976 }
4977
4978 /****************************************************************************
4979 ****************************************************************************/
4980
4981 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4982 {
4983         PRINTER_INFO_5 *printer=NULL;
4984         WERROR result = WERR_OK;
4985
4986         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4987                 return WERR_NOMEM;
4988
4989         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4990                 free_printer_info_5(printer);
4991                 return WERR_NOMEM;
4992         }
4993
4994         /* check the required size. */
4995         *needed += spoolss_size_printer_info_5(printer);
4996
4997         if (*needed > offered) {
4998                 result = WERR_INSUFFICIENT_BUFFER;
4999                 goto out;
5000         }
5001
5002         if (!rpcbuf_alloc_size(buffer, *needed)) {
5003                 result = WERR_NOMEM;
5004                 goto out;
5005         }
5006
5007         /* fill the buffer with the structures */
5008         smb_io_printer_info_5("", buffer, printer, 0);
5009
5010 out:
5011         /* clear memory */
5012         free_printer_info_5(printer);
5013
5014         return result;
5015 }
5016
5017 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5018                                  int snum,
5019                                  RPC_BUFFER *buffer, uint32 offered,
5020                                  uint32 *needed)
5021 {
5022         PRINTER_INFO_6 *printer;
5023         WERROR result = WERR_OK;
5024
5025         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5026                 return WERR_NOMEM;
5027         }
5028
5029         if (!construct_printer_info_6(print_hnd, printer, snum)) {
5030                 free_printer_info_6(printer);
5031                 return WERR_NOMEM;
5032         }
5033
5034         /* check the required size. */
5035         *needed += spoolss_size_printer_info_6(printer);
5036
5037         if (*needed > offered) {
5038                 result = WERR_INSUFFICIENT_BUFFER;
5039                 goto out;
5040         }
5041
5042         if (!rpcbuf_alloc_size(buffer, *needed)) {
5043                 result = WERR_NOMEM;
5044                 goto out;
5045         }
5046
5047         /* fill the buffer with the structures */
5048         smb_io_printer_info_6("", buffer, printer, 0);
5049
5050 out:
5051         /* clear memory */
5052         free_printer_info_6(printer);
5053
5054         return result;
5055 }
5056
5057 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5058 {
5059         PRINTER_INFO_7 *printer=NULL;
5060         WERROR result = WERR_OK;
5061
5062         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5063                 return WERR_NOMEM;
5064
5065         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5066                 result = WERR_NOMEM;
5067                 goto out;
5068         }
5069
5070         /* check the required size. */
5071         *needed += spoolss_size_printer_info_7(printer);
5072
5073         if (*needed > offered) {
5074                 result = WERR_INSUFFICIENT_BUFFER;
5075                 goto out;
5076         }
5077
5078         if (!rpcbuf_alloc_size(buffer, *needed)) {
5079                 result = WERR_NOMEM;
5080                 goto out;
5081
5082         }
5083
5084         /* fill the buffer with the structures */
5085         smb_io_printer_info_7("", buffer, printer, 0);
5086
5087 out:
5088         /* clear memory */
5089         free_printer_info_7(printer);
5090
5091         return result;
5092 }
5093
5094 /****************************************************************************
5095 ****************************************************************************/
5096
5097 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5098 {
5099         POLICY_HND *handle = &q_u->handle;
5100         uint32 level = q_u->level;
5101         RPC_BUFFER *buffer = NULL;
5102         uint32 offered = q_u->offered;
5103         uint32 *needed = &r_u->needed;
5104         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5105
5106         int snum;
5107
5108         /* that's an [in out] buffer */
5109
5110         if (!q_u->buffer && (offered!=0)) {
5111                 return WERR_INVALID_PARAM;
5112         }
5113
5114         if (offered > MAX_RPC_DATA_SIZE) {
5115                 return WERR_INVALID_PARAM;
5116         }
5117
5118         rpcbuf_move(q_u->buffer, &r_u->buffer);
5119         buffer = r_u->buffer;
5120
5121         *needed=0;
5122
5123         if (!get_printer_snum(p, handle, &snum, NULL))
5124                 return WERR_BADFID;
5125
5126         switch (level) {
5127         case 0:
5128                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5129         case 1:
5130                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5131         case 2:
5132                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5133         case 3:
5134                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5135         case 4:
5136                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5137         case 5:
5138                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5139         case 6:
5140                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5141         case 7:
5142                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5143         }
5144         return WERR_UNKNOWN_LEVEL;
5145 }
5146
5147 /********************************************************************
5148  * fill a DRIVER_INFO_1 struct
5149  ********************************************************************/
5150
5151 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5152 {
5153         init_unistr( &info->name, driver.info_3->name);
5154 }
5155
5156 /********************************************************************
5157  * construct_printer_driver_info_1
5158  ********************************************************************/
5159
5160 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5161 {
5162         NT_PRINTER_INFO_LEVEL *printer = NULL;
5163         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5164
5165         ZERO_STRUCT(driver);
5166
5167         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5168                 return WERR_INVALID_PRINTER_NAME;
5169
5170         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5171                 free_a_printer(&printer, 2);
5172                 return WERR_UNKNOWN_PRINTER_DRIVER;
5173         }
5174
5175         fill_printer_driver_info_1(info, driver, servername, architecture);
5176
5177         free_a_printer(&printer,2);
5178
5179         return WERR_OK;
5180 }
5181
5182 /********************************************************************
5183  * construct_printer_driver_info_2
5184  * fill a printer_info_2 struct
5185  ********************************************************************/
5186
5187 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5188 {
5189         TALLOC_CTX *ctx = talloc_tos();
5190         char *temp = NULL;
5191         const char *cservername = canon_servername(servername);
5192
5193         info->version=driver.info_3->cversion;
5194
5195         init_unistr( &info->name, driver.info_3->name );
5196         init_unistr( &info->architecture, driver.info_3->environment );
5197
5198         if (strlen(driver.info_3->driverpath)) {
5199                 temp = talloc_asprintf(ctx,
5200                                 "\\\\%s%s",
5201                                 cservername,
5202                                 driver.info_3->driverpath);
5203                 init_unistr( &info->driverpath, temp );
5204         } else {
5205                 init_unistr( &info->driverpath, "" );
5206         }
5207
5208         TALLOC_FREE(temp);
5209         if (strlen(driver.info_3->datafile)) {
5210                 temp = talloc_asprintf(ctx,
5211                                 "\\\\%s%s",
5212                                 cservername,
5213                                 driver.info_3->datafile);
5214                 init_unistr( &info->datafile, temp );
5215         } else
5216                 init_unistr( &info->datafile, "" );
5217
5218         TALLOC_FREE(temp);
5219         if (strlen(driver.info_3->configfile)) {
5220                 temp = talloc_asprintf(ctx,
5221                                 "\\\\%s%s",
5222                                 cservername,
5223                                 driver.info_3->configfile);
5224                 init_unistr( &info->configfile, temp );
5225         } else
5226                 init_unistr( &info->configfile, "" );
5227 }
5228
5229 /********************************************************************
5230  * construct_printer_driver_info_2
5231  * fill a printer_info_2 struct
5232  ********************************************************************/
5233
5234 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5235 {
5236         NT_PRINTER_INFO_LEVEL *printer = NULL;
5237         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5238
5239         ZERO_STRUCT(printer);
5240         ZERO_STRUCT(driver);
5241
5242         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5243                 return WERR_INVALID_PRINTER_NAME;
5244
5245         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5246                 free_a_printer(&printer, 2);
5247                 return WERR_UNKNOWN_PRINTER_DRIVER;
5248         }
5249
5250         fill_printer_driver_info_2(info, driver, servername);
5251
5252         free_a_printer(&printer,2);
5253
5254         return WERR_OK;
5255 }
5256
5257 /********************************************************************
5258  * copy a strings array and convert to UNICODE
5259  *
5260  * convert an array of ascii string to a UNICODE string
5261  ********************************************************************/
5262
5263 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5264 {
5265         int i=0;
5266         int j=0;
5267         const char *v;
5268         char *line = NULL;
5269         TALLOC_CTX *ctx = talloc_tos();
5270
5271         DEBUG(6,("init_unistr_array\n"));
5272         *uni_array=NULL;
5273
5274         while (true) {
5275                 if ( !char_array ) {
5276                         v = "";
5277                 } else {
5278                         v = char_array[i];
5279                         if (!v)
5280                                 v = ""; /* hack to handle null lists */
5281                 }
5282
5283                 /* hack to allow this to be used in places other than when generating
5284                    the list of dependent files */
5285
5286                 TALLOC_FREE(line);
5287                 if ( servername ) {
5288                         line = talloc_asprintf(ctx,
5289                                         "\\\\%s%s",
5290                                         canon_servername(servername),
5291                                         v);
5292                 } else {
5293                         line = talloc_strdup(ctx, v);
5294                 }
5295
5296                 if (!line) {
5297                         SAFE_FREE(*uni_array);
5298                         return 0;
5299                 }
5300                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5301
5302                 /* add one extra unit16 for the second terminating NULL */
5303
5304                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5305                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5306                         return 0;
5307                 }
5308
5309                 if ( !strlen(v) )
5310                         break;
5311
5312                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5313                 i++;
5314         }
5315
5316         if (*uni_array) {
5317                 /* special case for ""; we need to add both NULL's here */
5318                 if (!j)
5319                         (*uni_array)[j++]=0x0000;
5320                 (*uni_array)[j]=0x0000;
5321         }
5322
5323         DEBUGADD(6,("last one:done\n"));
5324
5325         /* return size of array in uint16's */
5326
5327         return j+1;
5328 }
5329
5330 /********************************************************************
5331  * construct_printer_info_3
5332  * fill a printer_info_3 struct
5333  ********************************************************************/
5334
5335 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5336 {
5337         char *temp = NULL;
5338         TALLOC_CTX *ctx = talloc_tos();
5339         const char *cservername = canon_servername(servername);
5340
5341         ZERO_STRUCTP(info);
5342
5343         info->version=driver.info_3->cversion;
5344
5345         init_unistr( &info->name, driver.info_3->name );
5346         init_unistr( &info->architecture, driver.info_3->environment );
5347
5348         if (strlen(driver.info_3->driverpath)) {
5349                 temp = talloc_asprintf(ctx,
5350                                 "\\\\%s%s",
5351                                 cservername,
5352                                 driver.info_3->driverpath);
5353                 init_unistr( &info->driverpath, temp );
5354         } else
5355                 init_unistr( &info->driverpath, "" );
5356
5357         TALLOC_FREE(temp);
5358         if (strlen(driver.info_3->datafile)) {
5359                 temp = talloc_asprintf(ctx,
5360                                 "\\\\%s%s",
5361                                 cservername,
5362                                 driver.info_3->datafile);
5363                 init_unistr( &info->datafile, temp );
5364         } else
5365                 init_unistr( &info->datafile, "" );
5366
5367         TALLOC_FREE(temp);
5368         if (strlen(driver.info_3->configfile)) {
5369                 temp = talloc_asprintf(ctx,
5370                                 "\\\\%s%s",
5371                                 cservername,
5372                                 driver.info_3->configfile);
5373                 init_unistr( &info->configfile, temp );
5374         } else
5375                 init_unistr( &info->configfile, "" );
5376
5377         TALLOC_FREE(temp);
5378         if (strlen(driver.info_3->helpfile)) {
5379                 temp = talloc_asprintf(ctx,
5380                                 "\\\\%s%s",
5381                                 cservername,
5382                                 driver.info_3->helpfile);
5383                 init_unistr( &info->helpfile, temp );
5384         } else
5385                 init_unistr( &info->helpfile, "" );
5386
5387         TALLOC_FREE(temp);
5388         init_unistr( &info->monitorname, driver.info_3->monitorname );
5389         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5390
5391         info->dependentfiles=NULL;
5392         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5393 }
5394
5395 /********************************************************************
5396  * construct_printer_info_3
5397  * fill a printer_info_3 struct
5398  ********************************************************************/
5399
5400 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5401 {
5402         NT_PRINTER_INFO_LEVEL *printer = NULL;
5403         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5404         WERROR status;
5405         ZERO_STRUCT(driver);
5406
5407         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5408         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5409         if (!W_ERROR_IS_OK(status))
5410                 return WERR_INVALID_PRINTER_NAME;
5411
5412         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5413         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5414
5415 #if 0   /* JERRY */
5416
5417         /*
5418          * I put this code in during testing.  Helpful when commenting out the
5419          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5420          * as win2k always queries the driver using an infor level of 6.
5421          * I've left it in (but ifdef'd out) because I'll probably
5422          * use it in experimentation again in the future.   --jerry 22/01/2002
5423          */
5424
5425         if (!W_ERROR_IS_OK(status)) {
5426                 /*
5427                  * Is this a W2k client ?
5428                  */
5429                 if (version == 3) {
5430                         /* Yes - try again with a WinNT driver. */
5431                         version = 2;
5432                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5433                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5434                 }
5435 #endif
5436
5437                 if (!W_ERROR_IS_OK(status)) {
5438                         free_a_printer(&printer,2);
5439                         return WERR_UNKNOWN_PRINTER_DRIVER;
5440                 }
5441
5442 #if 0   /* JERRY */
5443         }
5444 #endif
5445
5446
5447         fill_printer_driver_info_3(info, driver, servername);
5448
5449         free_a_printer(&printer,2);
5450
5451         return WERR_OK;
5452 }
5453
5454 /********************************************************************
5455  * construct_printer_info_6
5456  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5457  ********************************************************************/
5458
5459 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5460 {
5461         char *temp = NULL;
5462         fstring nullstr;
5463         TALLOC_CTX *ctx = talloc_tos();
5464         const char *cservername = canon_servername(servername);
5465
5466         ZERO_STRUCTP(info);
5467         memset(&nullstr, '\0', sizeof(fstring));
5468
5469         info->version=driver.info_3->cversion;
5470
5471         init_unistr( &info->name, driver.info_3->name );
5472         init_unistr( &info->architecture, driver.info_3->environment );
5473
5474         if (strlen(driver.info_3->driverpath)) {
5475                 temp = talloc_asprintf(ctx,
5476                                 "\\\\%s%s",
5477                                 cservername,
5478                                 driver.info_3->driverpath);
5479                 init_unistr( &info->driverpath, temp );
5480         } else
5481                 init_unistr( &info->driverpath, "" );
5482
5483         TALLOC_FREE(temp);
5484         if (strlen(driver.info_3->datafile)) {
5485                 temp = talloc_asprintf(ctx,
5486                                 "\\\\%s%s",
5487                                 cservername,
5488                                 driver.info_3->datafile);
5489                 init_unistr( &info->datafile, temp );
5490         } else
5491                 init_unistr( &info->datafile, "" );
5492
5493         TALLOC_FREE(temp);
5494         if (strlen(driver.info_3->configfile)) {
5495                 temp = talloc_asprintf(ctx,
5496                                 "\\\\%s%s",
5497                                 cservername,
5498                                 driver.info_3->configfile);
5499                 init_unistr( &info->configfile, temp );
5500         } else
5501                 init_unistr( &info->configfile, "" );
5502
5503         TALLOC_FREE(temp);
5504         if (strlen(driver.info_3->helpfile)) {
5505                 temp = talloc_asprintf(ctx,
5506                                 "\\\\%s%s",
5507                                 cservername,
5508                                 driver.info_3->helpfile);
5509                 init_unistr( &info->helpfile, temp );
5510         } else
5511                 init_unistr( &info->helpfile, "" );
5512
5513         TALLOC_FREE(temp);
5514         init_unistr( &info->monitorname, driver.info_3->monitorname );
5515         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5516
5517         info->dependentfiles = NULL;
5518         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5519
5520         info->previousdrivernames=NULL;
5521         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5522
5523         info->driver_date=0;
5524
5525         info->padding=0;
5526         info->driver_version_low=0;
5527         info->driver_version_high=0;
5528
5529         init_unistr( &info->mfgname, "");
5530         init_unistr( &info->oem_url, "");
5531         init_unistr( &info->hardware_id, "");
5532         init_unistr( &info->provider, "");
5533 }
5534
5535 /********************************************************************
5536  * construct_printer_info_6
5537  * fill a printer_info_6 struct
5538  ********************************************************************/
5539
5540 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5541               const char *servername, fstring architecture, uint32 version)
5542 {
5543         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5544         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5545         WERROR                          status;
5546
5547         ZERO_STRUCT(driver);
5548
5549         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5550
5551         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5552
5553         if (!W_ERROR_IS_OK(status))
5554                 return WERR_INVALID_PRINTER_NAME;
5555
5556         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5557
5558         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5559
5560         if (!W_ERROR_IS_OK(status))
5561         {
5562                 /*
5563                  * Is this a W2k client ?
5564                  */
5565
5566                 if (version < 3) {
5567                         free_a_printer(&printer,2);
5568                         return WERR_UNKNOWN_PRINTER_DRIVER;
5569                 }
5570
5571                 /* Yes - try again with a WinNT driver. */
5572                 version = 2;
5573                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5574                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5575                 if (!W_ERROR_IS_OK(status)) {
5576                         free_a_printer(&printer,2);
5577                         return WERR_UNKNOWN_PRINTER_DRIVER;
5578                 }
5579         }
5580
5581         fill_printer_driver_info_6(info, driver, servername);
5582
5583         free_a_printer(&printer,2);
5584         free_a_printer_driver(driver, 3);
5585
5586         return WERR_OK;
5587 }
5588
5589 /****************************************************************************
5590 ****************************************************************************/
5591
5592 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5593 {
5594         SAFE_FREE(info->dependentfiles);
5595 }
5596
5597 /****************************************************************************
5598 ****************************************************************************/
5599
5600 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5601 {
5602         SAFE_FREE(info->dependentfiles);
5603 }
5604
5605 /****************************************************************************
5606 ****************************************************************************/
5607
5608 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5609 {
5610         DRIVER_INFO_1 *info=NULL;
5611         WERROR result;
5612
5613         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5614                 return WERR_NOMEM;
5615
5616         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5617         if (!W_ERROR_IS_OK(result))
5618                 goto out;
5619
5620         /* check the required size. */
5621         *needed += spoolss_size_printer_driver_info_1(info);
5622
5623         if (*needed > offered) {
5624                 result = WERR_INSUFFICIENT_BUFFER;
5625                 goto out;
5626         }
5627
5628         if (!rpcbuf_alloc_size(buffer, *needed)) {
5629                 result = WERR_NOMEM;
5630                 goto out;
5631         }
5632
5633         /* fill the buffer with the structures */
5634         smb_io_printer_driver_info_1("", buffer, info, 0);
5635
5636 out:
5637         /* clear memory */
5638         SAFE_FREE(info);
5639
5640         return result;
5641 }
5642
5643 /****************************************************************************
5644 ****************************************************************************/
5645
5646 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5647 {
5648         DRIVER_INFO_2 *info=NULL;
5649         WERROR result;
5650
5651         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5652                 return WERR_NOMEM;
5653
5654         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5655         if (!W_ERROR_IS_OK(result))
5656                 goto out;
5657
5658         /* check the required size. */
5659         *needed += spoolss_size_printer_driver_info_2(info);
5660
5661         if (*needed > offered) {
5662                 result = WERR_INSUFFICIENT_BUFFER;
5663                 goto out;
5664         }
5665
5666         if (!rpcbuf_alloc_size(buffer, *needed)) {
5667                 result = WERR_NOMEM;
5668                 goto out;
5669         }
5670
5671         /* fill the buffer with the structures */
5672         smb_io_printer_driver_info_2("", buffer, info, 0);
5673
5674 out:
5675         /* clear memory */
5676         SAFE_FREE(info);
5677
5678         return result;
5679 }
5680
5681 /****************************************************************************
5682 ****************************************************************************/
5683
5684 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5685 {
5686         DRIVER_INFO_3 info;
5687         WERROR result;
5688
5689         ZERO_STRUCT(info);
5690
5691         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5692         if (!W_ERROR_IS_OK(result))
5693                 goto out;
5694
5695         /* check the required size. */
5696         *needed += spoolss_size_printer_driver_info_3(&info);
5697
5698         if (*needed > offered) {
5699                 result = WERR_INSUFFICIENT_BUFFER;
5700                 goto out;
5701         }
5702
5703         if (!rpcbuf_alloc_size(buffer, *needed)) {
5704                 result = WERR_NOMEM;
5705                 goto out;
5706         }
5707
5708         /* fill the buffer with the structures */
5709         smb_io_printer_driver_info_3("", buffer, &info, 0);
5710
5711 out:
5712         free_printer_driver_info_3(&info);
5713
5714         return result;
5715 }
5716
5717 /****************************************************************************
5718 ****************************************************************************/
5719
5720 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5721 {
5722         DRIVER_INFO_6 info;
5723         WERROR result;
5724
5725         ZERO_STRUCT(info);
5726
5727         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5728         if (!W_ERROR_IS_OK(result))
5729                 goto out;
5730
5731         /* check the required size. */
5732         *needed += spoolss_size_printer_driver_info_6(&info);
5733
5734         if (*needed > offered) {
5735                 result = WERR_INSUFFICIENT_BUFFER;
5736                 goto out;
5737         }
5738
5739         if (!rpcbuf_alloc_size(buffer, *needed)) {
5740                 result = WERR_NOMEM;
5741                 goto out;
5742         }
5743
5744         /* fill the buffer with the structures */
5745         smb_io_printer_driver_info_6("", buffer, &info, 0);
5746
5747 out:
5748         free_printer_driver_info_6(&info);
5749
5750         return result;
5751 }
5752
5753 /****************************************************************************
5754 ****************************************************************************/
5755
5756 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5757 {
5758         POLICY_HND *handle = &q_u->handle;
5759         UNISTR2 *uni_arch = &q_u->architecture;
5760         uint32 level = q_u->level;
5761         uint32 clientmajorversion = q_u->clientmajorversion;
5762         RPC_BUFFER *buffer = NULL;
5763         uint32 offered = q_u->offered;
5764         uint32 *needed = &r_u->needed;
5765         uint32 *servermajorversion = &r_u->servermajorversion;
5766         uint32 *serverminorversion = &r_u->serverminorversion;
5767         Printer_entry *printer;
5768
5769         fstring servername;
5770         fstring architecture;
5771         int snum;
5772
5773         /* that's an [in out] buffer */
5774
5775         if (!q_u->buffer && (offered!=0)) {
5776                 return WERR_INVALID_PARAM;
5777         }
5778
5779         if (offered > MAX_RPC_DATA_SIZE) {
5780                 return WERR_INVALID_PARAM;
5781         }
5782
5783         rpcbuf_move(q_u->buffer, &r_u->buffer);
5784         buffer = r_u->buffer;
5785
5786         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5787
5788         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5789                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5790                 return WERR_INVALID_PRINTER_NAME;
5791         }
5792
5793         *needed = 0;
5794         *servermajorversion = 0;
5795         *serverminorversion = 0;
5796
5797         fstrcpy(servername, get_server_name( printer ));
5798         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5799
5800         if (!get_printer_snum(p, handle, &snum, NULL))
5801                 return WERR_BADFID;
5802
5803         switch (level) {
5804         case 1:
5805                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5806         case 2:
5807                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5808         case 3:
5809                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5810         case 6:
5811                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5812 #if 0   /* JERRY */
5813         case 101:
5814                 /* apparently this call is the equivalent of
5815                    EnumPrinterDataEx() for the DsDriver key */
5816                 break;
5817 #endif
5818         }
5819
5820         return WERR_UNKNOWN_LEVEL;
5821 }
5822
5823
5824 /****************************************************************
5825  _spoolss_StartPagePrinter
5826 ****************************************************************/
5827
5828 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5829                                  struct spoolss_StartPagePrinter *r)
5830 {
5831         POLICY_HND *handle = r->in.handle;
5832
5833         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5834
5835         if (!Printer) {
5836                 DEBUG(3,("_spoolss_StartPagePrinter: "
5837                         "Error in startpageprinter printer handle\n"));
5838                 return WERR_BADFID;
5839         }
5840
5841         Printer->page_started=True;
5842         return WERR_OK;
5843 }
5844
5845 /****************************************************************
5846  _spoolss_EndPagePrinter
5847 ****************************************************************/
5848
5849 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5850                                struct spoolss_EndPagePrinter *r)
5851 {
5852         POLICY_HND *handle = r->in.handle;
5853         int snum;
5854
5855         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5856
5857         if (!Printer) {
5858                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5859                         OUR_HANDLE(handle)));
5860                 return WERR_BADFID;
5861         }
5862
5863         if (!get_printer_snum(p, handle, &snum, NULL))
5864                 return WERR_BADFID;
5865
5866         Printer->page_started=False;
5867         print_job_endpage(snum, Printer->jobid);
5868
5869         return WERR_OK;
5870 }
5871
5872 /****************************************************************
5873  _spoolss_StartDocPrinter
5874 ****************************************************************/
5875
5876 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5877                                 struct spoolss_StartDocPrinter *r)
5878 {
5879         POLICY_HND *handle = r->in.handle;
5880         uint32_t *jobid = r->out.job_id;
5881         struct spoolss_DocumentInfo1 *info_1;
5882         int snum;
5883         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5884
5885         if (!Printer) {
5886                 DEBUG(2,("_spoolss_StartDocPrinter: "
5887                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5888                 return WERR_BADFID;
5889         }
5890
5891         if (r->in.level != 1) {
5892                 return WERR_UNKNOWN_LEVEL;
5893         }
5894
5895         info_1 = r->in.info.info1;
5896
5897         /*
5898          * a nice thing with NT is it doesn't listen to what you tell it.
5899          * when asked to send _only_ RAW datas, it tries to send datas
5900          * in EMF format.
5901          *
5902          * So I add checks like in NT Server ...
5903          */
5904
5905         if (info_1->datatype) {
5906                 if (strcmp(info_1->datatype, "RAW") != 0) {
5907                         (*jobid)=0;
5908                         return WERR_INVALID_DATATYPE;
5909                 }
5910         }
5911
5912         /* get the share number of the printer */
5913         if (!get_printer_snum(p, handle, &snum, NULL)) {
5914                 return WERR_BADFID;
5915         }
5916
5917         Printer->jobid = print_job_start(p->server_info, snum,
5918                                          CONST_DISCARD(char *,info_1->document_name),
5919                                          Printer->nt_devmode);
5920
5921         /* An error occured in print_job_start() so return an appropriate
5922            NT error code. */
5923
5924         if (Printer->jobid == -1) {
5925                 return map_werror_from_unix(errno);
5926         }
5927
5928         Printer->document_started=True;
5929         (*jobid) = Printer->jobid;
5930
5931         return WERR_OK;
5932 }
5933
5934 /****************************************************************
5935  _spoolss_EndDocPrinter
5936 ****************************************************************/
5937
5938 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5939                               struct spoolss_EndDocPrinter *r)
5940 {
5941         POLICY_HND *handle = r->in.handle;
5942
5943         return _spoolss_enddocprinter_internal(p, handle);
5944 }
5945
5946 /****************************************************************
5947  _spoolss_WritePrinter
5948 ****************************************************************/
5949
5950 WERROR _spoolss_WritePrinter(pipes_struct *p,
5951                              struct spoolss_WritePrinter *r)
5952 {
5953         POLICY_HND *handle = r->in.handle;
5954         uint32 buffer_size = r->in._data_size;
5955         uint8 *buffer = r->in.data.data;
5956         uint32 *buffer_written = &r->in._data_size;
5957         int snum;
5958         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5959
5960         if (!Printer) {
5961                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5962                         OUR_HANDLE(handle)));
5963                 *r->out.num_written = r->in._data_size;
5964                 return WERR_BADFID;
5965         }
5966
5967         if (!get_printer_snum(p, handle, &snum, NULL))
5968                 return WERR_BADFID;
5969
5970         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5971                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5972         if (*buffer_written == (uint32)-1) {
5973                 *r->out.num_written = 0;
5974                 if (errno == ENOSPC)
5975                         return WERR_NO_SPOOL_SPACE;
5976                 else
5977                         return WERR_ACCESS_DENIED;
5978         }
5979
5980         *r->out.num_written = r->in._data_size;
5981
5982         return WERR_OK;
5983 }
5984
5985 /********************************************************************
5986  * api_spoolss_getprinter
5987  * called from the spoolss dispatcher
5988  *
5989  ********************************************************************/
5990
5991 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5992                               pipes_struct *p)
5993 {
5994         int snum;
5995         WERROR errcode = WERR_BADFUNC;
5996         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5997
5998         if (!Printer) {
5999                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6000                 return WERR_BADFID;
6001         }
6002
6003         if (!get_printer_snum(p, handle, &snum, NULL))
6004                 return WERR_BADFID;
6005
6006         switch (command) {
6007         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6008                 if (print_queue_pause(p->server_info, snum, &errcode)) {
6009                         errcode = WERR_OK;
6010                 }
6011                 break;
6012         case SPOOLSS_PRINTER_CONTROL_RESUME:
6013         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6014                 if (print_queue_resume(p->server_info, snum, &errcode)) {
6015                         errcode = WERR_OK;
6016                 }
6017                 break;
6018         case SPOOLSS_PRINTER_CONTROL_PURGE:
6019                 if (print_queue_purge(p->server_info, snum, &errcode)) {
6020                         errcode = WERR_OK;
6021                 }
6022                 break;
6023         default:
6024                 return WERR_UNKNOWN_LEVEL;
6025         }
6026
6027         return errcode;
6028 }
6029
6030
6031 /****************************************************************
6032  _spoolss_AbortPrinter
6033  * From MSDN: "Deletes printer's spool file if printer is configured
6034  * for spooling"
6035 ****************************************************************/
6036
6037 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6038                              struct spoolss_AbortPrinter *r)
6039 {
6040         POLICY_HND      *handle = r->in.handle;
6041         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6042         int             snum;
6043         WERROR          errcode = WERR_OK;
6044
6045         if (!Printer) {
6046                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6047                         OUR_HANDLE(handle)));
6048                 return WERR_BADFID;
6049         }
6050
6051         if (!get_printer_snum(p, handle, &snum, NULL))
6052                 return WERR_BADFID;
6053
6054         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6055
6056         return errcode;
6057 }
6058
6059 /********************************************************************
6060  * called by spoolss_api_setprinter
6061  * when updating a printer description
6062  ********************************************************************/
6063
6064 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6065                                  const SPOOL_PRINTER_INFO_LEVEL *info,
6066                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6067 {
6068         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6069         WERROR result;
6070         int snum;
6071
6072         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6073
6074         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6075                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6076                          OUR_HANDLE(handle)));
6077
6078                 result = WERR_BADFID;
6079                 goto done;
6080         }
6081
6082         if (!secdesc_ctr) {
6083                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6084                 result = WERR_INVALID_PARAM;
6085                 goto done;
6086         }
6087
6088         /* Check the user has permissions to change the security
6089            descriptor.  By experimentation with two NT machines, the user
6090            requires Full Access to the printer to change security
6091            information. */
6092
6093         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6094                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6095                 result = WERR_ACCESS_DENIED;
6096                 goto done;
6097         }
6098
6099         /* NT seems to like setting the security descriptor even though
6100            nothing may have actually changed. */
6101
6102         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6103                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6104                 result = WERR_BADFID;
6105                 goto done;
6106         }
6107
6108         if (DEBUGLEVEL >= 10) {
6109                 SEC_ACL *the_acl;
6110                 int i;
6111
6112                 the_acl = old_secdesc_ctr->sd->dacl;
6113                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6114                            PRINTERNAME(snum), the_acl->num_aces));
6115
6116                 for (i = 0; i < the_acl->num_aces; i++) {
6117                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6118                                            &the_acl->aces[i].trustee),
6119                                   the_acl->aces[i].access_mask));
6120                 }
6121
6122                 the_acl = secdesc_ctr->sd->dacl;
6123
6124                 if (the_acl) {
6125                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6126                                    PRINTERNAME(snum), the_acl->num_aces));
6127
6128                         for (i = 0; i < the_acl->num_aces; i++) {
6129                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6130                                                    &the_acl->aces[i].trustee),
6131                                            the_acl->aces[i].access_mask));
6132                         }
6133                 } else {
6134                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6135                 }
6136         }
6137
6138         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6139         if (!new_secdesc_ctr) {
6140                 result = WERR_NOMEM;
6141                 goto done;
6142         }
6143
6144         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6145                 result = WERR_OK;
6146                 goto done;
6147         }
6148
6149         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6150
6151  done:
6152
6153         return result;
6154 }
6155
6156 /********************************************************************
6157  Canonicalize printer info from a client
6158
6159  ATTN: It does not matter what we set the servername to hear
6160  since we do the necessary work in get_a_printer() to set it to
6161  the correct value based on what the client sent in the
6162  _spoolss_open_printer_ex().
6163  ********************************************************************/
6164
6165 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6166 {
6167         fstring printername;
6168         const char *p;
6169
6170         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6171                 "portname=%s drivername=%s comment=%s location=%s\n",
6172                 info->servername, info->printername, info->sharename,
6173                 info->portname, info->drivername, info->comment, info->location));
6174
6175         /* we force some elements to "correct" values */
6176         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6177         fstrcpy(info->sharename, lp_servicename(snum));
6178
6179         /* check to see if we allow printername != sharename */
6180
6181         if ( lp_force_printername(snum) ) {
6182                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6183                         global_myname(), info->sharename );
6184         } else {
6185
6186                 /* make sure printername is in \\server\printername format */
6187
6188                 fstrcpy( printername, info->printername );
6189                 p = printername;
6190                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6191                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6192                                 p++;
6193                 }
6194
6195                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6196                          global_myname(), p );
6197         }
6198
6199         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6200         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6201
6202
6203
6204         return True;
6205 }
6206
6207 /****************************************************************************
6208 ****************************************************************************/
6209
6210 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6211 {
6212         char *cmd = lp_addport_cmd();
6213         char *command = NULL;
6214         int ret;
6215         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6216         bool is_print_op = False;
6217
6218         if ( !*cmd ) {
6219                 return WERR_ACCESS_DENIED;
6220         }
6221
6222         command = talloc_asprintf(ctx,
6223                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6224         if (!command) {
6225                 return WERR_NOMEM;
6226         }
6227
6228         if ( token )
6229                 is_print_op = user_has_privileges( token, &se_printop );
6230
6231         DEBUG(10,("Running [%s]\n", command));
6232
6233         /********* BEGIN SePrintOperatorPrivilege **********/
6234
6235         if ( is_print_op )
6236                 become_root();
6237
6238         ret = smbrun(command, NULL);
6239
6240         if ( is_print_op )
6241                 unbecome_root();
6242
6243         /********* END SePrintOperatorPrivilege **********/
6244
6245         DEBUGADD(10,("returned [%d]\n", ret));
6246
6247         TALLOC_FREE(command);
6248
6249         if ( ret != 0 ) {
6250                 return WERR_ACCESS_DENIED;
6251         }
6252
6253         return WERR_OK;
6254 }
6255
6256 /****************************************************************************
6257 ****************************************************************************/
6258
6259 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6260 {
6261         char *cmd = lp_addprinter_cmd();
6262         char **qlines;
6263         char *command = NULL;
6264         int numlines;
6265         int ret;
6266         int fd;
6267         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6268         bool is_print_op = False;
6269         char *remote_machine = talloc_strdup(ctx, "%m");
6270
6271         if (!remote_machine) {
6272                 return false;
6273         }
6274         remote_machine = talloc_sub_basic(ctx,
6275                                 current_user_info.smb_name,
6276                                 current_user_info.domain,
6277                                 remote_machine);
6278         if (!remote_machine) {
6279                 return false;
6280         }
6281
6282         command = talloc_asprintf(ctx,
6283                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6284                         cmd, printer->info_2->printername, printer->info_2->sharename,
6285                         printer->info_2->portname, printer->info_2->drivername,
6286                         printer->info_2->location, printer->info_2->comment, remote_machine);
6287         if (!command) {
6288                 return false;
6289         }
6290
6291         if ( token )
6292                 is_print_op = user_has_privileges( token, &se_printop );
6293
6294         DEBUG(10,("Running [%s]\n", command));
6295
6296         /********* BEGIN SePrintOperatorPrivilege **********/
6297
6298         if ( is_print_op )
6299                 become_root();
6300
6301         if ( (ret = smbrun(command, &fd)) == 0 ) {
6302                 /* Tell everyone we updated smb.conf. */
6303                 message_send_all(smbd_messaging_context(),
6304                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6305         }
6306
6307         if ( is_print_op )
6308                 unbecome_root();
6309
6310         /********* END SePrintOperatorPrivilege **********/
6311
6312         DEBUGADD(10,("returned [%d]\n", ret));
6313
6314         TALLOC_FREE(command);
6315         TALLOC_FREE(remote_machine);
6316
6317         if ( ret != 0 ) {
6318                 if (fd != -1)
6319                         close(fd);
6320                 return False;
6321         }
6322
6323         /* reload our services immediately */
6324         reload_services( False );
6325
6326         numlines = 0;
6327         /* Get lines and convert them back to dos-codepage */
6328         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6329         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6330         close(fd);
6331
6332         /* Set the portname to what the script says the portname should be. */
6333         /* but don't require anything to be return from the script exit a good error code */
6334
6335         if (numlines) {
6336                 /* Set the portname to what the script says the portname should be. */
6337                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6338                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6339         }
6340
6341         TALLOC_FREE(qlines);
6342         return True;
6343 }
6344
6345
6346 /********************************************************************
6347  * Called by spoolss_api_setprinter
6348  * when updating a printer description.
6349  ********************************************************************/
6350
6351 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6352                            const SPOOL_PRINTER_INFO_LEVEL *info,
6353                            DEVICEMODE *devmode)
6354 {
6355         int snum;
6356         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6357         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6358         WERROR result;
6359         UNISTR2 buffer;
6360         fstring asc_buffer;
6361
6362         DEBUG(8,("update_printer\n"));
6363
6364         result = WERR_OK;
6365
6366         if (!Printer) {
6367                 result = WERR_BADFID;
6368                 goto done;
6369         }
6370
6371         if (!get_printer_snum(p, handle, &snum, NULL)) {
6372                 result = WERR_BADFID;
6373                 goto done;
6374         }
6375
6376         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6377             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6378                 result = WERR_BADFID;
6379                 goto done;
6380         }
6381
6382         DEBUGADD(8,("Converting info_2 struct\n"));
6383
6384         /*
6385          * convert_printer_info converts the incoming
6386          * info from the client and overwrites the info
6387          * just read from the tdb in the pointer 'printer'.
6388          */
6389
6390         if (!convert_printer_info(info, printer, level)) {
6391                 result =  WERR_NOMEM;
6392                 goto done;
6393         }
6394
6395         if (devmode) {
6396                 /* we have a valid devmode
6397                    convert it and link it*/
6398
6399                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6400                 if (!convert_devicemode(printer->info_2->printername, devmode,
6401                                 &printer->info_2->devmode)) {
6402                         result =  WERR_NOMEM;
6403                         goto done;
6404                 }
6405         }
6406
6407         /* Do sanity check on the requested changes for Samba */
6408
6409         if (!check_printer_ok(printer->info_2, snum)) {
6410                 result = WERR_INVALID_PARAM;
6411                 goto done;
6412         }
6413
6414         /* FIXME!!! If the driver has changed we really should verify that
6415            it is installed before doing much else   --jerry */
6416
6417         /* Check calling user has permission to update printer description */
6418
6419         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6420                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6421                 result = WERR_ACCESS_DENIED;
6422                 goto done;
6423         }
6424
6425         /* Call addprinter hook */
6426         /* Check changes to see if this is really needed */
6427
6428         if ( *lp_addprinter_cmd()
6429                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6430                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6431                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6432                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6433         {
6434                 /* add_printer_hook() will call reload_services() */
6435
6436                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6437                                        printer) ) {
6438                         result = WERR_ACCESS_DENIED;
6439                         goto done;
6440                 }
6441         }
6442
6443         /*
6444          * When a *new* driver is bound to a printer, the drivername is used to
6445          * lookup previously saved driver initialization info, which is then
6446          * bound to the printer, simulating what happens in the Windows arch.
6447          */
6448         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6449         {
6450                 if (!set_driver_init(printer, 2))
6451                 {
6452                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6453                                 printer->info_2->drivername));
6454                 }
6455
6456                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6457                         printer->info_2->drivername));
6458
6459                 notify_printer_driver(snum, printer->info_2->drivername);
6460         }
6461
6462         /*
6463          * flag which changes actually occured.  This is a small subset of
6464          * all the possible changes.  We also have to update things in the
6465          * DsSpooler key.
6466          */
6467
6468         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6469                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6470                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6471                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6472
6473                 notify_printer_comment(snum, printer->info_2->comment);
6474         }
6475
6476         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6477                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6478                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6479                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6480
6481                 notify_printer_sharename(snum, printer->info_2->sharename);
6482         }
6483
6484         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6485                 char *pname;
6486
6487                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6488                         pname++;
6489                 else
6490                         pname = printer->info_2->printername;
6491
6492
6493                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6494                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6495                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6496
6497                 notify_printer_printername( snum, pname );
6498         }
6499
6500         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6501                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6502                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6503                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6504
6505                 notify_printer_port(snum, printer->info_2->portname);
6506         }
6507
6508         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6509                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6510                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6511                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6512
6513                 notify_printer_location(snum, printer->info_2->location);
6514         }
6515
6516         /* here we need to update some more DsSpooler keys */
6517         /* uNCName, serverName, shortServerName */
6518
6519         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6520         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6521                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6522         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6523                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6524
6525         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6526                  global_myname(), printer->info_2->sharename );
6527         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6528         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6529                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6530
6531         /* Update printer info */
6532         result = mod_a_printer(printer, 2);
6533
6534 done:
6535         free_a_printer(&printer, 2);
6536         free_a_printer(&old_printer, 2);
6537
6538
6539         return result;
6540 }
6541
6542 /****************************************************************************
6543 ****************************************************************************/
6544 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6545                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6546 {
6547 #ifdef HAVE_ADS
6548         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6549         int snum;
6550         Printer_entry *Printer;
6551
6552         if ( lp_security() != SEC_ADS ) {
6553                 return WERR_UNKNOWN_LEVEL;
6554         }
6555
6556         Printer = find_printer_index_by_hnd(p, handle);
6557
6558         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6559
6560         if (!Printer)
6561                 return WERR_BADFID;
6562
6563         if (!get_printer_snum(p, handle, &snum, NULL))
6564                 return WERR_BADFID;
6565
6566         nt_printer_publish(Printer, snum, info7->action);
6567
6568         return WERR_OK;
6569 #else
6570         return WERR_UNKNOWN_LEVEL;
6571 #endif
6572 }
6573 /****************************************************************************
6574 ****************************************************************************/
6575
6576 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6577 {
6578         POLICY_HND *handle = &q_u->handle;
6579         uint32 level = q_u->level;
6580         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6581         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6582         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6583         uint32 command = q_u->command;
6584         WERROR result;
6585
6586         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6587
6588         if (!Printer) {
6589                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6590                 return WERR_BADFID;
6591         }
6592
6593         /* check the level */
6594         switch (level) {
6595                 case 0:
6596                         return control_printer(handle, command, p);
6597                 case 2:
6598                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6599                         if (!W_ERROR_IS_OK(result))
6600                                 return result;
6601                         if (secdesc_ctr)
6602                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6603                         return result;
6604                 case 3:
6605                         return update_printer_sec(handle, level, info, p,
6606                                                   secdesc_ctr);
6607                 case 7:
6608                         return publish_or_unpublish_printer(p, handle, info);
6609                 default:
6610                         return WERR_UNKNOWN_LEVEL;
6611         }
6612 }
6613
6614 /****************************************************************
6615  _spoolss_FindClosePrinterNotify
6616 ****************************************************************/
6617
6618 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6619                                        struct spoolss_FindClosePrinterNotify *r)
6620 {
6621         POLICY_HND *handle = r->in.handle;
6622         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6623
6624         if (!Printer) {
6625                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6626                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6627                 return WERR_BADFID;
6628         }
6629
6630         if (Printer->notify.client_connected==True) {
6631                 int snum = -1;
6632
6633                 if ( Printer->printer_type == SPLHND_SERVER)
6634                         snum = -1;
6635                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6636                                 !get_printer_snum(p, handle, &snum, NULL) )
6637                         return WERR_BADFID;
6638
6639                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6640         }
6641
6642         Printer->notify.flags=0;
6643         Printer->notify.options=0;
6644         Printer->notify.localmachine[0]='\0';
6645         Printer->notify.printerlocal=0;
6646         if (Printer->notify.option)
6647                 free_spool_notify_option(&Printer->notify.option);
6648         Printer->notify.client_connected=False;
6649
6650         return WERR_OK;
6651 }
6652
6653 /****************************************************************
6654  _spoolss_AddJob
6655 ****************************************************************/
6656
6657 WERROR _spoolss_AddJob(pipes_struct *p,
6658                        struct spoolss_AddJob *r)
6659 {
6660         if (!r->in.buffer && (r->in.offered != 0)) {
6661                 return WERR_INVALID_PARAM;
6662         }
6663
6664         /* this is what a NT server returns for AddJob. AddJob must fail on
6665          * non-local printers */
6666
6667         return WERR_INVALID_PARAM;
6668 }
6669
6670 /****************************************************************************
6671 ****************************************************************************/
6672
6673 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6674                             int position, int snum,
6675                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6676 {
6677         struct tm *t;
6678
6679         t=gmtime(&queue->time);
6680
6681         job_info->jobid=queue->job;
6682         init_unistr(&job_info->printername, lp_servicename(snum));
6683         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6684         init_unistr(&job_info->username, queue->fs_user);
6685         init_unistr(&job_info->document, queue->fs_file);
6686         init_unistr(&job_info->datatype, "RAW");
6687         init_unistr(&job_info->text_status, "");
6688         job_info->status=nt_printj_status(queue->status);
6689         job_info->priority=queue->priority;
6690         job_info->position=position;
6691         job_info->totalpages=queue->page_count;
6692         job_info->pagesprinted=0;
6693
6694         make_systemtime(&job_info->submitted, t);
6695 }
6696
6697 /****************************************************************************
6698 ****************************************************************************/
6699
6700 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6701                             int position, int snum,
6702                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6703                             DEVICEMODE *devmode)
6704 {
6705         struct tm *t;
6706
6707         t=gmtime(&queue->time);
6708
6709         job_info->jobid=queue->job;
6710
6711         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6712
6713         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6714         init_unistr(&job_info->username, queue->fs_user);
6715         init_unistr(&job_info->document, queue->fs_file);
6716         init_unistr(&job_info->notifyname, queue->fs_user);
6717         init_unistr(&job_info->datatype, "RAW");
6718         init_unistr(&job_info->printprocessor, "winprint");
6719         init_unistr(&job_info->parameters, "");
6720         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6721         init_unistr(&job_info->text_status, "");
6722
6723 /* and here the security descriptor */
6724
6725         job_info->status=nt_printj_status(queue->status);
6726         job_info->priority=queue->priority;
6727         job_info->position=position;
6728         job_info->starttime=0;
6729         job_info->untiltime=0;
6730         job_info->totalpages=queue->page_count;
6731         job_info->size=queue->size;
6732         make_systemtime(&(job_info->submitted), t);
6733         job_info->timeelapsed=0;
6734         job_info->pagesprinted=0;
6735
6736         job_info->devmode = devmode;
6737
6738         return (True);
6739 }
6740
6741 /****************************************************************************
6742  Enumjobs at level 1.
6743 ****************************************************************************/
6744
6745 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6746                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6747                               RPC_BUFFER *buffer, uint32 offered,
6748                               uint32 *needed, uint32 *returned)
6749 {
6750         JOB_INFO_1 *info;
6751         int i;
6752         WERROR result = WERR_OK;
6753
6754         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6755         if (info==NULL) {
6756                 *returned=0;
6757                 return WERR_NOMEM;
6758         }
6759
6760         for (i=0; i<*returned; i++)
6761                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6762
6763         /* check the required size. */
6764         for (i=0; i<*returned; i++)
6765                 (*needed) += spoolss_size_job_info_1(&info[i]);
6766
6767         if (*needed > offered) {
6768                 result = WERR_INSUFFICIENT_BUFFER;
6769                 goto out;
6770         }
6771
6772         if (!rpcbuf_alloc_size(buffer, *needed)) {
6773                 result = WERR_NOMEM;
6774                 goto out;
6775         }
6776
6777         /* fill the buffer with the structures */
6778         for (i=0; i<*returned; i++)
6779                 smb_io_job_info_1("", buffer, &info[i], 0);
6780
6781 out:
6782         /* clear memory */
6783         SAFE_FREE(info);
6784
6785         if ( !W_ERROR_IS_OK(result) )
6786                 *returned = 0;
6787
6788         return result;
6789 }
6790
6791 /****************************************************************************
6792  Enumjobs at level 2.
6793 ****************************************************************************/
6794
6795 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6796                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6797                               RPC_BUFFER *buffer, uint32 offered,
6798                               uint32 *needed, uint32 *returned)
6799 {
6800         JOB_INFO_2 *info = NULL;
6801         int i;
6802         WERROR result = WERR_OK;
6803         DEVICEMODE *devmode = NULL;
6804
6805         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6806                 *returned=0;
6807                 return WERR_NOMEM;
6808         }
6809
6810         /* this should not be a failure condition if the devmode is NULL */
6811
6812         devmode = construct_dev_mode(lp_const_servicename(snum));
6813
6814         for (i=0; i<*returned; i++)
6815                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6816
6817         /* check the required size. */
6818         for (i=0; i<*returned; i++)
6819                 (*needed) += spoolss_size_job_info_2(&info[i]);
6820
6821         if (*needed > offered) {
6822                 result = WERR_INSUFFICIENT_BUFFER;
6823                 goto out;
6824         }
6825
6826         if (!rpcbuf_alloc_size(buffer, *needed)) {
6827                 result = WERR_NOMEM;
6828                 goto out;
6829         }
6830
6831         /* fill the buffer with the structures */
6832         for (i=0; i<*returned; i++)
6833                 smb_io_job_info_2("", buffer, &info[i], 0);
6834
6835 out:
6836         free_devmode(devmode);
6837         SAFE_FREE(info);
6838
6839         if ( !W_ERROR_IS_OK(result) )
6840                 *returned = 0;
6841
6842         return result;
6843
6844 }
6845
6846 /****************************************************************************
6847  Enumjobs.
6848 ****************************************************************************/
6849
6850 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6851 {
6852         POLICY_HND *handle = &q_u->handle;
6853         uint32 level = q_u->level;
6854         RPC_BUFFER *buffer = NULL;
6855         uint32 offered = q_u->offered;
6856         uint32 *needed = &r_u->needed;
6857         uint32 *returned = &r_u->returned;
6858         WERROR wret;
6859         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6860         int snum;
6861         print_status_struct prt_status;
6862         print_queue_struct *queue=NULL;
6863
6864         /* that's an [in out] buffer */
6865
6866         if (!q_u->buffer && (offered!=0)) {
6867                 return WERR_INVALID_PARAM;
6868         }
6869
6870         if (offered > MAX_RPC_DATA_SIZE) {
6871                 return WERR_INVALID_PARAM;
6872         }
6873
6874         rpcbuf_move(q_u->buffer, &r_u->buffer);
6875         buffer = r_u->buffer;
6876
6877         DEBUG(4,("_spoolss_enumjobs\n"));
6878
6879         *needed=0;
6880         *returned=0;
6881
6882         /* lookup the printer snum and tdb entry */
6883
6884         if (!get_printer_snum(p, handle, &snum, NULL))
6885                 return WERR_BADFID;
6886
6887         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6888         if ( !W_ERROR_IS_OK(wret) )
6889                 return wret;
6890
6891         *returned = print_queue_status(snum, &queue, &prt_status);
6892         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6893
6894         if (*returned == 0) {
6895                 SAFE_FREE(queue);
6896                 free_a_printer(&ntprinter, 2);
6897                 return WERR_OK;
6898         }
6899
6900         switch (level) {
6901         case 1:
6902                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6903                 break;
6904         case 2:
6905                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6906                 break;
6907         default:
6908                 *returned=0;
6909                 wret = WERR_UNKNOWN_LEVEL;
6910                 break;
6911         }
6912
6913         SAFE_FREE(queue);
6914         free_a_printer( &ntprinter, 2 );
6915         return wret;
6916 }
6917
6918 /****************************************************************
6919  _spoolss_ScheduleJob
6920 ****************************************************************/
6921
6922 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6923                             struct spoolss_ScheduleJob *r)
6924 {
6925         return WERR_OK;
6926 }
6927
6928 /****************************************************************
6929  _spoolss_SetJob
6930 ****************************************************************/
6931
6932 WERROR _spoolss_SetJob(pipes_struct *p,
6933                        struct spoolss_SetJob *r)
6934 {
6935         POLICY_HND *handle = r->in.handle;
6936         uint32 jobid = r->in.job_id;
6937         uint32 command = r->in.command;
6938
6939         int snum;
6940         WERROR errcode = WERR_BADFUNC;
6941
6942         if (!get_printer_snum(p, handle, &snum, NULL)) {
6943                 return WERR_BADFID;
6944         }
6945
6946         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6947                 return WERR_INVALID_PRINTER_NAME;
6948         }
6949
6950         switch (command) {
6951         case SPOOLSS_JOB_CONTROL_CANCEL:
6952         case SPOOLSS_JOB_CONTROL_DELETE:
6953                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6954                         errcode = WERR_OK;
6955                 }
6956                 break;
6957         case SPOOLSS_JOB_CONTROL_PAUSE:
6958                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6959                         errcode = WERR_OK;
6960                 }
6961                 break;
6962         case SPOOLSS_JOB_CONTROL_RESTART:
6963         case SPOOLSS_JOB_CONTROL_RESUME:
6964                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6965                         errcode = WERR_OK;
6966                 }
6967                 break;
6968         default:
6969                 return WERR_UNKNOWN_LEVEL;
6970         }
6971
6972         return errcode;
6973 }
6974
6975 /****************************************************************************
6976  Enumerates all printer drivers at level 1.
6977 ****************************************************************************/
6978
6979 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6980 {
6981         int i;
6982         int ndrivers;
6983         uint32 version;
6984         fstring *list = NULL;
6985         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6986         DRIVER_INFO_1 *driver_info_1=NULL;
6987         WERROR result = WERR_OK;
6988
6989         *returned=0;
6990
6991         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6992                 list=NULL;
6993                 ndrivers=get_ntdrivers(&list, architecture, version);
6994                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6995
6996                 if(ndrivers == -1) {
6997                         SAFE_FREE(driver_info_1);
6998                         return WERR_NOMEM;
6999                 }
7000
7001                 if(ndrivers != 0) {
7002                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
7003                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
7004                                 SAFE_FREE(list);
7005                                 return WERR_NOMEM;
7006                         }
7007                 }
7008
7009                 for (i=0; i<ndrivers; i++) {
7010                         WERROR status;
7011                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7012                         ZERO_STRUCT(driver);
7013                         status = get_a_printer_driver(&driver, 3, list[i],
7014                                                       architecture, version);
7015                         if (!W_ERROR_IS_OK(status)) {
7016                                 SAFE_FREE(list);
7017                                 SAFE_FREE(driver_info_1);
7018                                 return status;
7019                         }
7020                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
7021                         free_a_printer_driver(driver, 3);
7022                 }
7023
7024                 *returned+=ndrivers;
7025                 SAFE_FREE(list);
7026         }
7027
7028         /* check the required size. */
7029         for (i=0; i<*returned; i++) {
7030                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7031                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
7032         }
7033
7034         if (*needed > offered) {
7035                 result = WERR_INSUFFICIENT_BUFFER;
7036                 goto out;
7037         }
7038
7039         if (!rpcbuf_alloc_size(buffer, *needed)) {
7040                 result = WERR_NOMEM;
7041                 goto out;
7042         }
7043
7044         /* fill the buffer with the driver structures */
7045         for (i=0; i<*returned; i++) {
7046                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7047                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7048         }
7049
7050 out:
7051         SAFE_FREE(driver_info_1);
7052
7053         if ( !W_ERROR_IS_OK(result) )
7054                 *returned = 0;
7055
7056         return result;
7057 }
7058
7059 /****************************************************************************
7060  Enumerates all printer drivers at level 2.
7061 ****************************************************************************/
7062
7063 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7064 {
7065         int i;
7066         int ndrivers;
7067         uint32 version;
7068         fstring *list = NULL;
7069         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7070         DRIVER_INFO_2 *driver_info_2=NULL;
7071         WERROR result = WERR_OK;
7072
7073         *returned=0;
7074
7075         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7076                 list=NULL;
7077                 ndrivers=get_ntdrivers(&list, architecture, version);
7078                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7079
7080                 if(ndrivers == -1) {
7081                         SAFE_FREE(driver_info_2);
7082                         return WERR_NOMEM;
7083                 }
7084
7085                 if(ndrivers != 0) {
7086                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7087                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7088                                 SAFE_FREE(list);
7089                                 return WERR_NOMEM;
7090                         }
7091                 }
7092
7093                 for (i=0; i<ndrivers; i++) {
7094                         WERROR status;
7095
7096                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7097                         ZERO_STRUCT(driver);
7098                         status = get_a_printer_driver(&driver, 3, list[i],
7099                                                       architecture, version);
7100                         if (!W_ERROR_IS_OK(status)) {
7101                                 SAFE_FREE(list);
7102                                 SAFE_FREE(driver_info_2);
7103                                 return status;
7104                         }
7105                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7106                         free_a_printer_driver(driver, 3);
7107                 }
7108
7109                 *returned+=ndrivers;
7110                 SAFE_FREE(list);
7111         }
7112
7113         /* check the required size. */
7114         for (i=0; i<*returned; i++) {
7115                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7116                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7117         }
7118
7119         if (*needed > offered) {
7120                 result = WERR_INSUFFICIENT_BUFFER;
7121                 goto out;
7122         }
7123
7124         if (!rpcbuf_alloc_size(buffer, *needed)) {
7125                 result = WERR_NOMEM;
7126                 goto out;
7127         }
7128
7129         /* fill the buffer with the form structures */
7130         for (i=0; i<*returned; i++) {
7131                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7132                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7133         }
7134
7135 out:
7136         SAFE_FREE(driver_info_2);
7137
7138         if ( !W_ERROR_IS_OK(result) )
7139                 *returned = 0;
7140
7141         return result;
7142 }
7143
7144 /****************************************************************************
7145  Enumerates all printer drivers at level 3.
7146 ****************************************************************************/
7147
7148 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7149 {
7150         int i;
7151         int ndrivers;
7152         uint32 version;
7153         fstring *list = NULL;
7154         DRIVER_INFO_3 *driver_info_3=NULL;
7155         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7156         WERROR result = WERR_OK;
7157
7158         *returned=0;
7159
7160         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7161                 list=NULL;
7162                 ndrivers=get_ntdrivers(&list, architecture, version);
7163                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7164
7165                 if(ndrivers == -1) {
7166                         SAFE_FREE(driver_info_3);
7167                         return WERR_NOMEM;
7168                 }
7169
7170                 if(ndrivers != 0) {
7171                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7172                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7173                                 SAFE_FREE(list);
7174                                 return WERR_NOMEM;
7175                         }
7176                 }
7177
7178                 for (i=0; i<ndrivers; i++) {
7179                         WERROR status;
7180
7181                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7182                         ZERO_STRUCT(driver);
7183                         status = get_a_printer_driver(&driver, 3, list[i],
7184                                                       architecture, version);
7185                         if (!W_ERROR_IS_OK(status)) {
7186                                 SAFE_FREE(list);
7187                                 SAFE_FREE(driver_info_3);
7188                                 return status;
7189                         }
7190                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7191                         free_a_printer_driver(driver, 3);
7192                 }
7193
7194                 *returned+=ndrivers;
7195                 SAFE_FREE(list);
7196         }
7197
7198         /* check the required size. */
7199         for (i=0; i<*returned; i++) {
7200                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7201                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7202         }
7203
7204         if (*needed > offered) {
7205                 result = WERR_INSUFFICIENT_BUFFER;
7206                 goto out;
7207         }
7208
7209         if (!rpcbuf_alloc_size(buffer, *needed)) {
7210                 result = WERR_NOMEM;
7211                 goto out;
7212         }
7213
7214         /* fill the buffer with the driver structures */
7215         for (i=0; i<*returned; i++) {
7216                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7217                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7218         }
7219
7220 out:
7221         for (i=0; i<*returned; i++) {
7222                 SAFE_FREE(driver_info_3[i].dependentfiles);
7223         }
7224
7225         SAFE_FREE(driver_info_3);
7226
7227         if ( !W_ERROR_IS_OK(result) )
7228                 *returned = 0;
7229
7230         return result;
7231 }
7232
7233 /****************************************************************************
7234  Enumerates all printer drivers.
7235 ****************************************************************************/
7236
7237 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7238 {
7239         uint32 level = q_u->level;
7240         RPC_BUFFER *buffer = NULL;
7241         uint32 offered = q_u->offered;
7242         uint32 *needed = &r_u->needed;
7243         uint32 *returned = &r_u->returned;
7244         const char *cservername;
7245         fstring servername;
7246         fstring architecture;
7247
7248         /* that's an [in out] buffer */
7249
7250         if (!q_u->buffer && (offered!=0)) {
7251                 return WERR_INVALID_PARAM;
7252         }
7253
7254         if (offered > MAX_RPC_DATA_SIZE) {
7255                 return WERR_INVALID_PARAM;
7256         }
7257
7258         rpcbuf_move(q_u->buffer, &r_u->buffer);
7259         buffer = r_u->buffer;
7260
7261         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7262
7263         *needed   = 0;
7264         *returned = 0;
7265
7266         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7267         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7268
7269         cservername = canon_servername(servername);
7270
7271         if (!is_myname_or_ipaddr(cservername))
7272                 return WERR_UNKNOWN_PRINTER_DRIVER;
7273
7274         switch (level) {
7275         case 1:
7276                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7277         case 2:
7278                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7279         case 3:
7280                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7281         default:
7282                 return WERR_UNKNOWN_LEVEL;
7283         }
7284 }
7285
7286 /****************************************************************************
7287 ****************************************************************************/
7288
7289 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7290 {
7291         form->flag=list->flag;
7292         init_unistr(&form->name, list->name);
7293         form->width=list->width;
7294         form->length=list->length;
7295         form->left=list->left;
7296         form->top=list->top;
7297         form->right=list->right;
7298         form->bottom=list->bottom;
7299 }
7300
7301 /****************************************************************************
7302 ****************************************************************************/
7303
7304 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7305                                struct spoolss_FormInfo1 *form,
7306                                nt_forms_struct *list)
7307 {
7308         form->form_name         = talloc_strdup(mem_ctx, list->name);
7309         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7310
7311         form->flags             = list->flag;
7312         form->size.width        = list->width;
7313         form->size.height       = list->length;
7314         form->area.left         = list->left;
7315         form->area.top          = list->top;
7316         form->area.right        = list->right;
7317         form->area.bottom       = list->bottom;
7318
7319         return WERR_OK;
7320 }
7321
7322 /****************************************************************************
7323 ****************************************************************************/
7324
7325 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7326 {
7327         uint32 level = q_u->level;
7328         RPC_BUFFER *buffer = NULL;
7329         uint32 offered = q_u->offered;
7330         uint32 *needed = &r_u->needed;
7331         uint32 *numofforms = &r_u->numofforms;
7332         uint32 numbuiltinforms;
7333
7334         nt_forms_struct *list=NULL;
7335         nt_forms_struct *builtinlist=NULL;
7336         FORM_1 *forms_1;
7337         int buffer_size=0;
7338         int i;
7339
7340         /* that's an [in out] buffer */
7341
7342         if (!q_u->buffer && (offered!=0) ) {
7343                 return WERR_INVALID_PARAM;
7344         }
7345
7346         if (offered > MAX_RPC_DATA_SIZE) {
7347                 return WERR_INVALID_PARAM;
7348         }
7349
7350         rpcbuf_move(q_u->buffer, &r_u->buffer);
7351         buffer = r_u->buffer;
7352
7353         DEBUG(4,("_spoolss_enumforms\n"));
7354         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7355         DEBUGADD(5,("Info level [%d]\n",          level));
7356
7357         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7358         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7359         *numofforms = get_ntforms(&list);
7360         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7361         *numofforms += numbuiltinforms;
7362
7363         if (*numofforms == 0) {
7364                 SAFE_FREE(builtinlist);
7365                 SAFE_FREE(list);
7366                 return WERR_NO_MORE_ITEMS;
7367         }
7368
7369         switch (level) {
7370         case 1:
7371                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7372                         SAFE_FREE(builtinlist);
7373                         SAFE_FREE(list);
7374                         *numofforms=0;
7375                         return WERR_NOMEM;
7376                 }
7377
7378                 /* construct the list of form structures */
7379                 for (i=0; i<numbuiltinforms; i++) {
7380                         DEBUGADD(6,("Filling form number [%d]\n",i));
7381                         fill_form_1(&forms_1[i], &builtinlist[i]);
7382                 }
7383
7384                 SAFE_FREE(builtinlist);
7385
7386                 for (; i<*numofforms; i++) {
7387                         DEBUGADD(6,("Filling form number [%d]\n",i));
7388                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7389                 }
7390
7391                 SAFE_FREE(list);
7392
7393                 /* check the required size. */
7394                 for (i=0; i<numbuiltinforms; i++) {
7395                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7396                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7397                 }
7398                 for (; i<*numofforms; i++) {
7399                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7400                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7401                 }
7402
7403                 *needed=buffer_size;
7404
7405                 if (*needed > offered) {
7406                         SAFE_FREE(forms_1);
7407                         *numofforms=0;
7408                         return WERR_INSUFFICIENT_BUFFER;
7409                 }
7410
7411                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7412                         SAFE_FREE(forms_1);
7413                         *numofforms=0;
7414                         return WERR_NOMEM;
7415                 }
7416
7417                 /* fill the buffer with the form structures */
7418                 for (i=0; i<numbuiltinforms; i++) {
7419                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7420                         smb_io_form_1("", buffer, &forms_1[i], 0);
7421                 }
7422                 for (; i<*numofforms; i++) {
7423                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7424                         smb_io_form_1("", buffer, &forms_1[i], 0);
7425                 }
7426
7427                 SAFE_FREE(forms_1);
7428
7429                 return WERR_OK;
7430
7431         default:
7432                 SAFE_FREE(list);
7433                 SAFE_FREE(builtinlist);
7434                 return WERR_UNKNOWN_LEVEL;
7435         }
7436 }
7437
7438 /****************************************************************
7439  _spoolss_GetForm
7440 ****************************************************************/
7441
7442 WERROR _spoolss_GetForm(pipes_struct *p,
7443                         struct spoolss_GetForm *r)
7444 {
7445         uint32 level = r->in.level;
7446         uint32 offered = r->in.offered;
7447         uint32 *needed = r->out.needed;
7448
7449         nt_forms_struct *list=NULL;
7450         nt_forms_struct builtin_form;
7451         bool foundBuiltin;
7452         union spoolss_FormInfo info;
7453         struct spoolss_FormInfo1 form_1;
7454         int numofforms=0, i=0;
7455
7456         /* that's an [in out] buffer */
7457
7458         if (!r->in.buffer && (offered!=0)) {
7459                 return WERR_INVALID_PARAM;
7460         }
7461
7462         DEBUG(4,("_spoolss_GetForm\n"));
7463         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7464         DEBUGADD(5,("Info level [%d]\n",          level));
7465
7466         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7467         if (!foundBuiltin) {
7468                 numofforms = get_ntforms(&list);
7469                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7470
7471                 if (numofforms == 0)
7472                         return WERR_BADFID;
7473         }
7474
7475         ZERO_STRUCT(form_1);
7476
7477         switch (level) {
7478         case 1:
7479                 if (foundBuiltin) {
7480                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7481                 } else {
7482
7483                         /* Check if the requested name is in the list of form structures */
7484                         for (i=0; i<numofforms; i++) {
7485
7486                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7487                                         list[i].name, r->in.form_name));
7488
7489                                 if (strequal(r->in.form_name, list[i].name)) {
7490                                         DEBUGADD(6,("Found form %s number [%d]\n",
7491                                                 r->in.form_name, i));
7492                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7493                                         break;
7494                                 }
7495                         }
7496
7497                         SAFE_FREE(list);
7498                         if (i == numofforms) {
7499                                 return WERR_BADFID;
7500                         }
7501                 }
7502                 /* check the required size. */
7503
7504                 info.info1 = form_1;
7505
7506                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7507
7508                 if (*needed > offered) {
7509                         r->out.info = NULL;
7510                         return WERR_INSUFFICIENT_BUFFER;
7511                 }
7512
7513                 r->out.info->info1 = form_1;
7514
7515                 /* fill the buffer with the form structures */
7516                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7517                         r->in.form_name, i));
7518
7519                 return WERR_OK;
7520
7521         default:
7522                 SAFE_FREE(list);
7523                 return WERR_UNKNOWN_LEVEL;
7524         }
7525 }
7526
7527 /****************************************************************************
7528 ****************************************************************************/
7529
7530 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7531 {
7532         init_unistr(&port->port_name, name);
7533 }
7534
7535 /****************************************************************************
7536  TODO: This probably needs distinguish between TCP/IP and Local ports
7537  somehow.
7538 ****************************************************************************/
7539
7540 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7541 {
7542         init_unistr(&port->port_name, name);
7543         init_unistr(&port->monitor_name, "Local Monitor");
7544         init_unistr(&port->description, SPL_LOCAL_PORT );
7545         port->port_type=PORT_TYPE_WRITE;
7546         port->reserved=0x0;
7547 }
7548
7549
7550 /****************************************************************************
7551  wrapper around the enumer ports command
7552 ****************************************************************************/
7553
7554 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7555 {
7556         char *cmd = lp_enumports_cmd();
7557         char **qlines = NULL;
7558         char *command = NULL;
7559         int numlines;
7560         int ret;
7561         int fd;
7562
7563         *count = 0;
7564         *lines = NULL;
7565
7566         /* if no hook then just fill in the default port */
7567
7568         if ( !*cmd ) {
7569                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7570                         return WERR_NOMEM;
7571                 }
7572                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7573                         TALLOC_FREE(qlines);
7574                         return WERR_NOMEM;
7575                 }
7576                 qlines[1] = NULL;
7577                 numlines = 1;
7578         }
7579         else {
7580                 /* we have a valid enumport command */
7581
7582                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7583                 if (!command) {
7584                         return WERR_NOMEM;
7585                 }
7586
7587                 DEBUG(10,("Running [%s]\n", command));
7588                 ret = smbrun(command, &fd);
7589                 DEBUG(10,("Returned [%d]\n", ret));
7590                 TALLOC_FREE(command);
7591                 if (ret != 0) {
7592                         if (fd != -1) {
7593                                 close(fd);
7594                         }
7595                         return WERR_ACCESS_DENIED;
7596                 }
7597
7598                 numlines = 0;
7599                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7600                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7601                 close(fd);
7602         }
7603
7604         *count = numlines;
7605         *lines = qlines;
7606
7607         return WERR_OK;
7608 }
7609
7610 /****************************************************************************
7611  enumports level 1.
7612 ****************************************************************************/
7613
7614 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7615 {
7616         PORT_INFO_1 *ports=NULL;
7617         int i=0;
7618         WERROR result = WERR_OK;
7619         char **qlines = NULL;
7620         int numlines = 0;
7621
7622         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7623         if (!W_ERROR_IS_OK(result)) {
7624                 TALLOC_FREE(qlines);
7625                 return result;
7626         }
7627
7628         if(numlines) {
7629                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7630                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7631                                   win_errstr(WERR_NOMEM)));
7632                         TALLOC_FREE(qlines);
7633                         return WERR_NOMEM;
7634                 }
7635
7636                 for (i=0; i<numlines; i++) {
7637                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7638                         fill_port_1(&ports[i], qlines[i]);
7639                 }
7640         }
7641         TALLOC_FREE(qlines);
7642
7643         *returned = numlines;
7644
7645         /* check the required size. */
7646         for (i=0; i<*returned; i++) {
7647                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7648                 *needed += spoolss_size_port_info_1(&ports[i]);
7649         }
7650
7651         if (*needed > offered) {
7652                 result = WERR_INSUFFICIENT_BUFFER;
7653                 goto out;
7654         }
7655
7656         if (!rpcbuf_alloc_size(buffer, *needed)) {
7657                 result = WERR_NOMEM;
7658                 goto out;
7659         }
7660
7661         /* fill the buffer with the ports structures */
7662         for (i=0; i<*returned; i++) {
7663                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7664                 smb_io_port_1("", buffer, &ports[i], 0);
7665         }
7666
7667 out:
7668         SAFE_FREE(ports);
7669
7670         if ( !W_ERROR_IS_OK(result) )
7671                 *returned = 0;
7672
7673         return result;
7674 }
7675
7676 /****************************************************************************
7677  enumports level 2.
7678 ****************************************************************************/
7679
7680 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7681 {
7682         PORT_INFO_2 *ports=NULL;
7683         int i=0;
7684         WERROR result = WERR_OK;
7685         char **qlines = NULL;
7686         int numlines = 0;
7687
7688         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7689         if ( !W_ERROR_IS_OK(result)) {
7690                 TALLOC_FREE(qlines);
7691                 return result;
7692         }
7693
7694         if(numlines) {
7695                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7696                         TALLOC_FREE(qlines);
7697                         return WERR_NOMEM;
7698                 }
7699
7700                 for (i=0; i<numlines; i++) {
7701                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7702                         fill_port_2(&(ports[i]), qlines[i]);
7703                 }
7704         }
7705
7706         TALLOC_FREE(qlines);
7707
7708         *returned = numlines;
7709
7710         /* check the required size. */
7711         for (i=0; i<*returned; i++) {
7712                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7713                 *needed += spoolss_size_port_info_2(&ports[i]);
7714         }
7715
7716         if (*needed > offered) {
7717                 result = WERR_INSUFFICIENT_BUFFER;
7718                 goto out;
7719         }
7720
7721         if (!rpcbuf_alloc_size(buffer, *needed)) {
7722                 result = WERR_NOMEM;
7723                 goto out;
7724         }
7725
7726         /* fill the buffer with the ports structures */
7727         for (i=0; i<*returned; i++) {
7728                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7729                 smb_io_port_2("", buffer, &ports[i], 0);
7730         }
7731
7732 out:
7733         SAFE_FREE(ports);
7734
7735         if ( !W_ERROR_IS_OK(result) )
7736                 *returned = 0;
7737
7738         return result;
7739 }
7740
7741 /****************************************************************************
7742  enumports.
7743 ****************************************************************************/
7744
7745 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7746 {
7747         uint32 level = q_u->level;
7748         RPC_BUFFER *buffer = NULL;
7749         uint32 offered = q_u->offered;
7750         uint32 *needed = &r_u->needed;
7751         uint32 *returned = &r_u->returned;
7752
7753         /* that's an [in out] buffer */
7754
7755         if (!q_u->buffer && (offered!=0)) {
7756                 return WERR_INVALID_PARAM;
7757         }
7758
7759         if (offered > MAX_RPC_DATA_SIZE) {
7760                 return WERR_INVALID_PARAM;
7761         }
7762
7763         rpcbuf_move(q_u->buffer, &r_u->buffer);
7764         buffer = r_u->buffer;
7765
7766         DEBUG(4,("_spoolss_enumports\n"));
7767
7768         *returned=0;
7769         *needed=0;
7770
7771         switch (level) {
7772         case 1:
7773                 return enumports_level_1(buffer, offered, needed, returned);
7774         case 2:
7775                 return enumports_level_2(buffer, offered, needed, returned);
7776         default:
7777                 return WERR_UNKNOWN_LEVEL;
7778         }
7779 }
7780
7781 /****************************************************************************
7782 ****************************************************************************/
7783
7784 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7785                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7786                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7787                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7788                                 POLICY_HND *handle)
7789 {
7790         NT_PRINTER_INFO_LEVEL *printer = NULL;
7791         fstring name;
7792         int     snum;
7793         WERROR err = WERR_OK;
7794
7795         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7796                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7797                 return WERR_NOMEM;
7798         }
7799
7800         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7801         if (!convert_printer_info(info, printer, 2)) {
7802                 free_a_printer(&printer, 2);
7803                 return WERR_NOMEM;
7804         }
7805
7806         /* check to see if the printer already exists */
7807
7808         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7809                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7810                         printer->info_2->sharename));
7811                 free_a_printer(&printer, 2);
7812                 return WERR_PRINTER_ALREADY_EXISTS;
7813         }
7814
7815         /* FIXME!!!  smbd should check to see if the driver is installed before
7816            trying to add a printer like this  --jerry */
7817
7818         if (*lp_addprinter_cmd() ) {
7819                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7820                                        printer) ) {
7821                         free_a_printer(&printer,2);
7822                         return WERR_ACCESS_DENIED;
7823                 }
7824         } else {
7825                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7826                         "smb.conf parameter \"addprinter command\" is defined. This"
7827                         "parameter must exist for this call to succeed\n",
7828                         printer->info_2->sharename ));
7829         }
7830
7831         /* use our primary netbios name since get_a_printer() will convert
7832            it to what the client expects on a case by case basis */
7833
7834         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7835              printer->info_2->sharename);
7836
7837
7838         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7839                 free_a_printer(&printer,2);
7840                 return WERR_ACCESS_DENIED;
7841         }
7842
7843         /* you must be a printer admin to add a new printer */
7844         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7845                 free_a_printer(&printer,2);
7846                 return WERR_ACCESS_DENIED;
7847         }
7848
7849         /*
7850          * Do sanity check on the requested changes for Samba.
7851          */
7852
7853         if (!check_printer_ok(printer->info_2, snum)) {
7854                 free_a_printer(&printer,2);
7855                 return WERR_INVALID_PARAM;
7856         }
7857
7858         /*
7859          * When a printer is created, the drivername bound to the printer is used
7860          * to lookup previously saved driver initialization info, which is then
7861          * bound to the new printer, simulating what happens in the Windows arch.
7862          */
7863
7864         if (!devmode)
7865         {
7866                 set_driver_init(printer, 2);
7867         }
7868         else
7869         {
7870                 /* A valid devmode was included, convert and link it
7871                 */
7872                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7873
7874                 if (!convert_devicemode(printer->info_2->printername, devmode,
7875                                 &printer->info_2->devmode))
7876                         return  WERR_NOMEM;
7877         }
7878
7879         /* write the ASCII on disk */
7880         err = mod_a_printer(printer, 2);
7881         if (!W_ERROR_IS_OK(err)) {
7882                 free_a_printer(&printer,2);
7883                 return err;
7884         }
7885
7886         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7887                 /* Handle open failed - remove addition. */
7888                 del_a_printer(printer->info_2->sharename);
7889                 free_a_printer(&printer,2);
7890                 return WERR_ACCESS_DENIED;
7891         }
7892
7893         update_c_setprinter(False);
7894         free_a_printer(&printer,2);
7895
7896         return WERR_OK;
7897 }
7898
7899 /****************************************************************************
7900 ****************************************************************************/
7901
7902 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7903 {
7904         UNISTR2 *uni_srv_name = q_u->server_name;
7905         uint32 level = q_u->level;
7906         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7907         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7908         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7909         uint32 user_switch = q_u->user_switch;
7910         SPOOL_USER_CTR *user = &q_u->user_ctr;
7911         POLICY_HND *handle = &r_u->handle;
7912
7913         switch (level) {
7914                 case 1:
7915                         /* we don't handle yet */
7916                         /* but I know what to do ... */
7917                         return WERR_UNKNOWN_LEVEL;
7918                 case 2:
7919                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7920                                                             devmode, sdb,
7921                                                             user_switch, user, handle);
7922                 default:
7923                         return WERR_UNKNOWN_LEVEL;
7924         }
7925 }
7926
7927 /****************************************************************************
7928 ****************************************************************************/
7929
7930 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7931 {
7932         uint32 level = q_u->level;
7933         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7934         WERROR err = WERR_OK;
7935         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7936         fstring driver_name;
7937         uint32 version;
7938
7939         ZERO_STRUCT(driver);
7940
7941         if (!convert_printer_driver_info(info, &driver, level)) {
7942                 err = WERR_NOMEM;
7943                 goto done;
7944         }
7945
7946         DEBUG(5,("Cleaning driver's information\n"));
7947         err = clean_up_driver_struct(p, driver, level);
7948         if (!W_ERROR_IS_OK(err))
7949                 goto done;
7950
7951         DEBUG(5,("Moving driver to final destination\n"));
7952         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7953                                                               &err)) ) {
7954                 goto done;
7955         }
7956
7957         if (add_a_printer_driver(driver, level)!=0) {
7958                 err = WERR_ACCESS_DENIED;
7959                 goto done;
7960         }
7961
7962         switch(level) {
7963         case 3:
7964                 fstrcpy(driver_name,
7965                         driver.info_3->name ? driver.info_3->name : "");
7966                 break;
7967         case 6:
7968                 fstrcpy(driver_name,
7969                         driver.info_6->name ?  driver.info_6->name : "");
7970                 break;
7971         }
7972
7973         /*
7974          * I think this is where he DrvUpgradePrinter() hook would be
7975          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7976          * server.  Right now, we just need to send ourselves a message
7977          * to update each printer bound to this driver.   --jerry
7978          */
7979
7980         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7981                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7982                         driver_name));
7983         }
7984
7985         /*
7986          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7987          * decide if the driver init data should be deleted. The rules are:
7988          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7989          *  2) delete init data only if there is no 2k/Xp driver
7990          *  3) always delete init data
7991          * The generalized rule is always use init data from the highest order driver.
7992          * It is necessary to follow the driver install by an initialization step to
7993          * finish off this process.
7994         */
7995         if (level == 3)
7996                 version = driver.info_3->cversion;
7997         else if (level == 6)
7998                 version = driver.info_6->version;
7999         else
8000                 version = -1;
8001         switch (version) {
8002                 /*
8003                  * 9x printer driver - never delete init data
8004                 */
8005                 case 0:
8006                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
8007                                         driver_name));
8008                         break;
8009
8010                 /*
8011                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
8012                  * there is no 2k/Xp driver init data for this driver name.
8013                 */
8014                 case 2:
8015                 {
8016                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
8017
8018                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
8019                                 /*
8020                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8021                                 */
8022                                 if (!del_driver_init(driver_name))
8023                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
8024                         } else {
8025                                 /*
8026                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8027                                 */
8028                                 free_a_printer_driver(driver1,3);
8029                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
8030                                                 driver_name));
8031                         }
8032                 }
8033                 break;
8034
8035                 /*
8036                  * 2k or Xp printer driver - always delete init data
8037                 */
8038                 case 3:
8039                         if (!del_driver_init(driver_name))
8040                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
8041                         break;
8042
8043                 default:
8044                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
8045                         break;
8046         }
8047
8048
8049 done:
8050         free_a_printer_driver(driver, level);
8051         return err;
8052 }
8053
8054 /********************************************************************
8055  * spoolss_addprinterdriverex
8056  ********************************************************************/
8057
8058 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
8059 {
8060         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
8061         SPOOL_R_ADDPRINTERDRIVER r_u_local;
8062
8063         /*
8064          * we only support the semantics of AddPrinterDriver()
8065          * i.e. only copy files that are newer than existing ones
8066          */
8067
8068         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
8069                 return WERR_ACCESS_DENIED;
8070
8071         ZERO_STRUCT(q_u_local);
8072         ZERO_STRUCT(r_u_local);
8073
8074         /* just pass the information off to _spoolss_addprinterdriver() */
8075         q_u_local.server_name_ptr = q_u->server_name_ptr;
8076         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
8077         q_u_local.level = q_u->level;
8078         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
8079
8080         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
8081 }
8082
8083 /****************************************************************************
8084 ****************************************************************************/
8085
8086 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
8087 {
8088         init_unistr(&info->name, name);
8089 }
8090
8091 /****************************************************************************
8092 ****************************************************************************/
8093
8094 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8095 {
8096         char *path = NULL;
8097         char *long_archi = NULL;
8098         char *servername = NULL;
8099         const char *pservername = NULL;
8100         const char *short_archi;
8101         DRIVER_DIRECTORY_1 *info=NULL;
8102         WERROR result = WERR_OK;
8103         TALLOC_CTX *ctx = talloc_tos();
8104
8105         servername = unistr2_to_ascii_talloc(ctx, name);
8106         if (!servername) {
8107                 return WERR_NOMEM;
8108         }
8109         long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8110         if (!long_archi) {
8111                 return WERR_NOMEM;
8112         }
8113
8114         pservername = canon_servername(servername);
8115
8116         if ( !is_myname_or_ipaddr(pservername))
8117                 return WERR_INVALID_PARAM;
8118
8119         if (!(short_archi = get_short_archi(long_archi)))
8120                 return WERR_INVALID_ENVIRONMENT;
8121
8122         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8123                 return WERR_NOMEM;
8124
8125         path = talloc_asprintf(ctx,
8126                         "\\\\%s\\print$\\%s", pservername, short_archi);
8127         if (!path) {
8128                 result = WERR_NOMEM;
8129                 goto out;
8130         }
8131
8132         DEBUG(4,("printer driver directory: [%s]\n", path));
8133
8134         fill_driverdir_1(info, path);
8135
8136         *needed += spoolss_size_driverdir_info_1(info);
8137
8138         if (*needed > offered) {
8139                 result = WERR_INSUFFICIENT_BUFFER;
8140                 goto out;
8141         }
8142
8143         if (!rpcbuf_alloc_size(buffer, *needed)) {
8144                 result = WERR_NOMEM;
8145                 goto out;
8146         }
8147
8148         smb_io_driverdir_1("", buffer, info, 0);
8149
8150 out:
8151         SAFE_FREE(info);
8152
8153         return result;
8154 }
8155
8156 /****************************************************************************
8157 ****************************************************************************/
8158
8159 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8160 {
8161         UNISTR2 *name = &q_u->name;
8162         UNISTR2 *uni_environment = &q_u->environment;
8163         uint32 level = q_u->level;
8164         RPC_BUFFER *buffer = NULL;
8165         uint32 offered = q_u->offered;
8166         uint32 *needed = &r_u->needed;
8167
8168         /* that's an [in out] buffer */
8169
8170         if (!q_u->buffer && (offered!=0)) {
8171                 return WERR_INVALID_PARAM;
8172         }
8173
8174         if (offered > MAX_RPC_DATA_SIZE) {
8175                 return WERR_INVALID_PARAM;
8176         }
8177
8178         rpcbuf_move(q_u->buffer, &r_u->buffer);
8179         buffer = r_u->buffer;
8180
8181         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8182
8183         *needed=0;
8184
8185         switch(level) {
8186         case 1:
8187                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8188         default:
8189                 return WERR_UNKNOWN_LEVEL;
8190         }
8191 }
8192
8193 /****************************************************************************
8194 ****************************************************************************/
8195
8196 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8197 {
8198         POLICY_HND *handle = &q_u->handle;
8199         uint32 idx               = q_u->index;
8200         uint32 in_value_len      = q_u->valuesize;
8201         uint32 in_data_len       = q_u->datasize;
8202         uint32 *out_max_value_len = &r_u->valuesize;
8203         uint16 **out_value       = &r_u->value;
8204         uint32 *out_value_len    = &r_u->realvaluesize;
8205         uint32 *out_type         = &r_u->type;
8206         uint32 *out_max_data_len = &r_u->datasize;
8207         uint8  **data_out        = &r_u->data;
8208         uint32 *out_data_len     = &r_u->realdatasize;
8209
8210         NT_PRINTER_INFO_LEVEL *printer = NULL;
8211
8212         uint32          biggest_valuesize;
8213         uint32          biggest_datasize;
8214         uint32          data_len;
8215         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8216         int             snum;
8217         WERROR          result;
8218         REGISTRY_VALUE  *val = NULL;
8219         NT_PRINTER_DATA *p_data;
8220         int             i, key_index, num_values;
8221         int             name_length;
8222
8223         *out_type = 0;
8224
8225         *out_max_data_len = 0;
8226         *data_out         = NULL;
8227         *out_data_len     = 0;
8228
8229         DEBUG(5,("spoolss_enumprinterdata\n"));
8230
8231         if (!Printer) {
8232                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8233                 return WERR_BADFID;
8234         }
8235
8236         if (!get_printer_snum(p,handle, &snum, NULL))
8237                 return WERR_BADFID;
8238
8239         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8240         if (!W_ERROR_IS_OK(result))
8241                 return result;
8242
8243         p_data = printer->info_2->data;
8244         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8245
8246         result = WERR_OK;
8247
8248         /*
8249          * The NT machine wants to know the biggest size of value and data
8250          *
8251          * cf: MSDN EnumPrinterData remark section
8252          */
8253
8254         if ( !in_value_len && !in_data_len && (key_index != -1) )
8255         {
8256                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8257
8258                 biggest_valuesize = 0;
8259                 biggest_datasize  = 0;
8260
8261                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8262
8263                 for ( i=0; i<num_values; i++ )
8264                 {
8265                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8266
8267                         name_length = strlen(val->valuename);
8268                         if ( strlen(val->valuename) > biggest_valuesize )
8269                                 biggest_valuesize = name_length;
8270
8271                         if ( val->size > biggest_datasize )
8272                                 biggest_datasize = val->size;
8273
8274                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8275                                 biggest_datasize));
8276                 }
8277
8278                 /* the value is an UNICODE string but real_value_size is the length
8279                    in bytes including the trailing 0 */
8280
8281                 *out_value_len = 2 * (1+biggest_valuesize);
8282                 *out_data_len  = biggest_datasize;
8283
8284                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8285
8286                 goto done;
8287         }
8288
8289         /*
8290          * the value len is wrong in NT sp3
8291          * that's the number of bytes not the number of unicode chars
8292          */
8293
8294         if ( key_index != -1 )
8295                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8296
8297         if ( !val )
8298         {
8299
8300                 /* out_value should default to "" or else NT4 has
8301                    problems unmarshalling the response */
8302
8303                 *out_max_value_len=(in_value_len/sizeof(uint16));
8304
8305                 if (in_value_len) {
8306                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8307                         {
8308                                 result = WERR_NOMEM;
8309                                 goto done;
8310                         }
8311                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8312                 } else {
8313                         *out_value=NULL;
8314                         *out_value_len = 0;
8315                 }
8316
8317                 /* the data is counted in bytes */
8318
8319                 *out_max_data_len = in_data_len;
8320                 *out_data_len     = in_data_len;
8321
8322                 /* only allocate when given a non-zero data_len */
8323
8324                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8325                 {
8326                         result = WERR_NOMEM;
8327                         goto done;
8328                 }
8329
8330                 result = WERR_NO_MORE_ITEMS;
8331         }
8332         else
8333         {
8334                 /*
8335                  * the value is:
8336                  * - counted in bytes in the request
8337                  * - counted in UNICODE chars in the max reply
8338                  * - counted in bytes in the real size
8339                  *
8340                  * take a pause *before* coding not *during* coding
8341                  */
8342
8343                 /* name */
8344                 *out_max_value_len=(in_value_len/sizeof(uint16));
8345                 if (in_value_len) {
8346                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8347                         {
8348                                 result = WERR_NOMEM;
8349                                 goto done;
8350                         }
8351
8352                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8353                 } else {
8354                         *out_value = NULL;
8355                         *out_value_len = 0;
8356                 }
8357
8358                 /* type */
8359
8360                 *out_type = regval_type( val );
8361
8362                 /* data - counted in bytes */
8363
8364                 *out_max_data_len = in_data_len;
8365                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8366                 {
8367                         result = WERR_NOMEM;
8368                         goto done;
8369                 }
8370                 data_len = regval_size(val);
8371                 if ( *data_out && data_len )
8372                         memcpy( *data_out, regval_data_p(val), data_len );
8373                 *out_data_len = data_len;
8374         }
8375
8376 done:
8377         free_a_printer(&printer, 2);
8378         return result;
8379 }
8380
8381 /****************************************************************************
8382 ****************************************************************************/
8383
8384 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8385 {
8386         POLICY_HND              *handle = &q_u->handle;
8387         UNISTR2                 *value = &q_u->value;
8388         uint32                  type = q_u->type;
8389         uint8                   *data = q_u->data;
8390         uint32                  real_len = q_u->real_len;
8391
8392         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8393         int                     snum=0;
8394         WERROR                  status = WERR_OK;
8395         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8396         fstring                 valuename;
8397
8398         DEBUG(5,("spoolss_setprinterdata\n"));
8399
8400         if (!Printer) {
8401                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8402                 return WERR_BADFID;
8403         }
8404
8405         if ( Printer->printer_type == SPLHND_SERVER ) {
8406                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8407                 return WERR_INVALID_PARAM;
8408         }
8409
8410         if (!get_printer_snum(p,handle, &snum, NULL))
8411                 return WERR_BADFID;
8412
8413         /*
8414          * Access check : NT returns "access denied" if you make a
8415          * SetPrinterData call without the necessary privildge.
8416          * we were originally returning OK if nothing changed
8417          * which made Win2k issue **a lot** of SetPrinterData
8418          * when connecting to a printer  --jerry
8419          */
8420
8421         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8422         {
8423                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8424                 status = WERR_ACCESS_DENIED;
8425                 goto done;
8426         }
8427
8428         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8429         if (!W_ERROR_IS_OK(status))
8430                 return status;
8431
8432         unistr2_to_ascii(valuename, value, sizeof(valuename));
8433
8434         /*
8435          * When client side code sets a magic printer data key, detect it and save
8436          * the current printer data and the magic key's data (its the DEVMODE) for
8437          * future printer/driver initializations.
8438          */
8439         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8440         {
8441                 /* Set devmode and printer initialization info */
8442                 status = save_driver_init( printer, 2, data, real_len );
8443
8444                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8445         }
8446         else
8447         {
8448         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8449                                         type, data, real_len );
8450                 if ( W_ERROR_IS_OK(status) )
8451                         status = mod_a_printer(printer, 2);
8452         }
8453
8454 done:
8455         free_a_printer(&printer, 2);
8456
8457         return status;
8458 }
8459
8460 /****************************************************************************
8461 ****************************************************************************/
8462
8463 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8464 {
8465         POLICY_HND      *handle = &q_u->handle;
8466         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8467         int             snum;
8468
8469         DEBUG(5,("_spoolss_resetprinter\n"));
8470
8471         /*
8472          * All we do is to check to see if the handle and queue is valid.
8473          * This call really doesn't mean anything to us because we only
8474          * support RAW printing.   --jerry
8475          */
8476
8477         if (!Printer) {
8478                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8479                 return WERR_BADFID;
8480         }
8481
8482         if (!get_printer_snum(p,handle, &snum, NULL))
8483                 return WERR_BADFID;
8484
8485
8486         /* blindly return success */
8487         return WERR_OK;
8488 }
8489
8490 /****************************************************************
8491  _spoolss_DeletePrinterData
8492 ****************************************************************/
8493
8494 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8495                                   struct spoolss_DeletePrinterData *r)
8496 {
8497         POLICY_HND      *handle = r->in.handle;
8498         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8499         int             snum=0;
8500         WERROR          status = WERR_OK;
8501         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8502
8503         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8504
8505         if (!Printer) {
8506                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8507                         OUR_HANDLE(handle)));
8508                 return WERR_BADFID;
8509         }
8510
8511         if (!get_printer_snum(p, handle, &snum, NULL))
8512                 return WERR_BADFID;
8513
8514         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8515                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8516                         "printer properties change denied by handle\n"));
8517                 return WERR_ACCESS_DENIED;
8518         }
8519
8520         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8521         if (!W_ERROR_IS_OK(status))
8522                 return status;
8523
8524         if (!r->in.value_name) {
8525                 free_a_printer(&printer, 2);
8526                 return WERR_NOMEM;
8527         }
8528
8529         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8530                                         r->in.value_name );
8531
8532         if ( W_ERROR_IS_OK(status) )
8533                 mod_a_printer( printer, 2 );
8534
8535         free_a_printer(&printer, 2);
8536
8537         return status;
8538 }
8539
8540 /****************************************************************
8541  _spoolss_AddForm
8542 ****************************************************************/
8543
8544 WERROR _spoolss_AddForm(pipes_struct *p,
8545                         struct spoolss_AddForm *r)
8546 {
8547         POLICY_HND *handle = r->in.handle;
8548         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8549         nt_forms_struct tmpForm;
8550         int snum;
8551         WERROR status = WERR_OK;
8552         NT_PRINTER_INFO_LEVEL *printer = NULL;
8553
8554         int count=0;
8555         nt_forms_struct *list=NULL;
8556         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8557
8558         DEBUG(5,("_spoolss_AddForm\n"));
8559
8560         if (!Printer) {
8561                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8562                         OUR_HANDLE(handle)));
8563                 return WERR_BADFID;
8564         }
8565
8566
8567         /* forms can be added on printer of on the print server handle */
8568
8569         if ( Printer->printer_type == SPLHND_PRINTER )
8570         {
8571                 if (!get_printer_snum(p,handle, &snum, NULL))
8572                         return WERR_BADFID;
8573
8574                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8575                 if (!W_ERROR_IS_OK(status))
8576                         goto done;
8577         }
8578
8579         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8580                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8581                 status = WERR_ACCESS_DENIED;
8582                 goto done;
8583         }
8584
8585         /* can't add if builtin */
8586
8587         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8588                 status = WERR_FILE_EXISTS;
8589                 goto done;
8590         }
8591
8592         count = get_ntforms(&list);
8593
8594         if(!add_a_form(&list, form, &count)) {
8595                 status =  WERR_NOMEM;
8596                 goto done;
8597         }
8598
8599         write_ntforms(&list, count);
8600
8601         /*
8602          * ChangeID must always be set if this is a printer
8603          */
8604
8605         if ( Printer->printer_type == SPLHND_PRINTER )
8606                 status = mod_a_printer(printer, 2);
8607
8608 done:
8609         if ( printer )
8610                 free_a_printer(&printer, 2);
8611         SAFE_FREE(list);
8612
8613         return status;
8614 }
8615
8616 /****************************************************************
8617  _spoolss_DeleteForm
8618 ****************************************************************/
8619
8620 WERROR _spoolss_DeleteForm(pipes_struct *p,
8621                            struct spoolss_DeleteForm *r)
8622 {
8623         POLICY_HND *handle = r->in.handle;
8624         const char *form_name = r->in.form_name;
8625         nt_forms_struct tmpForm;
8626         int count=0;
8627         nt_forms_struct *list=NULL;
8628         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8629         int snum;
8630         WERROR status = WERR_OK;
8631         NT_PRINTER_INFO_LEVEL *printer = NULL;
8632
8633         DEBUG(5,("_spoolss_DeleteForm\n"));
8634
8635         if (!Printer) {
8636                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8637                         OUR_HANDLE(handle)));
8638                 return WERR_BADFID;
8639         }
8640
8641         /* forms can be deleted on printer of on the print server handle */
8642
8643         if ( Printer->printer_type == SPLHND_PRINTER )
8644         {
8645                 if (!get_printer_snum(p,handle, &snum, NULL))
8646                         return WERR_BADFID;
8647
8648                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8649                 if (!W_ERROR_IS_OK(status))
8650                         goto done;
8651         }
8652
8653         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8654                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8655                 status = WERR_ACCESS_DENIED;
8656                 goto done;
8657         }
8658
8659         /* can't delete if builtin */
8660
8661         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8662                 status = WERR_INVALID_PARAM;
8663                 goto done;
8664         }
8665
8666         count = get_ntforms(&list);
8667
8668         if ( !delete_a_form(&list, form_name, &count, &status ))
8669                 goto done;
8670
8671         /*
8672          * ChangeID must always be set if this is a printer
8673          */
8674
8675         if ( Printer->printer_type == SPLHND_PRINTER )
8676                 status = mod_a_printer(printer, 2);
8677
8678 done:
8679         if ( printer )
8680                 free_a_printer(&printer, 2);
8681         SAFE_FREE(list);
8682
8683         return status;
8684 }
8685
8686 /****************************************************************
8687  _spoolss_SetForm
8688 ****************************************************************/
8689
8690 WERROR _spoolss_SetForm(pipes_struct *p,
8691                         struct spoolss_SetForm *r)
8692 {
8693         POLICY_HND *handle = r->in.handle;
8694         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8695         nt_forms_struct tmpForm;
8696         int snum;
8697         WERROR status = WERR_OK;
8698         NT_PRINTER_INFO_LEVEL *printer = NULL;
8699
8700         int count=0;
8701         nt_forms_struct *list=NULL;
8702         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8703
8704         DEBUG(5,("_spoolss_SetForm\n"));
8705
8706         if (!Printer) {
8707                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8708                         OUR_HANDLE(handle)));
8709                 return WERR_BADFID;
8710         }
8711
8712         /* forms can be modified on printer of on the print server handle */
8713
8714         if ( Printer->printer_type == SPLHND_PRINTER )
8715         {
8716                 if (!get_printer_snum(p,handle, &snum, NULL))
8717                         return WERR_BADFID;
8718
8719                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8720                 if (!W_ERROR_IS_OK(status))
8721                         goto done;
8722         }
8723
8724         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8725                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8726                 status = WERR_ACCESS_DENIED;
8727                 goto done;
8728         }
8729
8730         /* can't set if builtin */
8731         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8732                 status = WERR_INVALID_PARAM;
8733                 goto done;
8734         }
8735
8736         count = get_ntforms(&list);
8737         update_a_form(&list, form, count);
8738         write_ntforms(&list, count);
8739
8740         /*
8741          * ChangeID must always be set if this is a printer
8742          */
8743
8744         if ( Printer->printer_type == SPLHND_PRINTER )
8745                 status = mod_a_printer(printer, 2);
8746
8747
8748 done:
8749         if ( printer )
8750                 free_a_printer(&printer, 2);
8751         SAFE_FREE(list);
8752
8753         return status;
8754 }
8755
8756 /****************************************************************************
8757  enumprintprocessors level 1.
8758 ****************************************************************************/
8759
8760 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8761 {
8762         PRINTPROCESSOR_1 *info_1=NULL;
8763         WERROR result = WERR_OK;
8764
8765         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8766                 return WERR_NOMEM;
8767
8768         (*returned) = 0x1;
8769
8770         init_unistr(&info_1->name, "winprint");
8771
8772         *needed += spoolss_size_printprocessor_info_1(info_1);
8773
8774         if (*needed > offered) {
8775                 result = WERR_INSUFFICIENT_BUFFER;
8776                 goto out;
8777         }
8778
8779         if (!rpcbuf_alloc_size(buffer, *needed)) {
8780                 result = WERR_NOMEM;
8781                 goto out;
8782         }
8783
8784         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8785
8786 out:
8787         SAFE_FREE(info_1);
8788
8789         if ( !W_ERROR_IS_OK(result) )
8790                 *returned = 0;
8791
8792         return result;
8793 }
8794
8795 /****************************************************************************
8796 ****************************************************************************/
8797
8798 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8799 {
8800         uint32 level = q_u->level;
8801         RPC_BUFFER *buffer = NULL;
8802         uint32 offered = q_u->offered;
8803         uint32 *needed = &r_u->needed;
8804         uint32 *returned = &r_u->returned;
8805
8806         /* that's an [in out] buffer */
8807
8808         if (!q_u->buffer && (offered!=0)) {
8809                 return WERR_INVALID_PARAM;
8810         }
8811
8812         if (offered > MAX_RPC_DATA_SIZE) {
8813                 return WERR_INVALID_PARAM;
8814         }
8815
8816         rpcbuf_move(q_u->buffer, &r_u->buffer);
8817         buffer = r_u->buffer;
8818
8819         DEBUG(5,("spoolss_enumprintprocessors\n"));
8820
8821         /*
8822          * Enumerate the print processors ...
8823          *
8824          * Just reply with "winprint", to keep NT happy
8825          * and I can use my nice printer checker.
8826          */
8827
8828         *returned=0;
8829         *needed=0;
8830
8831         switch (level) {
8832         case 1:
8833                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8834         default:
8835                 return WERR_UNKNOWN_LEVEL;
8836         }
8837 }
8838
8839 /****************************************************************************
8840  enumprintprocdatatypes level 1.
8841 ****************************************************************************/
8842
8843 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8844 {
8845         PRINTPROCDATATYPE_1 *info_1=NULL;
8846         WERROR result = WERR_OK;
8847
8848         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8849                 return WERR_NOMEM;
8850
8851         (*returned) = 0x1;
8852
8853         init_unistr(&info_1->name, "RAW");
8854
8855         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8856
8857         if (*needed > offered) {
8858                 result = WERR_INSUFFICIENT_BUFFER;
8859                 goto out;
8860         }
8861
8862         if (!rpcbuf_alloc_size(buffer, *needed)) {
8863                 result = WERR_NOMEM;
8864                 goto out;
8865         }
8866
8867         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8868
8869 out:
8870         SAFE_FREE(info_1);
8871
8872         if ( !W_ERROR_IS_OK(result) )
8873                 *returned = 0;
8874
8875         return result;
8876 }
8877
8878 /****************************************************************************
8879 ****************************************************************************/
8880
8881 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8882 {
8883         uint32 level = q_u->level;
8884         RPC_BUFFER *buffer = NULL;
8885         uint32 offered = q_u->offered;
8886         uint32 *needed = &r_u->needed;
8887         uint32 *returned = &r_u->returned;
8888
8889         /* that's an [in out] buffer */
8890
8891         if (!q_u->buffer && (offered!=0)) {
8892                 return WERR_INVALID_PARAM;
8893         }
8894
8895         if (offered > MAX_RPC_DATA_SIZE) {
8896                 return WERR_INVALID_PARAM;
8897         }
8898
8899         rpcbuf_move(q_u->buffer, &r_u->buffer);
8900         buffer = r_u->buffer;
8901
8902         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8903
8904         *returned=0;
8905         *needed=0;
8906
8907         switch (level) {
8908         case 1:
8909                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8910         default:
8911                 return WERR_UNKNOWN_LEVEL;
8912         }
8913 }
8914
8915 /****************************************************************************
8916  enumprintmonitors level 1.
8917 ****************************************************************************/
8918
8919 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8920 {
8921         PRINTMONITOR_1 *info_1;
8922         WERROR result = WERR_OK;
8923         int i;
8924
8925         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8926                 return WERR_NOMEM;
8927
8928         *returned = 2;
8929
8930         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8931         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8932
8933         for ( i=0; i<*returned; i++ ) {
8934                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8935         }
8936
8937         if (*needed > offered) {
8938                 result = WERR_INSUFFICIENT_BUFFER;
8939                 goto out;
8940         }
8941
8942         if (!rpcbuf_alloc_size(buffer, *needed)) {
8943                 result = WERR_NOMEM;
8944                 goto out;
8945         }
8946
8947         for ( i=0; i<*returned; i++ ) {
8948                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8949         }
8950
8951 out:
8952         SAFE_FREE(info_1);
8953
8954         if ( !W_ERROR_IS_OK(result) )
8955                 *returned = 0;
8956
8957         return result;
8958 }
8959
8960 /****************************************************************************
8961  enumprintmonitors level 2.
8962 ****************************************************************************/
8963
8964 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8965 {
8966         PRINTMONITOR_2 *info_2;
8967         WERROR result = WERR_OK;
8968         int i;
8969
8970         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8971                 return WERR_NOMEM;
8972
8973         *returned = 2;
8974
8975         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8976         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8977         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8978
8979         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8980         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8981         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8982
8983         for ( i=0; i<*returned; i++ ) {
8984                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8985         }
8986
8987         if (*needed > offered) {
8988                 result = WERR_INSUFFICIENT_BUFFER;
8989                 goto out;
8990         }
8991
8992         if (!rpcbuf_alloc_size(buffer, *needed)) {
8993                 result = WERR_NOMEM;
8994                 goto out;
8995         }
8996
8997         for ( i=0; i<*returned; i++ ) {
8998                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8999         }
9000
9001 out:
9002         SAFE_FREE(info_2);
9003
9004         if ( !W_ERROR_IS_OK(result) )
9005                 *returned = 0;
9006
9007         return result;
9008 }
9009
9010 /****************************************************************************
9011 ****************************************************************************/
9012
9013 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
9014 {
9015         uint32 level = q_u->level;
9016         RPC_BUFFER *buffer = NULL;
9017         uint32 offered = q_u->offered;
9018         uint32 *needed = &r_u->needed;
9019         uint32 *returned = &r_u->returned;
9020
9021         /* that's an [in out] buffer */
9022
9023         if (!q_u->buffer && (offered!=0)) {
9024                 return WERR_INVALID_PARAM;
9025         }
9026
9027         if (offered > MAX_RPC_DATA_SIZE) {
9028                 return WERR_INVALID_PARAM;
9029         }
9030
9031         rpcbuf_move(q_u->buffer, &r_u->buffer);
9032         buffer = r_u->buffer;
9033
9034         DEBUG(5,("spoolss_enumprintmonitors\n"));
9035
9036         /*
9037          * Enumerate the print monitors ...
9038          *
9039          * Just reply with "Local Port", to keep NT happy
9040          * and I can use my nice printer checker.
9041          */
9042
9043         *returned=0;
9044         *needed=0;
9045
9046         switch (level) {
9047         case 1:
9048                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9049         case 2:
9050                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9051         default:
9052                 return WERR_UNKNOWN_LEVEL;
9053         }
9054 }
9055
9056 /****************************************************************************
9057 ****************************************************************************/
9058
9059 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9060                              NT_PRINTER_INFO_LEVEL *ntprinter,
9061                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9062                              uint32 *needed)
9063 {
9064         int i=0;
9065         bool found=False;
9066         JOB_INFO_1 *info_1=NULL;
9067         WERROR result = WERR_OK;
9068
9069         info_1=SMB_MALLOC_P(JOB_INFO_1);
9070
9071         if (info_1 == NULL) {
9072                 return WERR_NOMEM;
9073         }
9074
9075         for (i=0; i<count && found==False; i++) {
9076                 if ((*queue)[i].job==(int)jobid)
9077                         found=True;
9078         }
9079
9080         if (found==False) {
9081                 SAFE_FREE(info_1);
9082                 /* NT treats not found as bad param... yet another bad choice */
9083                 return WERR_INVALID_PARAM;
9084         }
9085
9086         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9087
9088         *needed += spoolss_size_job_info_1(info_1);
9089
9090         if (*needed > offered) {
9091                 result = WERR_INSUFFICIENT_BUFFER;
9092                 goto out;
9093         }
9094
9095         if (!rpcbuf_alloc_size(buffer, *needed)) {
9096                 result = WERR_NOMEM;
9097                 goto out;
9098         }
9099
9100         smb_io_job_info_1("", buffer, info_1, 0);
9101
9102 out:
9103         SAFE_FREE(info_1);
9104
9105         return result;
9106 }
9107
9108 /****************************************************************************
9109 ****************************************************************************/
9110
9111 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9112                              NT_PRINTER_INFO_LEVEL *ntprinter,
9113                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9114                              uint32 *needed)
9115 {
9116         int             i = 0;
9117         bool            found = False;
9118         JOB_INFO_2      *info_2;
9119         WERROR          result;
9120         DEVICEMODE      *devmode = NULL;
9121         NT_DEVICEMODE   *nt_devmode = NULL;
9122
9123         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9124                 return WERR_NOMEM;
9125
9126         ZERO_STRUCTP(info_2);
9127
9128         for ( i=0; i<count && found==False; i++ )
9129         {
9130                 if ((*queue)[i].job == (int)jobid)
9131                         found = True;
9132         }
9133
9134         if ( !found ) {
9135                 /* NT treats not found as bad param... yet another bad
9136                    choice */
9137                 result = WERR_INVALID_PARAM;
9138                 goto done;
9139         }
9140
9141         /*
9142          * if the print job does not have a DEVMODE associated with it,
9143          * just use the one for the printer. A NULL devicemode is not
9144          *  a failure condition
9145          */
9146
9147         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9148                 devmode = construct_dev_mode(lp_const_servicename(snum));
9149         else {
9150                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9151                         ZERO_STRUCTP( devmode );
9152                         convert_nt_devicemode( devmode, nt_devmode );
9153                 }
9154         }
9155
9156         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9157
9158         *needed += spoolss_size_job_info_2(info_2);
9159
9160         if (*needed > offered) {
9161                 result = WERR_INSUFFICIENT_BUFFER;
9162                 goto done;
9163         }
9164
9165         if (!rpcbuf_alloc_size(buffer, *needed)) {
9166                 result = WERR_NOMEM;
9167                 goto done;
9168         }
9169
9170         smb_io_job_info_2("", buffer, info_2, 0);
9171
9172         result = WERR_OK;
9173
9174  done:
9175         /* Cleanup allocated memory */
9176
9177         free_job_info_2(info_2);        /* Also frees devmode */
9178         SAFE_FREE(info_2);
9179
9180         return result;
9181 }
9182
9183 /****************************************************************************
9184 ****************************************************************************/
9185
9186 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9187 {
9188         POLICY_HND *handle = &q_u->handle;
9189         uint32 jobid = q_u->jobid;
9190         uint32 level = q_u->level;
9191         RPC_BUFFER *buffer = NULL;
9192         uint32 offered = q_u->offered;
9193         uint32 *needed = &r_u->needed;
9194         WERROR          wstatus = WERR_OK;
9195         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9196         int snum;
9197         int count;
9198         print_queue_struct      *queue = NULL;
9199         print_status_struct prt_status;
9200
9201         /* that's an [in out] buffer */
9202
9203         if (!q_u->buffer && (offered!=0)) {
9204                 return WERR_INVALID_PARAM;
9205         }
9206
9207         if (offered > MAX_RPC_DATA_SIZE) {
9208                 return WERR_INVALID_PARAM;
9209         }
9210
9211         rpcbuf_move(q_u->buffer, &r_u->buffer);
9212         buffer = r_u->buffer;
9213
9214         DEBUG(5,("spoolss_getjob\n"));
9215
9216         *needed = 0;
9217
9218         if (!get_printer_snum(p, handle, &snum, NULL))
9219                 return WERR_BADFID;
9220
9221         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9222         if ( !W_ERROR_IS_OK(wstatus) )
9223                 return wstatus;
9224
9225         count = print_queue_status(snum, &queue, &prt_status);
9226
9227         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9228                      count, prt_status.status, prt_status.message));
9229
9230         switch ( level ) {
9231         case 1:
9232                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9233                                 buffer, offered, needed);
9234                         break;
9235         case 2:
9236                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9237                                 buffer, offered, needed);
9238                         break;
9239         default:
9240                         wstatus = WERR_UNKNOWN_LEVEL;
9241                         break;
9242         }
9243
9244         SAFE_FREE(queue);
9245         free_a_printer( &ntprinter, 2 );
9246
9247         return wstatus;
9248 }
9249
9250 /****************************************************************
9251  _spoolss_GetPrinterDataEx
9252
9253  From MSDN documentation of GetPrinterDataEx: pass request
9254  to GetPrinterData if key is "PrinterDriverData".
9255 ****************************************************************/
9256
9257 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9258                                  struct spoolss_GetPrinterDataEx *r)
9259 {
9260         POLICY_HND      *handle = r->in.handle;
9261         uint8           *data = NULL;
9262         const char      *keyname = r->in.key_name;
9263         const char      *valuename = r->in.value_name;
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         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9274                 keyname, valuename));
9275
9276         /* in case of problem, return some default values */
9277
9278         *r->out.needed  = 0;
9279         *r->out.type    = 0;
9280
9281         if (!Printer) {
9282                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9283                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9284                 status = WERR_BADFID;
9285                 goto done;
9286         }
9287
9288         /* Is the handle to a printer or to the server? */
9289
9290         if (Printer->printer_type == SPLHND_SERVER) {
9291                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9292                         "Not implemented for server handles yet\n"));
9293                 status = WERR_INVALID_PARAM;
9294                 goto done;
9295         }
9296
9297         if ( !get_printer_snum(p,handle, &snum, NULL) )
9298                 return WERR_BADFID;
9299
9300         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9301         if ( !W_ERROR_IS_OK(status) )
9302                 goto done;
9303
9304         /* check to see if the keyname is valid */
9305         if ( !strlen(keyname) ) {
9306                 status = WERR_INVALID_PARAM;
9307                 goto done;
9308         }
9309
9310         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9311                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9312                         "Invalid keyname [%s]\n", keyname ));
9313                 free_a_printer( &printer, 2 );
9314                 status = WERR_BADFILE;
9315                 goto done;
9316         }
9317
9318         /* When given a new keyname, we should just create it */
9319
9320         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9321                                      r->out.type, &data, r->out.needed,
9322                                      r->in.offered );
9323
9324         if (*r->out.needed > r->in.offered) {
9325                 status = WERR_MORE_DATA;
9326         }
9327
9328         if (W_ERROR_IS_OK(status)) {
9329                 memcpy(r->out.buffer, data, r->in.offered);
9330         }
9331
9332 done:
9333         if ( printer )
9334         free_a_printer( &printer, 2 );
9335
9336         return status;
9337 }
9338
9339 /****************************************************************
9340  _spoolss_SetPrinterDataEx
9341 ****************************************************************/
9342
9343 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9344                                  struct spoolss_SetPrinterDataEx *r)
9345 {
9346         POLICY_HND              *handle = r->in.handle;
9347         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9348         int                     snum = 0;
9349         WERROR                  status = WERR_OK;
9350         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9351         char                    *oid_string;
9352
9353         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9354
9355         /* From MSDN documentation of SetPrinterDataEx: pass request to
9356            SetPrinterData if key is "PrinterDriverData" */
9357
9358         if (!Printer) {
9359                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9360                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9361                 return WERR_BADFID;
9362         }
9363
9364         if ( Printer->printer_type == SPLHND_SERVER ) {
9365                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9366                         "Not implemented for server handles yet\n"));
9367                 return WERR_INVALID_PARAM;
9368         }
9369
9370         if ( !get_printer_snum(p,handle, &snum, NULL) )
9371                 return WERR_BADFID;
9372
9373         /*
9374          * Access check : NT returns "access denied" if you make a
9375          * SetPrinterData call without the necessary privildge.
9376          * we were originally returning OK if nothing changed
9377          * which made Win2k issue **a lot** of SetPrinterData
9378          * when connecting to a printer  --jerry
9379          */
9380
9381         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9382         {
9383                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9384                         "change denied by handle access permissions\n"));
9385                 return WERR_ACCESS_DENIED;
9386         }
9387
9388         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9389         if (!W_ERROR_IS_OK(status))
9390                 return status;
9391
9392         /* check for OID in valuename */
9393
9394         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9395         {
9396                 *oid_string = '\0';
9397                 oid_string++;
9398         }
9399
9400         /* save the registry data */
9401
9402         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9403                                      r->in.type, r->in.buffer, r->in.offered );
9404
9405         if ( W_ERROR_IS_OK(status) )
9406         {
9407                 /* save the OID if one was specified */
9408                 if ( oid_string ) {
9409                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9410                                 r->in.key_name, SPOOL_OID_KEY);
9411                         if (!str) {
9412                                 return WERR_NOMEM;
9413                         }
9414
9415                         /*
9416                          * I'm not checking the status here on purpose.  Don't know
9417                          * if this is right, but I'm returning the status from the
9418                          * previous set_printer_dataex() call.  I have no idea if
9419                          * this is right.    --jerry
9420                          */
9421
9422                         set_printer_dataex( printer, str, r->in.value_name,
9423                                             REG_SZ, (uint8 *)oid_string,
9424                                             strlen(oid_string)+1 );
9425                 }
9426
9427                 status = mod_a_printer(printer, 2);
9428         }
9429
9430         free_a_printer(&printer, 2);
9431
9432         return status;
9433 }
9434
9435 /****************************************************************
9436  _spoolss_DeletePrinterDataEx
9437 ****************************************************************/
9438
9439 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9440                                     struct spoolss_DeletePrinterDataEx *r)
9441 {
9442         POLICY_HND      *handle = r->in.handle;
9443         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9444         int             snum=0;
9445         WERROR          status = WERR_OK;
9446         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9447
9448         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9449
9450         if (!Printer) {
9451                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9452                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9453                 return WERR_BADFID;
9454         }
9455
9456         if (!get_printer_snum(p, handle, &snum, NULL))
9457                 return WERR_BADFID;
9458
9459         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9460                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9461                         "printer properties change denied by handle\n"));
9462                 return WERR_ACCESS_DENIED;
9463         }
9464
9465         if (!r->in.value_name || !r->in.key_name) {
9466                 return WERR_NOMEM;
9467         }
9468
9469         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9470         if (!W_ERROR_IS_OK(status))
9471                 return status;
9472
9473         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9474
9475         if ( W_ERROR_IS_OK(status) )
9476                 mod_a_printer( printer, 2 );
9477
9478         free_a_printer(&printer, 2);
9479
9480         return status;
9481 }
9482
9483 /********************************************************************
9484  * spoolss_enumprinterkey
9485  ********************************************************************/
9486
9487
9488 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9489 {
9490         fstring         key;
9491         fstring         *keynames = NULL;
9492         uint16          *enumkeys = NULL;
9493         int             num_keys;
9494         int             printerkey_len;
9495         POLICY_HND      *handle = &q_u->handle;
9496         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9497         NT_PRINTER_DATA *data;
9498         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9499         int             snum = 0;
9500         WERROR          status = WERR_BADFILE;
9501
9502
9503         DEBUG(4,("_spoolss_enumprinterkey\n"));
9504
9505         if (!Printer) {
9506                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9507                 return WERR_BADFID;
9508         }
9509
9510         if ( !get_printer_snum(p,handle, &snum, NULL) )
9511                 return WERR_BADFID;
9512
9513         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9514         if (!W_ERROR_IS_OK(status))
9515                 return status;
9516
9517         /* get the list of subkey names */
9518
9519         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9520         data = printer->info_2->data;
9521
9522         num_keys = get_printer_subkeys( data, key, &keynames );
9523
9524         if ( num_keys == -1 ) {
9525                 status = WERR_BADFILE;
9526                 goto done;
9527         }
9528
9529         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9530
9531         r_u->needed = printerkey_len*2;
9532
9533         if ( q_u->size < r_u->needed ) {
9534                 status = WERR_MORE_DATA;
9535                 goto done;
9536         }
9537
9538         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9539                 status = WERR_NOMEM;
9540                 goto done;
9541         }
9542
9543         status = WERR_OK;
9544
9545         if ( q_u->size < r_u->needed )
9546                 status = WERR_MORE_DATA;
9547
9548 done:
9549         free_a_printer( &printer, 2 );
9550         SAFE_FREE( keynames );
9551
9552         return status;
9553 }
9554
9555 /****************************************************************
9556  _spoolss_DeletePrinterKey
9557 ****************************************************************/
9558
9559 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9560                                  struct spoolss_DeletePrinterKey *r)
9561 {
9562         POLICY_HND              *handle = r->in.handle;
9563         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9564         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9565         int                     snum=0;
9566         WERROR                  status;
9567
9568         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9569
9570         if (!Printer) {
9571                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9572                         OUR_HANDLE(handle)));
9573                 return WERR_BADFID;
9574         }
9575
9576         /* if keyname == NULL, return error */
9577
9578         if ( !r->in.key_name )
9579                 return WERR_INVALID_PARAM;
9580
9581         if (!get_printer_snum(p, handle, &snum, NULL))
9582                 return WERR_BADFID;
9583
9584         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9585                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9586                         "printer properties change denied by handle\n"));
9587                 return WERR_ACCESS_DENIED;
9588         }
9589
9590         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9591         if (!W_ERROR_IS_OK(status))
9592                 return status;
9593
9594         /* delete the key and all subneys */
9595
9596         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9597
9598         if ( W_ERROR_IS_OK(status) )
9599                 status = mod_a_printer(printer, 2);
9600
9601         free_a_printer( &printer, 2 );
9602
9603         return status;
9604 }
9605
9606
9607 /********************************************************************
9608  * spoolss_enumprinterdataex
9609  ********************************************************************/
9610
9611 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9612 {
9613         POLICY_HND      *handle = &q_u->handle;
9614         uint32          in_size = q_u->size;
9615         uint32          num_entries,
9616                         needed;
9617         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9618         PRINTER_ENUM_VALUES     *enum_values = NULL;
9619         NT_PRINTER_DATA         *p_data;
9620         fstring         key;
9621         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9622         int             snum;
9623         WERROR          result;
9624         int             key_index;
9625         int             i;
9626         REGISTRY_VALUE  *val;
9627         char            *value_name;
9628         uint32          data_len;
9629
9630
9631         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9632
9633         if (!Printer) {
9634                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9635                 return WERR_BADFID;
9636         }
9637
9638         /*
9639          * first check for a keyname of NULL or "".  Win2k seems to send
9640          * this a lot and we should send back WERR_INVALID_PARAM
9641          * no need to spend time looking up the printer in this case.
9642          * --jerry
9643          */
9644
9645         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9646         if ( !strlen(key) ) {
9647                 result = WERR_INVALID_PARAM;
9648                 goto done;
9649         }
9650
9651         /* get the printer off of disk */
9652
9653         if (!get_printer_snum(p,handle, &snum, NULL))
9654                 return WERR_BADFID;
9655
9656         ZERO_STRUCT(printer);
9657         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9658         if (!W_ERROR_IS_OK(result))
9659                 return result;
9660
9661         /* now look for a match on the key name */
9662
9663         p_data = printer->info_2->data;
9664
9665         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9666         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9667         {
9668                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9669                 result = WERR_INVALID_PARAM;
9670                 goto done;
9671         }
9672
9673         result = WERR_OK;
9674         needed = 0;
9675
9676         /* allocate the memory for the array of pointers -- if necessary */
9677
9678         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9679         if ( num_entries )
9680         {
9681                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9682                 {
9683                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9684                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9685                         result = WERR_NOMEM;
9686                         goto done;
9687                 }
9688
9689                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9690         }
9691
9692         /*
9693          * loop through all params and build the array to pass
9694          * back to the  client
9695          */
9696
9697         for ( i=0; i<num_entries; i++ )
9698         {
9699                 /* lookup the registry value */
9700
9701                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9702                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9703
9704                 /* copy the data */
9705
9706                 value_name = regval_name( val );
9707                 init_unistr( &enum_values[i].valuename, value_name );
9708                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9709                 enum_values[i].type      = regval_type( val );
9710
9711                 data_len = regval_size( val );
9712                 if ( data_len ) {
9713                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9714                         {
9715                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9716                                         data_len ));
9717                                 result = WERR_NOMEM;
9718                                 goto done;
9719                         }
9720                 }
9721                 enum_values[i].data_len = data_len;
9722
9723                 /* keep track of the size of the array in bytes */
9724
9725                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9726         }
9727
9728         /* housekeeping information in the reply */
9729
9730         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9731          * the hand marshalled container size is a multiple
9732          * of 4 bytes for RPC alignment.
9733          */
9734
9735         if (needed % 4) {
9736                 needed += 4-(needed % 4);
9737         }
9738
9739         r_u->needed     = needed;
9740         r_u->returned   = num_entries;
9741
9742         if (needed > in_size) {
9743                 result = WERR_MORE_DATA;
9744                 goto done;
9745         }
9746
9747         /* copy data into the reply */
9748
9749         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9750            response buffer size is != the offered buffer size
9751
9752                 r_u->ctr.size           = r_u->needed;
9753         */
9754         r_u->ctr.size           = in_size;
9755
9756         r_u->ctr.size_of_array  = r_u->returned;
9757         r_u->ctr.values         = enum_values;
9758
9759 done:
9760         if ( printer )
9761         free_a_printer(&printer, 2);
9762
9763         return result;
9764 }
9765
9766 /****************************************************************************
9767 ****************************************************************************/
9768
9769 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9770 {
9771         init_unistr(&info->name, name);
9772 }
9773
9774 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9775                                                  UNISTR2 *environment,
9776                                                  RPC_BUFFER *buffer,
9777                                                  uint32 offered,
9778                                                  uint32 *needed)
9779 {
9780         char *long_archi = NULL;
9781         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9782         WERROR result = WERR_OK;
9783         TALLOC_CTX *ctx = talloc_tos();
9784
9785         long_archi = unistr2_to_ascii_talloc(ctx, environment);
9786         if (!long_archi) {
9787                 return WERR_NOMEM;
9788         }
9789
9790         if (!get_short_archi(long_archi))
9791                 return WERR_INVALID_ENVIRONMENT;
9792
9793         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9794                 return WERR_NOMEM;
9795
9796         fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9797
9798         *needed += spoolss_size_printprocessordirectory_info_1(info);
9799
9800         if (*needed > offered) {
9801                 result = WERR_INSUFFICIENT_BUFFER;
9802                 goto out;
9803         }
9804
9805         if (!rpcbuf_alloc_size(buffer, *needed)) {
9806                 result = WERR_INSUFFICIENT_BUFFER;
9807                 goto out;
9808         }
9809
9810         smb_io_printprocessordirectory_1("", buffer, info, 0);
9811
9812 out:
9813         SAFE_FREE(info);
9814
9815         return result;
9816 }
9817
9818 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9819 {
9820         uint32 level = q_u->level;
9821         RPC_BUFFER *buffer = NULL;
9822         uint32 offered = q_u->offered;
9823         uint32 *needed = &r_u->needed;
9824         WERROR result;
9825
9826         /* that's an [in out] buffer */
9827
9828         if (!q_u->buffer && (offered!=0)) {
9829                 return WERR_INVALID_PARAM;
9830         }
9831
9832         if (offered > MAX_RPC_DATA_SIZE) {
9833                 return WERR_INVALID_PARAM;
9834         }
9835
9836         rpcbuf_move(q_u->buffer, &r_u->buffer);
9837         buffer = r_u->buffer;
9838
9839         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9840
9841         *needed=0;
9842
9843         switch(level) {
9844         case 1:
9845                 result = getprintprocessordirectory_level_1
9846                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9847                 break;
9848         default:
9849                 result = WERR_UNKNOWN_LEVEL;
9850         }
9851
9852         return result;
9853 }
9854
9855 /*******************************************************************
9856  Streams the monitor UI DLL name in UNICODE
9857 *******************************************************************/
9858
9859 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9860                                 RPC_BUFFER *out, uint32 *needed )
9861 {
9862         const char *dllname = "tcpmonui.dll";
9863
9864         *needed = (strlen(dllname)+1) * 2;
9865
9866         if ( rpcbuf_get_size(out) < *needed ) {
9867                 return WERR_INSUFFICIENT_BUFFER;
9868         }
9869
9870         if ( !make_monitorui_buf( out, dllname ) ) {
9871                 return WERR_NOMEM;
9872         }
9873
9874         return WERR_OK;
9875 }
9876
9877 /*******************************************************************
9878  Create a new TCP/IP port
9879 *******************************************************************/
9880
9881 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9882                               RPC_BUFFER *out, uint32 *needed )
9883 {
9884         NT_PORT_DATA_1 port1;
9885         TALLOC_CTX *ctx = talloc_tos();
9886         char *device_uri = NULL;
9887
9888         ZERO_STRUCT( port1 );
9889
9890         /* convert to our internal port data structure */
9891
9892         if ( !convert_port_data_1( &port1, in ) ) {
9893                 return WERR_NOMEM;
9894         }
9895
9896         /* create the device URI and call the add_port_hook() */
9897
9898         switch ( port1.protocol ) {
9899         case PORT_PROTOCOL_DIRECT:
9900                 device_uri = talloc_asprintf(ctx,
9901                                 "socket://%s:%d/", port1.hostaddr, port1.port );
9902                 break;
9903
9904         case PORT_PROTOCOL_LPR:
9905                 device_uri = talloc_asprintf(ctx,
9906                         "lpr://%s/%s", port1.hostaddr, port1.queue );
9907                 break;
9908
9909         default:
9910                 return WERR_UNKNOWN_PORT;
9911         }
9912
9913         if (!device_uri) {
9914                 return WERR_NOMEM;
9915         }
9916
9917         return add_port_hook(ctx, token, port1.name, device_uri );
9918 }
9919
9920 /*******************************************************************
9921 *******************************************************************/
9922
9923 struct xcv_api_table xcvtcp_cmds[] = {
9924         { "MonitorUI",  xcvtcp_monitorui },
9925         { "AddPort",    xcvtcp_addport},
9926         { NULL,         NULL }
9927 };
9928
9929 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9930                                       RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9931                                       uint32 *needed )
9932 {
9933         int i;
9934
9935         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9936
9937         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9938                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9939                         return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9940         }
9941
9942         return WERR_BADFUNC;
9943 }
9944
9945 /*******************************************************************
9946 *******************************************************************/
9947 #if 0   /* don't support management using the "Local Port" monitor */
9948
9949 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9950                                   RPC_BUFFER *out, uint32 *needed )
9951 {
9952         const char *dllname = "localui.dll";
9953
9954         *needed = (strlen(dllname)+1) * 2;
9955
9956         if ( rpcbuf_get_size(out) < *needed ) {
9957                 return WERR_INSUFFICIENT_BUFFER;
9958         }
9959
9960         if ( !make_monitorui_buf( out, dllname )) {
9961                 return WERR_NOMEM;
9962         }
9963
9964         return WERR_OK;
9965 }
9966
9967 /*******************************************************************
9968 *******************************************************************/
9969
9970 struct xcv_api_table xcvlocal_cmds[] = {
9971         { "MonitorUI",  xcvlocal_monitorui },
9972         { NULL,         NULL }
9973 };
9974 #else
9975 struct xcv_api_table xcvlocal_cmds[] = {
9976         { NULL,         NULL }
9977 };
9978 #endif
9979
9980
9981
9982 /*******************************************************************
9983 *******************************************************************/
9984
9985 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9986                                         RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9987                                         uint32 *needed )
9988 {
9989         int i;
9990
9991         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9992
9993         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9994                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9995                         return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9996         }
9997         return WERR_BADFUNC;
9998 }
9999
10000 /*******************************************************************
10001 *******************************************************************/
10002
10003 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
10004 {
10005         Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
10006         fstring command;
10007
10008         if (!Printer) {
10009                 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
10010                 return WERR_BADFID;
10011         }
10012
10013         /* Has to be a handle to the TCP/IP port monitor */
10014
10015         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10016                 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
10017                 return WERR_BADFID;
10018         }
10019
10020         /* requires administrative access to the server */
10021
10022         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10023                 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
10024                 return WERR_ACCESS_DENIED;
10025         }
10026
10027         /* Get the command name.  There's numerous commands supported by the
10028            TCPMON interface. */
10029
10030         rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
10031                 q_u->dataname.uni_str_len*2, 0);
10032
10033         /* Allocate the outgoing buffer */
10034
10035         if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
10036                 return WERR_NOMEM;
10037
10038         switch ( Printer->printer_type ) {
10039         case SPLHND_PORTMON_TCP:
10040                 return process_xcvtcp_command( p->server_info->ptok, command,
10041                         &q_u->indata, &r_u->outdata, &r_u->needed );
10042         case SPLHND_PORTMON_LOCAL:
10043                 return process_xcvlocal_command( p->server_info->ptok, command,
10044                         &q_u->indata, &r_u->outdata, &r_u->needed );
10045         }
10046
10047         return WERR_INVALID_PRINT_MONITOR;
10048 }
10049
10050 /****************************************************************
10051  _spoolss_AddPrintProcessor
10052 ****************************************************************/
10053
10054 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10055                                   struct spoolss_AddPrintProcessor *r)
10056 {
10057         /* for now, just indicate success and ignore the add.  We'll
10058            automatically set the winprint processor for printer
10059            entries later.  Used to debug the LexMark Optra S 1855 PCL
10060            driver --jerry */
10061
10062         return WERR_OK;
10063 }
10064
10065 /****************************************************************
10066  _spoolss_EnumPrinters
10067 ****************************************************************/
10068
10069 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10070                              struct spoolss_EnumPrinters *r)
10071 {
10072         p->rng_fault_state = true;
10073         return WERR_NOT_SUPPORTED;
10074 }
10075
10076 /****************************************************************
10077  _spoolss_GetJob
10078 ****************************************************************/
10079
10080 WERROR _spoolss_GetJob(pipes_struct *p,
10081                        struct spoolss_GetJob *r)
10082 {
10083         p->rng_fault_state = true;
10084         return WERR_NOT_SUPPORTED;
10085 }
10086
10087 /****************************************************************
10088  _spoolss_EnumJobs
10089 ****************************************************************/
10090
10091 WERROR _spoolss_EnumJobs(pipes_struct *p,
10092                          struct spoolss_EnumJobs *r)
10093 {
10094         p->rng_fault_state = true;
10095         return WERR_NOT_SUPPORTED;
10096 }
10097
10098 /****************************************************************
10099  _spoolss_AddPrinter
10100 ****************************************************************/
10101
10102 WERROR _spoolss_AddPrinter(pipes_struct *p,
10103                            struct spoolss_AddPrinter *r)
10104 {
10105         p->rng_fault_state = true;
10106         return WERR_NOT_SUPPORTED;
10107 }
10108
10109 /****************************************************************
10110  _spoolss_SetPrinter
10111 ****************************************************************/
10112
10113 WERROR _spoolss_SetPrinter(pipes_struct *p,
10114                            struct spoolss_SetPrinter *r)
10115 {
10116         p->rng_fault_state = true;
10117         return WERR_NOT_SUPPORTED;
10118 }
10119
10120 /****************************************************************
10121  _spoolss_GetPrinter
10122 ****************************************************************/
10123
10124 WERROR _spoolss_GetPrinter(pipes_struct *p,
10125                            struct spoolss_GetPrinter *r)
10126 {
10127         p->rng_fault_state = true;
10128         return WERR_NOT_SUPPORTED;
10129 }
10130
10131 /****************************************************************
10132  _spoolss_AddPrinterDriver
10133 ****************************************************************/
10134
10135 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10136                                  struct spoolss_AddPrinterDriver *r)
10137 {
10138         p->rng_fault_state = true;
10139         return WERR_NOT_SUPPORTED;
10140 }
10141
10142 /****************************************************************
10143  _spoolss_EnumPrinterDrivers
10144 ****************************************************************/
10145
10146 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10147                                    struct spoolss_EnumPrinterDrivers *r)
10148 {
10149         p->rng_fault_state = true;
10150         return WERR_NOT_SUPPORTED;
10151 }
10152
10153 /****************************************************************
10154  _spoolss_GetPrinterDriver
10155 ****************************************************************/
10156
10157 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10158                                  struct spoolss_GetPrinterDriver *r)
10159 {
10160         p->rng_fault_state = true;
10161         return WERR_NOT_SUPPORTED;
10162 }
10163
10164 /****************************************************************
10165  _spoolss_GetPrinterDriverDirectory
10166 ****************************************************************/
10167
10168 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
10169                                           struct spoolss_GetPrinterDriverDirectory *r)
10170 {
10171         p->rng_fault_state = true;
10172         return WERR_NOT_SUPPORTED;
10173 }
10174
10175 /****************************************************************
10176  _spoolss_EnumPrintProcessors
10177 ****************************************************************/
10178
10179 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10180                                     struct spoolss_EnumPrintProcessors *r)
10181 {
10182         p->rng_fault_state = true;
10183         return WERR_NOT_SUPPORTED;
10184 }
10185
10186 /****************************************************************
10187  _spoolss_GetPrintProcessorDirectory
10188 ****************************************************************/
10189
10190 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10191                                            struct spoolss_GetPrintProcessorDirectory *r)
10192 {
10193         p->rng_fault_state = true;
10194         return WERR_NOT_SUPPORTED;
10195 }
10196
10197 /****************************************************************
10198  _spoolss_ReadPrinter
10199 ****************************************************************/
10200
10201 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10202                             struct spoolss_ReadPrinter *r)
10203 {
10204         p->rng_fault_state = true;
10205         return WERR_NOT_SUPPORTED;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_GetPrinterData
10210 ****************************************************************/
10211
10212 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10213                                struct spoolss_GetPrinterData *r)
10214 {
10215         p->rng_fault_state = true;
10216         return WERR_NOT_SUPPORTED;
10217 }
10218
10219 /****************************************************************
10220  _spoolss_SetPrinterData
10221 ****************************************************************/
10222
10223 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10224                                struct spoolss_SetPrinterData *r)
10225 {
10226         p->rng_fault_state = true;
10227         return WERR_NOT_SUPPORTED;
10228 }
10229
10230 /****************************************************************
10231  _spoolss_WaitForPrinterChange
10232 ****************************************************************/
10233
10234 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10235                                      struct spoolss_WaitForPrinterChange *r)
10236 {
10237         p->rng_fault_state = true;
10238         return WERR_NOT_SUPPORTED;
10239 }
10240
10241 /****************************************************************
10242  _spoolss_EnumForms
10243 ****************************************************************/
10244
10245 WERROR _spoolss_EnumForms(pipes_struct *p,
10246                           struct spoolss_EnumForms *r)
10247 {
10248         p->rng_fault_state = true;
10249         return WERR_NOT_SUPPORTED;
10250 }
10251
10252 /****************************************************************
10253  _spoolss_EnumPorts
10254 ****************************************************************/
10255
10256 WERROR _spoolss_EnumPorts(pipes_struct *p,
10257                           struct spoolss_EnumPorts *r)
10258 {
10259         p->rng_fault_state = true;
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_EnumMonitors
10265 ****************************************************************/
10266
10267 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10268                              struct spoolss_EnumMonitors *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_AddPort
10276 ****************************************************************/
10277
10278 WERROR _spoolss_AddPort(pipes_struct *p,
10279                         struct spoolss_AddPort *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_ConfigurePort
10287 ****************************************************************/
10288
10289 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10290                               struct spoolss_ConfigurePort *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_DeletePort
10298 ****************************************************************/
10299
10300 WERROR _spoolss_DeletePort(pipes_struct *p,
10301                            struct spoolss_DeletePort *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_CreatePrinterIC
10309 ****************************************************************/
10310
10311 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10312                                 struct spoolss_CreatePrinterIC *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_PlayGDIScriptOnPrinterIC
10320 ****************************************************************/
10321
10322 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10323                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }
10328
10329 /****************************************************************
10330  _spoolss_DeletePrinterIC
10331 ****************************************************************/
10332
10333 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10334                                 struct spoolss_DeletePrinterIC *r)
10335 {
10336         p->rng_fault_state = true;
10337         return WERR_NOT_SUPPORTED;
10338 }
10339
10340 /****************************************************************
10341  _spoolss_AddPrinterConnection
10342 ****************************************************************/
10343
10344 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10345                                      struct spoolss_AddPrinterConnection *r)
10346 {
10347         p->rng_fault_state = true;
10348         return WERR_NOT_SUPPORTED;
10349 }
10350
10351 /****************************************************************
10352  _spoolss_DeletePrinterConnection
10353 ****************************************************************/
10354
10355 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10356                                         struct spoolss_DeletePrinterConnection *r)
10357 {
10358         p->rng_fault_state = true;
10359         return WERR_NOT_SUPPORTED;
10360 }
10361
10362 /****************************************************************
10363  _spoolss_PrinterMessageBox
10364 ****************************************************************/
10365
10366 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10367                                   struct spoolss_PrinterMessageBox *r)
10368 {
10369         p->rng_fault_state = true;
10370         return WERR_NOT_SUPPORTED;
10371 }
10372
10373 /****************************************************************
10374  _spoolss_AddMonitor
10375 ****************************************************************/
10376
10377 WERROR _spoolss_AddMonitor(pipes_struct *p,
10378                            struct spoolss_AddMonitor *r)
10379 {
10380         p->rng_fault_state = true;
10381         return WERR_NOT_SUPPORTED;
10382 }
10383
10384 /****************************************************************
10385  _spoolss_DeleteMonitor
10386 ****************************************************************/
10387
10388 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10389                               struct spoolss_DeleteMonitor *r)
10390 {
10391         p->rng_fault_state = true;
10392         return WERR_NOT_SUPPORTED;
10393 }
10394
10395 /****************************************************************
10396  _spoolss_DeletePrintProcessor
10397 ****************************************************************/
10398
10399 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10400                                      struct spoolss_DeletePrintProcessor *r)
10401 {
10402         p->rng_fault_state = true;
10403         return WERR_NOT_SUPPORTED;
10404 }
10405
10406 /****************************************************************
10407  _spoolss_AddPrintProvidor
10408 ****************************************************************/
10409
10410 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10411                                  struct spoolss_AddPrintProvidor *r)
10412 {
10413         p->rng_fault_state = true;
10414         return WERR_NOT_SUPPORTED;
10415 }
10416
10417 /****************************************************************
10418  _spoolss_DeletePrintProvidor
10419 ****************************************************************/
10420
10421 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10422                                     struct spoolss_DeletePrintProvidor *r)
10423 {
10424         p->rng_fault_state = true;
10425         return WERR_NOT_SUPPORTED;
10426 }
10427
10428 /****************************************************************
10429  _spoolss_EnumPrintProcDataTypes
10430 ****************************************************************/
10431
10432 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10433                                        struct spoolss_EnumPrintProcDataTypes *r)
10434 {
10435         p->rng_fault_state = true;
10436         return WERR_NOT_SUPPORTED;
10437 }
10438
10439 /****************************************************************
10440  _spoolss_ResetPrinter
10441 ****************************************************************/
10442
10443 WERROR _spoolss_ResetPrinter(pipes_struct *p,
10444                              struct spoolss_ResetPrinter *r)
10445 {
10446         p->rng_fault_state = true;
10447         return WERR_NOT_SUPPORTED;
10448 }
10449
10450 /****************************************************************
10451  _spoolss_GetPrinterDriver2
10452 ****************************************************************/
10453
10454 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10455                                   struct spoolss_GetPrinterDriver2 *r)
10456 {
10457         p->rng_fault_state = true;
10458         return WERR_NOT_SUPPORTED;
10459 }
10460
10461 /****************************************************************
10462  _spoolss_FindFirstPrinterChangeNotification
10463 ****************************************************************/
10464
10465 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10466                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10467 {
10468         p->rng_fault_state = true;
10469         return WERR_NOT_SUPPORTED;
10470 }
10471
10472 /****************************************************************
10473  _spoolss_FindNextPrinterChangeNotification
10474 ****************************************************************/
10475
10476 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10477                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10478 {
10479         p->rng_fault_state = true;
10480         return WERR_NOT_SUPPORTED;
10481 }
10482
10483 /****************************************************************
10484  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10485 ****************************************************************/
10486
10487 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10488                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10489 {
10490         p->rng_fault_state = true;
10491         return WERR_NOT_SUPPORTED;
10492 }
10493
10494 /****************************************************************
10495  _spoolss_ReplyOpenPrinter
10496 ****************************************************************/
10497
10498 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10499                                  struct spoolss_ReplyOpenPrinter *r)
10500 {
10501         p->rng_fault_state = true;
10502         return WERR_NOT_SUPPORTED;
10503 }
10504
10505 /****************************************************************
10506  _spoolss_RouterReplyPrinter
10507 ****************************************************************/
10508
10509 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10510                                    struct spoolss_RouterReplyPrinter *r)
10511 {
10512         p->rng_fault_state = true;
10513         return WERR_NOT_SUPPORTED;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_ReplyClosePrinter
10518 ****************************************************************/
10519
10520 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10521                                   struct spoolss_ReplyClosePrinter *r)
10522 {
10523         p->rng_fault_state = true;
10524         return WERR_NOT_SUPPORTED;
10525 }
10526
10527 /****************************************************************
10528  _spoolss_AddPortEx
10529 ****************************************************************/
10530
10531 WERROR _spoolss_AddPortEx(pipes_struct *p,
10532                           struct spoolss_AddPortEx *r)
10533 {
10534         p->rng_fault_state = true;
10535         return WERR_NOT_SUPPORTED;
10536 }
10537
10538 /****************************************************************
10539  _spoolss_RouterFindFirstPrinterChangeNotification
10540 ****************************************************************/
10541
10542 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10543                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10544 {
10545         p->rng_fault_state = true;
10546         return WERR_NOT_SUPPORTED;
10547 }
10548
10549 /****************************************************************
10550  _spoolss_SpoolerInit
10551 ****************************************************************/
10552
10553 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10554                             struct spoolss_SpoolerInit *r)
10555 {
10556         p->rng_fault_state = true;
10557         return WERR_NOT_SUPPORTED;
10558 }
10559
10560 /****************************************************************
10561  _spoolss_ResetPrinterEx
10562 ****************************************************************/
10563
10564 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10565                                struct spoolss_ResetPrinterEx *r)
10566 {
10567         p->rng_fault_state = true;
10568         return WERR_NOT_SUPPORTED;
10569 }
10570
10571 /****************************************************************
10572  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10573 ****************************************************************/
10574
10575 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10576                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10577 {
10578         p->rng_fault_state = true;
10579         return WERR_NOT_SUPPORTED;
10580 }
10581
10582 /****************************************************************
10583  _spoolss_RouterReplyPrinterEx
10584 ****************************************************************/
10585
10586 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10587                                      struct spoolss_RouterReplyPrinterEx *r)
10588 {
10589         p->rng_fault_state = true;
10590         return WERR_NOT_SUPPORTED;
10591 }
10592
10593 /****************************************************************
10594  _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10595 ****************************************************************/
10596
10597 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10598                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
10599 {
10600         p->rng_fault_state = true;
10601         return WERR_NOT_SUPPORTED;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_44
10606 ****************************************************************/
10607
10608 WERROR _spoolss_44(pipes_struct *p,
10609                    struct spoolss_44 *r)
10610 {
10611         p->rng_fault_state = true;
10612         return WERR_NOT_SUPPORTED;
10613 }
10614
10615 /****************************************************************
10616  _spoolss_AddPrinterEx
10617 ****************************************************************/
10618
10619 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
10620                              struct spoolss_AddPrinterEx *r)
10621 {
10622         p->rng_fault_state = true;
10623         return WERR_NOT_SUPPORTED;
10624 }
10625
10626 /****************************************************************
10627  _spoolss_47
10628 ****************************************************************/
10629
10630 WERROR _spoolss_47(pipes_struct *p,
10631                    struct spoolss_47 *r)
10632 {
10633         p->rng_fault_state = true;
10634         return WERR_NOT_SUPPORTED;
10635 }
10636
10637 /****************************************************************
10638  _spoolss_EnumPrinterData
10639 ****************************************************************/
10640
10641 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10642                                 struct spoolss_EnumPrinterData *r)
10643 {
10644         p->rng_fault_state = true;
10645         return WERR_NOT_SUPPORTED;
10646 }
10647
10648 /****************************************************************
10649  _spoolss_4a
10650 ****************************************************************/
10651
10652 WERROR _spoolss_4a(pipes_struct *p,
10653                    struct spoolss_4a *r)
10654 {
10655         p->rng_fault_state = true;
10656         return WERR_NOT_SUPPORTED;
10657 }
10658
10659 /****************************************************************
10660  _spoolss_4b
10661 ****************************************************************/
10662
10663 WERROR _spoolss_4b(pipes_struct *p,
10664                    struct spoolss_4b *r)
10665 {
10666         p->rng_fault_state = true;
10667         return WERR_NOT_SUPPORTED;
10668 }
10669
10670 /****************************************************************
10671  _spoolss_4c
10672 ****************************************************************/
10673
10674 WERROR _spoolss_4c(pipes_struct *p,
10675                    struct spoolss_4c *r)
10676 {
10677         p->rng_fault_state = true;
10678         return WERR_NOT_SUPPORTED;
10679 }
10680
10681 /****************************************************************
10682  _spoolss_EnumPrinterDataEx
10683 ****************************************************************/
10684
10685 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10686                                   struct spoolss_EnumPrinterDataEx *r)
10687 {
10688         p->rng_fault_state = true;
10689         return WERR_NOT_SUPPORTED;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_EnumPrinterKey
10694 ****************************************************************/
10695
10696 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10697                                struct spoolss_EnumPrinterKey *r)
10698 {
10699         p->rng_fault_state = true;
10700         return WERR_NOT_SUPPORTED;
10701 }
10702
10703 /****************************************************************
10704  _spoolss_53
10705 ****************************************************************/
10706
10707 WERROR _spoolss_53(pipes_struct *p,
10708                    struct spoolss_53 *r)
10709 {
10710         p->rng_fault_state = true;
10711         return WERR_NOT_SUPPORTED;
10712 }
10713
10714 /****************************************************************
10715  _spoolss_55
10716 ****************************************************************/
10717
10718 WERROR _spoolss_55(pipes_struct *p,
10719                    struct spoolss_55 *r)
10720 {
10721         p->rng_fault_state = true;
10722         return WERR_NOT_SUPPORTED;
10723 }
10724
10725 /****************************************************************
10726  _spoolss_56
10727 ****************************************************************/
10728
10729 WERROR _spoolss_56(pipes_struct *p,
10730                    struct spoolss_56 *r)
10731 {
10732         p->rng_fault_state = true;
10733         return WERR_NOT_SUPPORTED;
10734 }
10735
10736 /****************************************************************
10737  _spoolss_57
10738 ****************************************************************/
10739
10740 WERROR _spoolss_57(pipes_struct *p,
10741                    struct spoolss_57 *r)
10742 {
10743         p->rng_fault_state = true;
10744         return WERR_NOT_SUPPORTED;
10745 }
10746
10747 /****************************************************************
10748  _spoolss_XcvData
10749 ****************************************************************/
10750
10751 WERROR _spoolss_XcvData(pipes_struct *p,
10752                         struct spoolss_XcvData *r)
10753 {
10754         p->rng_fault_state = true;
10755         return WERR_NOT_SUPPORTED;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_AddPrinterDriverEx
10760 ****************************************************************/
10761
10762 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10763                                    struct spoolss_AddPrinterDriverEx *r)
10764 {
10765         p->rng_fault_state = true;
10766         return WERR_NOT_SUPPORTED;
10767 }
10768
10769 /****************************************************************
10770  _spoolss_5a
10771 ****************************************************************/
10772
10773 WERROR _spoolss_5a(pipes_struct *p,
10774                    struct spoolss_5a *r)
10775 {
10776         p->rng_fault_state = true;
10777         return WERR_NOT_SUPPORTED;
10778 }
10779
10780 /****************************************************************
10781  _spoolss_5b
10782 ****************************************************************/
10783
10784 WERROR _spoolss_5b(pipes_struct *p,
10785                    struct spoolss_5b *r)
10786 {
10787         p->rng_fault_state = true;
10788         return WERR_NOT_SUPPORTED;
10789 }
10790
10791 /****************************************************************
10792  _spoolss_5c
10793 ****************************************************************/
10794
10795 WERROR _spoolss_5c(pipes_struct *p,
10796                    struct spoolss_5c *r)
10797 {
10798         p->rng_fault_state = true;
10799         return WERR_NOT_SUPPORTED;
10800 }
10801
10802 /****************************************************************
10803  _spoolss_5d
10804 ****************************************************************/
10805
10806 WERROR _spoolss_5d(pipes_struct *p,
10807                    struct spoolss_5d *r)
10808 {
10809         p->rng_fault_state = true;
10810         return WERR_NOT_SUPPORTED;
10811 }
10812
10813 /****************************************************************
10814  _spoolss_5e
10815 ****************************************************************/
10816
10817 WERROR _spoolss_5e(pipes_struct *p,
10818                    struct spoolss_5e *r)
10819 {
10820         p->rng_fault_state = true;
10821         return WERR_NOT_SUPPORTED;
10822 }
10823
10824 /****************************************************************
10825  _spoolss_5f
10826 ****************************************************************/
10827
10828 WERROR _spoolss_5f(pipes_struct *p,
10829                    struct spoolss_5f *r)
10830 {
10831         p->rng_fault_state = true;
10832         return WERR_NOT_SUPPORTED;
10833 }
10834