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