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