r8022: * implement default actions rather than having to define functions
[ira/wip.git] / source / registry / reg_printing.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /* Implementation of registry virtual views for printing information */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /* registrt paths used in the print_registry[] */
29
30 #define KEY_MONITORS            "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/MONITORS"
31 #define KEY_FORMS               "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
32 #define KEY_CONTROL_PRINTERS    "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
33 #define KEY_DRIVERS             "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS/.../DRIVERS"
34 #define KEY_PRINTPROC           "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS/.../PRINTPROC"
35 #define KEY_ENVIRONMENTS        "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
36 #define KEY_CONTROL_PRINT       "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
37 #define KEY_WINNT_PRINTERS      "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
38 #define KEY_WINNT_PRINT         "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT"
39 #define KEY_PORTS               "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS"
40
41 /* callback table for various registry paths below the ones we service in this module */
42         
43 struct reg_dyn_tree {
44         /* full key path in normalized form */
45         const char *path;
46         
47         /* callbscks for fetch/store operations */
48         int ( *fetch_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
49         BOOL (*store_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
50         int  (*fetch_values)  ( const char *path, REGVAL_CTR *values );
51         BOOL (*store_values)  ( const char *path, REGVAL_CTR *values );
52 };
53
54 #if 0   /* UNUSED */
55
56 /**********************************************************************
57  handle enumeration of subkeys below KEY_PRINTING\Printers
58  *********************************************************************/
59  
60 static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys )
61 {
62         int n_services = lp_numservices();      
63         int snum;
64         fstring sname;
65         int i;
66         int num_subkeys = 0;
67         char *keystr, *key2 = NULL;
68         char *base, *new_path;
69         NT_PRINTER_INFO_LEVEL *printer = NULL;
70         fstring *subkey_names = NULL;
71         
72         DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" ));
73         
74         if ( !key )
75         {
76                 /* enumerate all printers */
77                 
78                 for (snum=0; snum<n_services; snum++) {
79                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
80                                 continue;
81
82                         /* don't report the [printers] share */
83
84                         if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
85                                 continue;
86                                 
87                         fstrcpy( sname, lp_servicename(snum) );
88                                 
89                         regsubkey_ctr_addkey( subkeys, sname );
90                 }
91                 
92                 num_subkeys = regsubkey_ctr_numkeys( subkeys );
93                 goto done;
94         }
95
96         /* get information for a specific printer */
97         
98         key2 = SMB_STRDUP( key );
99         keystr = key2;
100         reg_split_path( keystr, &base, &new_path );
101
102                 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, base) ) )
103                 goto done;
104
105         num_subkeys = get_printer_subkeys( &printer->info_2->data, new_path?new_path:"", &subkey_names );
106         
107         for ( i=0; i<num_subkeys; i++ )
108                 regsubkey_ctr_addkey( subkeys, subkey_names[i] );
109         
110         free_a_printer( &printer, 2 );
111                         
112         /* no other subkeys below here */
113
114 done:   
115         SAFE_FREE( key2 );
116         SAFE_FREE( subkey_names );
117         
118         return num_subkeys;
119 }
120
121 /**********************************************************************
122  handle enumeration of values below KEY_PRINTING\Printers
123  *********************************************************************/
124  
125 static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
126 {
127         int             num_values = 0;
128         char            *keystr, *key2 = NULL;
129         char            *base, *new_path;
130         NT_PRINTER_INFO_LEVEL   *printer = NULL;
131         NT_PRINTER_INFO_LEVEL_2 *info2;
132         DEVICEMODE      *devmode;
133         prs_struct      prs;
134         uint32          offset;
135         int             snum;
136         fstring         printername; 
137         NT_PRINTER_DATA *p_data;
138         int             i, key_index;
139         UNISTR2         data;
140         
141         /* 
142          * Theres are tw cases to deal with here
143          * (1) enumeration of printer_info_2 values
144          * (2) enumeration of the PrinterDriverData subney
145          */
146          
147         if ( !key ) {
148                 /* top level key has no values */
149                 goto done;
150         }
151         
152         key2 = SMB_STRDUP( key );
153         keystr = key2;
154         reg_split_path( keystr, &base, &new_path );
155         
156         fstrcpy( printername, base );
157         
158         if ( !new_path ) {
159                 char *p;
160                 uint32 printer_status = PRINTER_STATUS_OK;
161
162                 /* we are dealing with the printer itself */
163
164                 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
165                         goto done;
166
167                 info2 = printer->info_2;
168                 
169
170                 regval_ctr_addvalue( val, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
171                 regval_ctr_addvalue( val, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
172                 regval_ctr_addvalue( val, "ChangeID",         REG_DWORD, (char*)&info2->changeid,         sizeof(info2->changeid) );
173                 regval_ctr_addvalue( val, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
174
175                 /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
176                 regval_ctr_addvalue( val, "Status",           REG_DWORD, (char*)&printer_status,          sizeof(info2->status) );
177
178                 regval_ctr_addvalue( val, "StartTime",        REG_DWORD, (char*)&info2->starttime,        sizeof(info2->starttime) );
179                 regval_ctr_addvalue( val, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );
180
181                 /* strip the \\server\ from this string */
182                 if ( !(p = strrchr( info2->printername, '\\' ) ) )
183                         p = info2->printername;
184                 else
185                         p++;
186                 init_unistr2( &data, p, UNI_STR_TERMINATE);
187                 regval_ctr_addvalue( val, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
188
189                 init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
190                 regval_ctr_addvalue( val, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
191
192                 init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
193                 regval_ctr_addvalue( val, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
194
195                 init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
196                 regval_ctr_addvalue( val, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
197
198                 init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
199                 regval_ctr_addvalue( val, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
200
201                 init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
202                 regval_ctr_addvalue( val, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
203
204                 init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
205                 regval_ctr_addvalue( val, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
206
207                 init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
208                 regval_ctr_addvalue( val, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
209
210                 init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
211                 regval_ctr_addvalue( val, "Print Processor",  REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
212
213                 init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
214                 regval_ctr_addvalue( val, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
215
216                 
217                 /* use a prs_struct for converting the devmode and security 
218                    descriptor to REG_BINARY */
219                 
220                 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(val), MARSHALL);
221
222                 /* stream the device mode */
223                 
224                 snum = lp_servicenumber(info2->sharename);
225                 if ( (devmode = construct_dev_mode( snum )) != NULL )
226                 {                       
227                         if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
228                         
229                                 offset = prs_offset( &prs );
230                                 
231                                 regval_ctr_addvalue( val, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
232                         }
233                         
234                         
235                 }
236                 
237                 prs_mem_clear( &prs );
238                 prs_set_offset( &prs, 0 );
239                 
240                 if ( info2->secdesc_buf && info2->secdesc_buf->len ) 
241                 {
242                         if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
243                         
244                                 offset = prs_offset( &prs );
245                         
246                                 regval_ctr_addvalue( val, "Security", REG_BINARY, prs_data_p(&prs), offset );
247                         }
248                 }
249
250                 prs_mem_free( &prs );
251                 
252                 num_values = regval_ctr_numvals( val ); 
253                 
254                 goto done;
255                 
256         }
257                 
258         /* now enumerate the key */
259         
260         if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
261                 goto done;
262         
263         /* iterate over all printer data and fill the regval container */
264         
265         p_data = &printer->info_2->data;
266         if ( (key_index = lookup_printerkey( p_data, new_path )) == -1  ) {
267                 DEBUG(10,("print_subpath_values_printer: Unknown keyname [%s]\n", new_path));
268                 goto done;
269         }
270         
271         num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
272         
273         for ( i=0; i<num_values; i++ )
274                 regval_ctr_copyvalue( val, regval_ctr_specific_value(&p_data->keys[key_index].values, i) );
275                         
276
277 done:
278         if ( printer )
279                 free_a_printer( &printer, 2 );
280                 
281         SAFE_FREE( key2 ); 
282         
283         return num_values;
284 }
285
286 /**********************************************************************
287  Routine to handle enumeration of subkeys and values 
288  below KEY_PRINTING (depending on whether or not subkeys/val are 
289  valid pointers. 
290  *********************************************************************/
291  
292 static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CTR *val )
293 {
294         int result = 0;
295         char *p, *base;
296         int i;
297         
298         DEBUG(10,("handle_printing_subpath: key=>[%s]\n", key ));
299         
300         /* 
301          * break off the first part of the path 
302          * topmost base **must** be one of the strings 
303          * in top_level_keys[]
304          */
305         
306         reg_split_path( key, &base, &p);
307                 
308         for ( i=0; i<MAX_TOP_LEVEL_KEYS; i++ ) {
309                 if ( StrCaseCmp( top_level_keys[i], base ) == 0 )
310                         break;
311         }
312         
313         DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base, i));  
314                 
315         if ( !(i < MAX_TOP_LEVEL_KEYS) )
316                 return -1;
317                                                 
318         /* Call routine to handle each top level key */
319         switch ( i )
320         {
321                 case KEY_INDEX_ENVIR:
322                         if ( subkeys )
323                                 print_subpath_environments( p, subkeys );
324                         if ( val )
325                                 print_subpath_values_environments( p, val );
326                         break;
327                 
328                 case KEY_INDEX_FORMS:
329                         if ( subkeys )
330                                 print_subpath_forms( p, subkeys );
331                         if ( val )
332                                 print_subpath_values_forms( p, val );
333                         break;
334                         
335                 case KEY_INDEX_PRINTER:
336                         if ( subkeys )
337                                 print_subpath_printers( p, subkeys );
338                         if ( val )
339                                 print_subpath_values_printers( p, val );
340                         break;
341         
342                 /* default case for top level key that has no handler */
343                 
344                 default:
345                         break;
346         }
347         
348         
349         
350         return result;
351
352 }
353
354 /**********************************************************************
355  Enumerate registry subkey names given a registry path.  
356  Caller is responsible for freeing memory to **subkeys
357  *********************************************************************/
358  
359 static int printing_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
360 {
361         char            *path;
362         int             num_subkeys = 0;
363         
364         DEBUG(10,("printing_subkey_info: key=>[%s]\n", key));
365         
366         path = trim_reg_path( key );
367         
368         /* check to see if we are dealing with the top level key */
369         
370         if ( path ) {
371                 num_subkeys = handle_printing_subpath( path, subkey_ctr, NULL );
372                 SAFE_FREE( path );
373                 return num_subkeys;
374         }
375         
376         /* handle top level keys here */
377                 
378         if ( strequal( KEY_PRINTING, key ) ) {
379                 regsubkey_ctr_addkey( subkey_ctr, "Environments" );
380                 regsubkey_ctr_addkey( subkey_ctr, "Forms" );
381         }
382         else if ( strequal( KEY_PRINTING_2K, key ) ) {
383                 regsubkey_ctr_addkey( subkey_ctr, "Printers" );
384         }
385
386         return num_subkeys;
387 }
388
389 #endif  /* UNUSED */
390
391 /**********************************************************************
392  move to next non-delimter character
393 *********************************************************************/
394
395 static char* remaining_path( const char *key )
396 {
397         static pstring new_path;
398         char *p;
399         
400         if ( !key || !*key )
401                 return NULL;
402
403         pstrcpy( new_path, key );
404         normalize_reg_path( new_path );
405         
406         p = strchr( new_path, '/' );
407         
408         if ( p )
409                 p++;
410         else
411                 p = new_path;
412                 
413         return p;
414 }
415
416 /***********************************************************************
417  simple function to prune a pathname down to the basename of a file 
418  **********************************************************************/
419  
420 static char* dos_basename ( char *path )
421 {
422         char *p;
423         
424         p = strrchr( path, '\\' );
425         if ( p )
426                 p++;
427         else
428                 p = path;
429                 
430         return p;
431 }
432
433 /**********************************************************************
434  *********************************************************************/
435
436 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
437 {
438         return 0;
439 }
440
441 static BOOL key_forms_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
442 {
443         return True;
444 }
445
446 static int key_forms_fetch_values( const char *key, REGVAL_CTR *values )
447 {
448         int             num_values = 0;
449         uint32          data[8];
450         int             form_index = 1;
451         int i;
452         
453         DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
454         
455         nt_forms_struct *forms_list = NULL;
456         nt_forms_struct *form = NULL;
457                 
458         if ( (num_values = get_ntforms( &forms_list )) == 0 ) 
459                 return 0;
460                 
461         DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
462                 num_values));
463
464         /* handle user defined forms */
465                                 
466         for ( i=0; i<num_values; i++ ) {
467                 form = &forms_list[i];
468                         
469                 data[0] = form->width;
470                 data[1] = form->length;
471                 data[2] = form->left;
472                 data[3] = form->top;
473                 data[4] = form->right;
474                 data[5] = form->bottom;
475                 data[6] = form_index++;
476                 data[7] = form->flag;
477                         
478                 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );       
479         }
480                 
481         SAFE_FREE( forms_list );
482         forms_list = NULL;
483                 
484         /* handle built-on forms */
485                 
486         if ( (num_values = get_builtin_ntforms( &forms_list )) == 0 ) 
487                 return 0;
488                 
489         DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
490                 num_values));
491                         
492         for ( i=0; i<num_values; i++ ) {
493                 form = &forms_list[i];
494                         
495                 data[0] = form->width;
496                 data[1] = form->length;
497                 data[2] = form->left;
498                 data[3] = form->top;
499                 data[4] = form->right;
500                 data[5] = form->bottom;
501                 data[6] = form_index++;
502                 data[7] = form->flag;
503                                         
504                 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
505         }
506                 
507         SAFE_FREE( forms_list );
508         
509         return regval_ctr_numvals( values );
510 }
511
512 static BOOL key_forms_store_values( const char *key, REGVAL_CTR *values )
513 {
514         return True;
515 }
516
517 /**********************************************************************
518  *********************************************************************/
519
520 static int key_printer_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
521 {
522         return 0;
523 }
524
525 static BOOL key_printer_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
526 {
527         return True;
528 }
529
530 static int key_printer_fetch_values( const char *key, REGVAL_CTR *values )
531 {
532         return 0;
533 }
534
535 static BOOL key_printer_store_values( const char *key, REGVAL_CTR *values )
536 {
537         return True;
538 }
539
540 /**********************************************************************
541  *********************************************************************/
542 #define ENVIRONMENT_DRIVERS     1
543 #define ENVIRONMENT_PRINTPROC   2
544
545 static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
546 {
547         const char *environments[] = {
548                 "Windows 4.0",
549                 "Windows NT x86",
550                 "Windows NT R4000",
551                 "Windows NT Alpha_AXP",
552                 "Windows NT PowerPC",
553                 "Windows IA64",
554                 "Windows x64",
555                 NULL };
556         fstring *drivers = NULL;
557         int i, env_index, num_drivers;
558         char *keystr, *base, *subkeypath;
559         pstring key2;
560         int num_subkeys = -1;
561         int env_subkey_type = 0;
562         int version;
563
564         DEBUG(10,("print_subpath_environments: key=>[%s]\n", key ? key : "NULL" ));
565         
566         /* list all possible architectures */
567         
568         if ( !key ) {
569                 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ ) 
570                         regsubkey_ctr_addkey( subkeys,  environments[num_subkeys] );
571
572                 return num_subkeys;
573         }
574         
575         /* we are dealing with a subkey of "Environments */
576         
577         pstrcpy( key2, key );
578         keystr = key2;
579         reg_split_path( keystr, &base, &subkeypath );
580         
581         /* sanity check */
582         
583         for ( env_index=0; environments[env_index]; env_index++ ) {
584                 if ( strequal( environments[env_index], base ) )
585                         break;
586         }
587         if ( !environments[env_index] )
588                 return -1;
589         
590         /* ...\Print\Environements\...\ */
591         
592         if ( !subkeypath ) {
593                 regsubkey_ctr_addkey( subkeys, "Drivers" );
594                 regsubkey_ctr_addkey( subkeys, "Print Processors" );
595                                 
596                 return 2;
597         }
598         
599         /* more of the key path to process */
600         
601         keystr = subkeypath;
602         reg_split_path( keystr, &base, &subkeypath );   
603                 
604         /* ...\Print\Environements\...\Drivers\ */
605         
606         if ( strequal(base, "Drivers") )
607                 env_subkey_type = ENVIRONMENT_DRIVERS;
608         else if ( strequal(base, "Print Processors") )
609                 env_subkey_type = ENVIRONMENT_PRINTPROC;
610         else
611                 /* invalid path */
612                 return -1;
613         
614         if ( !subkeypath ) {
615                 switch ( env_subkey_type ) {
616                 case ENVIRONMENT_DRIVERS:
617                         switch ( env_index ) {
618                                 case 0: /* Win9x */
619                                         regsubkey_ctr_addkey( subkeys, "Version-0" );
620                                         break;
621                                 default: /* Windows NT based systems */
622                                         regsubkey_ctr_addkey( subkeys, "Version-2" );
623                                         regsubkey_ctr_addkey( subkeys, "Version-3" );
624                                         break;                  
625                         }
626                 
627                         return regsubkey_ctr_numkeys( subkeys );
628                 
629                 case ENVIRONMENT_PRINTPROC:
630                         if ( env_index == 1 || env_index == 5 || env_index == 6 )
631                                 regsubkey_ctr_addkey( subkeys, "winprint" );
632                                 
633                         return regsubkey_ctr_numkeys( subkeys );
634                 }
635         }
636         
637         /* we finally get to enumerate the drivers */
638         
639         keystr = subkeypath;
640         reg_split_path( keystr, &base, &subkeypath );
641
642         /* get thr print processors key out of the way */
643         if ( env_subkey_type == ENVIRONMENT_PRINTPROC ) {
644                 if ( !strequal( base, "winprint" ) )
645                         return -1;
646                 return !subkeypath ? 0 : -1;
647         }
648         
649         /* only dealing with drivers from here on out */
650         
651         version = atoi(&base[strlen(base)-1]);
652                         
653         switch (env_index) {
654         case 0:
655                 if ( version != 0 )
656                         return -1;
657                 break;
658         default:
659                 if ( version != 2 && version != 3 )
660                         return -1;
661                 break;
662         }
663
664         
665         if ( !subkeypath ) {
666                 num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
667                 for ( i=0; i<num_drivers; i++ )
668                         regsubkey_ctr_addkey( subkeys, drivers[i] );
669                         
670                 return regsubkey_ctr_numkeys( subkeys );        
671         }       
672         
673         /* if anything else left, just say if has no subkeys */
674         
675         DEBUG(1,("print_subpath_environments: unhandled key [%s] (subkey == %s\n", 
676                 key, subkeypath ));
677         
678         return 0;
679 }
680
681 static BOOL key_driver_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
682 {
683         return True;
684 }
685
686 static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
687 {
688         char            *keystr, *base, *subkeypath;
689         pstring         key2;
690         fstring         arch_environment;
691         fstring         driver;
692         int             version;
693         NT_PRINTER_DRIVER_INFO_LEVEL    driver_ctr;
694         NT_PRINTER_DRIVER_INFO_LEVEL_3  *info3;
695         WERROR          w_result;
696         char            *buffer = NULL;
697         char            *buffer2 = NULL;
698         int             buffer_size = 0;
699         int             i, length;
700         char            *filename;
701         UNISTR2         data;
702         int             env_subkey_type = 0;
703         
704         
705         DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL"));
706         
707         if ( !key )
708                 return 0;
709                 
710         /* The only keys below KEY_PRINTING\Environments is the 
711            specific printer driver info */
712         
713         /* environment */
714         
715         pstrcpy( key2, key );
716         keystr = key2;
717         reg_split_path( keystr, &base, &subkeypath );
718         if ( !subkeypath ) 
719                 return 0;
720         fstrcpy( arch_environment, base );
721         
722         /* Driver */
723         
724         keystr = subkeypath;
725         reg_split_path( keystr, &base, &subkeypath );
726
727         if ( strequal(base, "Drivers") )
728                 env_subkey_type = ENVIRONMENT_DRIVERS;
729         else if ( strequal(base, "Print Processors") )
730                 env_subkey_type = ENVIRONMENT_PRINTPROC;
731         else
732                 /* invalid path */
733                 return -1;
734         
735         if ( !subkeypath )
736                 return 0;
737
738         /* for now bail out if we are seeing anything other than the drivers key */
739         
740         if ( env_subkey_type == ENVIRONMENT_PRINTPROC )
741                 return 0;
742                 
743         keystr = subkeypath;
744         reg_split_path( keystr, &base, &subkeypath );
745                 
746         version = atoi(&base[strlen(base)-1]);
747
748         /* printer driver name */
749         
750         keystr = subkeypath;
751         reg_split_path( keystr, &base, &subkeypath );
752         /* don't go any deeper for now */
753         if ( subkeypath )
754                 return 0;
755         fstrcpy( driver, base );
756
757         w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );
758
759         if ( !W_ERROR_IS_OK(w_result) )
760                 return -1;
761                 
762         /* build the values out of the driver information */
763         info3 = driver_ctr.info_3;
764         
765         filename = dos_basename( info3->driverpath );
766         init_unistr2( &data, filename, UNI_STR_TERMINATE);
767         regval_ctr_addvalue( values, "Driver",             REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
768         
769         filename = dos_basename( info3->configfile );
770         init_unistr2( &data, filename, UNI_STR_TERMINATE);
771         regval_ctr_addvalue( values, "Configuration File", REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
772         
773         filename = dos_basename( info3->datafile );
774         init_unistr2( &data, filename, UNI_STR_TERMINATE);
775         regval_ctr_addvalue( values, "Data File",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
776         
777         filename = dos_basename( info3->helpfile );
778         init_unistr2( &data, filename, UNI_STR_TERMINATE);
779         regval_ctr_addvalue( values, "Help File",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
780         
781         init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE);
782         regval_ctr_addvalue( values, "Data Type",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
783         
784         regval_ctr_addvalue( values, "Version",            REG_DWORD,    (char*)&info3->cversion, sizeof(info3->cversion) );
785         
786         if ( info3->dependentfiles ) {
787                 /* place the list of dependent files in a single 
788                    character buffer, separating each file name by
789                    a NULL */
790                    
791                 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) {
792                         /* strip the path to only the file's base name */
793                 
794                         filename = dos_basename( info3->dependentfiles[i] );
795                         
796                         length = strlen(filename);
797                 
798                         buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
799                         if ( !buffer2 )
800                                 break;
801                         buffer = buffer2;
802                         
803                         init_unistr2( &data, filename, UNI_STR_TERMINATE);
804                         memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
805                 
806                         buffer_size += (length + 1)*sizeof(uint16);
807                 }
808                 
809                 /* terminated by double NULL.  Add the final one here */
810                 
811                 buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
812                 if ( !buffer2 ) {
813                         SAFE_FREE( buffer );
814                         buffer_size = 0;
815                 } else {
816                         buffer = buffer2;
817                         buffer[buffer_size++] = '\0';
818                         buffer[buffer_size++] = '\0';
819                 }
820         }
821         
822         regval_ctr_addvalue( values, "Dependent Files",    REG_MULTI_SZ, buffer, buffer_size );
823         
824         free_a_printer_driver( driver_ctr, 3 );
825         
826         SAFE_FREE( buffer );
827                 
828         DEBUG(8,("print_subpath_values_environments: Exit\n"));
829         
830         return regval_ctr_numvals( values );
831 }
832
833 static BOOL key_driver_store_values( const char *key, REGVAL_CTR *values )
834 {
835         return True;
836 }
837
838 /**********************************************************************
839  Deal with the 'Print' key the same whether it came from SYSTEM
840  or SOFTWARE
841  *********************************************************************/
842
843 static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
844 {       
845         int key_len = strlen(key);
846         
847         /* no keys below 'Print' handled here */
848         
849         if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
850                 return -1;
851
852         regsubkey_ctr_addkey( subkeys, "Environments" );
853         regsubkey_ctr_addkey( subkeys, "Monitors" );
854         regsubkey_ctr_addkey( subkeys, "Forms" );
855         regsubkey_ctr_addkey( subkeys, "Printers" );
856         
857         return regsubkey_ctr_numkeys( subkeys );
858 }
859
860 /**********************************************************************
861  *********************************************************************/
862
863 static int key_ports_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
864 {
865         char *p = remaining_path( key + strlen(KEY_PORTS) );
866         
867         /* no keys below ports */
868         if ( p )
869                 return -1;
870                 
871         return 0;
872 }
873
874 static BOOL key_ports_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
875 {
876         return True;
877 }
878
879 static int key_ports_fetch_values( const char *key, REGVAL_CTR *values )
880 {
881         int numlines, i;
882         char **lines;
883         UNISTR2 data;
884         WERROR result;
885         char *p = remaining_path( key + strlen(KEY_PORTS) );
886         
887         /* no keys below ports */
888         if ( p )
889                 return -1;
890
891         if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &lines )) )
892                 return -1;
893
894         init_unistr2( &data, "", UNI_STR_TERMINATE);
895         for ( i=0; i<numlines; i++ )
896                 regval_ctr_addvalue( values, lines[i], REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
897         
898         return regval_ctr_numvals( values );
899 }
900
901 static BOOL key_ports_store_values( const char *key, REGVAL_CTR *values )
902 {
903         return True;
904 }
905
906 /**********************************************************************
907  Structure to hold dispatch table of ops for various printer keys.
908  Make sure to always store deeper keys along the same path first so 
909  we ge a more specific match.
910  *********************************************************************/
911
912 static struct reg_dyn_tree print_registry[] = {
913 /* just pass the monitor onto the regostry tdb */
914 { KEY_MONITORS,
915         &regdb_fetch_keys, 
916         &regdb_store_keys,
917         &regdb_fetch_values,
918         &regdb_store_values },
919 { KEY_FORMS, 
920         &key_forms_fetch_keys, 
921         &key_forms_store_keys, 
922         &key_forms_fetch_values,
923         &key_forms_store_values },
924 { KEY_CONTROL_PRINTERS, 
925         &key_printer_fetch_keys,
926         &key_printer_store_keys,
927         &key_printer_fetch_values,
928         &key_printer_store_values },
929 { KEY_ENVIRONMENTS,
930         &key_driver_fetch_keys,
931         &key_driver_store_keys,
932         &key_driver_fetch_values,
933         &key_driver_store_values },
934 { KEY_CONTROL_PRINT,
935         &key_print_fetch_keys,
936         NULL,
937         NULL,
938         NULL },
939 { KEY_WINNT_PRINTERS,
940         &key_printer_fetch_keys,
941         &key_printer_store_keys,
942         &key_printer_fetch_values,
943         &key_printer_store_values },
944 { KEY_WINNT_PRINT,
945         &key_print_fetch_keys,
946         NULL,
947         NULL,
948         NULL },
949 { KEY_PORTS,
950         &key_ports_fetch_keys,
951         &key_ports_store_keys,
952         &key_ports_fetch_values,
953         &key_ports_store_values },
954         
955 { NULL, NULL, NULL, NULL, NULL }
956 };
957
958
959 /**********************************************************************
960  *********************************************************************/
961  
962 static int match_registry_path( const char *key )
963 {
964         int i;
965         pstring path;
966         
967         if ( !key )
968                 return -1;
969
970         pstrcpy( path, key );
971         normalize_reg_path( path );
972         
973         for ( i=0; print_registry[i].path; i++ ) {
974                 if ( strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
975                         return i;
976         }
977         
978         return -1;
979 }
980
981 /**********************************************************************
982  *********************************************************************/
983  
984 static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
985 {
986         int i = match_registry_path( key );
987         
988         if ( i == -1 )
989                 return -1;
990                 
991         if ( !print_registry[i].fetch_subkeys )
992                 return -1;
993                 
994         return print_registry[i].fetch_subkeys( key, subkeys );
995 }
996
997 /**********************************************************************
998  *********************************************************************/
999
1000 static BOOL regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
1001 {
1002         int i = match_registry_path( key );
1003         
1004         if ( i == -1 )
1005                 return False;
1006         
1007         if ( !print_registry[i].store_subkeys )
1008                 return False;
1009                 
1010         return print_registry[i].store_subkeys( key, subkeys );
1011 }
1012
1013 /**********************************************************************
1014  *********************************************************************/
1015
1016 static int regprint_fetch_reg_values( const char *key, REGVAL_CTR *values )
1017 {
1018         int i = match_registry_path( key );
1019         
1020         if ( i == -1 )
1021                 return -1;
1022         
1023         /* return 0 values by default since we know the key had 
1024            to exist because the client opened a handle */
1025            
1026         if ( !print_registry[i].fetch_values )
1027                 return 0;
1028                 
1029         return print_registry[i].fetch_values( key, values );
1030 }
1031
1032 /**********************************************************************
1033  *********************************************************************/
1034
1035 static BOOL regprint_store_reg_values( const char *key, REGVAL_CTR *values )
1036 {
1037         int i = match_registry_path( key );
1038         
1039         if ( i == -1 )
1040                 return False;
1041         
1042         if ( !print_registry[i].store_values )
1043                 return False;
1044                 
1045         return print_registry[i].store_values( key, values );
1046 }
1047
1048 /* 
1049  * Table of function pointers for accessing printing data
1050  */
1051  
1052 REGISTRY_OPS printing_ops = {
1053         regprint_fetch_reg_keys,
1054         regprint_fetch_reg_values,
1055         regprint_store_reg_keys,
1056         regprint_store_reg_values,
1057         NULL
1058 };
1059
1060