several changes in this checkin
[tprouty/samba.git] / source / registry / reg_frontend.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Gerald Carter                     2002.
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 frontend view functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 extern REGISTRY_OPS printing_ops;
29 extern REGISTRY_OPS regdb_ops;          /* these are the default */
30
31 /* array of REGISTRY_HOOK's which are read into a tree for easy access */
32
33
34 REGISTRY_HOOK reg_hooks[] = {
35   { KEY_PRINTING,   &printing_ops },
36   { NULL, NULL }
37 };
38
39
40 /*
41  * Utility functions for REGSUBKEY_CTR
42  */
43
44 /***********************************************************************
45  Init the talloc context held by a REGSUBKEY_CTR structure
46  **********************************************************************/
47
48 void regsubkey_ctr_init( REGSUBKEY_CTR *ctr )
49 {
50         if ( !ctr->ctx )
51                 ctr->ctx = talloc_init();
52 }
53
54 /***********************************************************************
55  Add a new key to the array
56  **********************************************************************/
57
58 int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, char *keyname )
59 {
60         uint32 len;
61         char **pp;
62         
63         if ( keyname )
64         {
65                 len = strlen( keyname );
66
67                 /* allocate a space for the char* in the array */
68                 
69                 if (  ctr->subkeys == 0 )
70                         ctr->subkeys = talloc( ctr->ctx, sizeof(char*) );
71                 else {
72                         pp = talloc_realloc( ctr->ctx, ctr->subkeys, sizeof(char*)*(ctr->num_subkeys+1) );
73                         if ( pp )
74                                 ctr->subkeys = pp;
75                 }
76
77                 /* allocate the string and save it in the array */
78                 
79                 ctr->subkeys[ctr->num_subkeys] = talloc( ctr->ctx, len+1 );
80                 strncpy( ctr->subkeys[ctr->num_subkeys], keyname, len+1 );
81                 ctr->num_subkeys++;
82         }
83         
84         return ctr->num_subkeys;
85 }
86  
87 /***********************************************************************
88  How many keys does the container hold ?
89  **********************************************************************/
90
91 int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
92 {
93         return ctr->num_subkeys;
94 }
95
96 /***********************************************************************
97  Retreive a specific key string
98  **********************************************************************/
99
100 char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index )
101 {
102         if ( ! (key_index < ctr->num_subkeys) )
103                 return NULL;
104                 
105         return ctr->subkeys[key_index];
106 }
107
108 /***********************************************************************
109  free memory held by a REGSUBKEY_CTR structure
110  **********************************************************************/
111
112 void regsubkey_ctr_destroy( REGSUBKEY_CTR *ctr )
113 {
114         if ( ctr ) {
115                 talloc_destroy( ctr->ctx );     
116                 ZERO_STRUCTP( ctr );
117         }
118 }
119
120
121 /*
122  * Utility functions for REGVAL_CTR
123  */
124
125 /***********************************************************************
126  Init the talloc context held by a REGSUBKEY_CTR structure
127  **********************************************************************/
128
129 void regval_ctr_init( REGVAL_CTR *ctr )
130 {
131         if ( !ctr->ctx )
132                 ctr->ctx = talloc_init();
133 }
134
135 /***********************************************************************
136  How many keys does the container hold ?
137  **********************************************************************/
138
139 int regval_ctr_numvals( REGVAL_CTR *ctr )
140 {
141         return ctr->num_values;
142 }
143
144 /***********************************************************************
145  allocate memory for and duplicate a REGISTRY_VALUE.
146  This is malloc'd memory so the caller should free it when done
147  **********************************************************************/
148
149 REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
150 {
151         REGISTRY_VALUE  *copy = NULL;
152         
153         if ( !val )
154                 return NULL;
155         
156         if ( !(copy = malloc( sizeof(REGISTRY_VALUE) )) ) {
157                 DEBUG(0,("dup_registry_value: malloc() failed!\n"));
158                 return NULL;
159         }
160         
161         /* copy all the non-pointer initial data */
162         
163         memcpy( copy, val, sizeof(REGISTRY_VALUE) );
164         if ( val->data_p ) 
165         {
166                 if ( !(copy->data_p = memdup( val->data_p, val->size )) ) {
167                         DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
168                                 val->size));
169                         SAFE_FREE( copy );
170                 }
171         }
172         
173         return copy;    
174 }
175
176 /**********************************************************************
177  free the memory allocated to a REGISTRY_VALUE 
178  *********************************************************************/
179  
180 void free_registry_value( REGISTRY_VALUE *val )
181 {
182         if ( !val )
183                 return;
184                 
185         SAFE_FREE( val->data_p );
186         SAFE_FREE( val );
187         
188         return;
189 }
190
191 /***********************************************************************
192  Retreive a pointer to a specific value.  Caller shoud dup the structure
193  since this memory may go away with a regval_ctr_destroy()
194  **********************************************************************/
195
196 REGISTRY_VALUE* regval_ctr_specific_value( REGVAL_CTR *ctr, uint32 idx )
197 {
198         if ( !(idx < ctr->num_values) )
199                 return NULL;
200                 
201         return ctr->values[idx];
202 }
203
204 /***********************************************************************
205  Ad a new regostry value to the array
206  **********************************************************************/
207
208 int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type, 
209                          char *data_p, size_t size )
210 {
211         REGISTRY_VALUE **ppreg;
212         uint16 len;
213         
214         if ( name )
215         {
216                 len = strlen( name );
217
218                 /* allocate a slot in the array of pointers */
219                 
220                 if (  ctr->num_values == 0 )
221                         ctr->values = talloc( ctr->ctx, sizeof(REGISTRY_VALUE*) );
222                 else {
223                         ppreg = talloc_realloc( ctr->ctx, ctr->values, sizeof(REGISTRY_VALUE*)*(ctr->num_values+1) );
224                         if ( ppreg )
225                                 ctr->values = ppreg;
226                 }
227
228                 /* allocate a new valuie and store the pointer in the arrya */
229                 
230                 ctr->values[ctr->num_values] = talloc( ctr->ctx, sizeof(REGISTRY_VALUE) );
231
232                 /* init the value */
233         
234                 fstrcpy( ctr->values[ctr->num_values]->valuename, name );
235                 ctr->values[ctr->num_values]->type = type;
236                 ctr->values[ctr->num_values]->data_p = talloc_memdup( ctr->ctx, data_p, size );
237                 ctr->values[ctr->num_values]->size = size;
238 #if 0
239                 switch ( type )
240                 {
241                         case REG_SZ:
242                                 ctr->values[ctr->num_values]->data.string = talloc_strdup( ctr->ctx, data_p );
243                                 break;
244                         case REG_MULTI_SZ:
245                                 ctr->values[ctr->num_values]->data.string = talloc_memdup( ctr->ctx, data_p, size );
246                                 break;
247                         case REG_DWORD:
248                                 ctr->values[ctr->num_values]->data.dword = *(uint32*)data_p;
249                                 break;
250                         case REG_BINARY:
251                                 ctr->values[ctr->num_values]->data.binary = talloc_memdup( ctr->ctx, data_p, size );
252                                 break;
253                                 
254                 }
255 #endif
256                 
257                 ctr->num_values++;
258         }
259
260         return ctr->num_values;
261 }
262
263 /***********************************************************************
264  free memory held by a REGVAL_CTR structure
265  **********************************************************************/
266
267 void regval_ctr_destroy( REGVAL_CTR *ctr )
268 {
269         if ( ctr ) {
270                 talloc_destroy( ctr->ctx );
271                 ZERO_STRUCTP( ctr );
272         }
273 }
274
275 /***********************************************************************
276  Open the registry database and initialize the REGISTRY_HOOK cache
277  ***********************************************************************/
278  
279 BOOL init_registry( void )
280 {
281         int i;
282         
283         if ( !init_registry_db() ) {
284                 DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
285                 return False;
286         }
287                 
288         /* build the cache tree of registry hooks */
289         
290         reghook_cache_init();
291         
292         for ( i=0; reg_hooks[i].keyname; i++ ) {
293                 if ( !reghook_cache_add(&reg_hooks[i]) )
294                         return False;
295         }
296
297         if ( DEBUGLEVEL >= 20 )
298                 reghook_dump_cache(20);
299
300         return True;
301 }
302
303
304
305
306 /***********************************************************************
307  High level wrapper function for storing registry subkeys
308  ***********************************************************************/
309  
310 BOOL store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
311 {
312         if ( key->hook && key->hook->ops && key->hook->ops->store_subkeys_fn )
313                 return key->hook->ops->store_subkeys_fn( key->name, subkeys );
314         else
315                 return False;
316
317 }
318
319 /***********************************************************************
320  High level wrapper function for storing registry values
321  ***********************************************************************/
322  
323 BOOL store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
324 {
325         if ( key->hook && key->hook->ops && key->hook->ops->store_values_fn )
326                 return key->hook->ops->store_values_fn( key->name, val );
327         else
328                 return False;
329 }
330
331
332 /***********************************************************************
333  High level wrapper function for enumerating registry subkeys
334  Initialize the TALLOC_CTX if necessary
335  ***********************************************************************/
336
337 int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
338 {
339         int result = -1;
340         
341         if ( key->hook && key->hook->ops && key->hook->ops->subkey_fn )
342                 result = key->hook->ops->subkey_fn( key->name, subkey_ctr );
343
344         return result;
345 }
346
347 /***********************************************************************
348  retreive a specific subkey specified by index.  Caller is 
349  responsible for freeing memory
350  ***********************************************************************/
351
352 BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index )
353 {
354         static REGSUBKEY_CTR ctr;
355         static pstring save_path;
356         static BOOL ctr_init = False;
357         char *s;
358         
359         *subkey = NULL;
360         
361         /* simple caching for performance; very basic heuristic */
362         
363         if ( !ctr_init ) {
364                 DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name));
365                 ZERO_STRUCTP( &ctr );   
366                 regsubkey_ctr_init( &ctr );
367                 
368                 pstrcpy( save_path, key->name );
369                 
370                 if ( fetch_reg_keys( key, &ctr) == -1 )
371                         return False;
372                         
373                 ctr_init = True;
374         }
375         /* clear the cache when key_index == 0 or the path has changed */
376         else if ( !key_index || StrCaseCmp( save_path, key->name) ) {
377
378                 DEBUG(8,("fetch_reg_keys_specific: Updating cache of subkeys for [%s]\n", key->name));
379                 
380                 regsubkey_ctr_destroy( &ctr );  
381                 regsubkey_ctr_init( &ctr );
382                 
383                 pstrcpy( save_path, key->name );
384                 
385                 if ( fetch_reg_keys( key, &ctr) == -1 )
386                         return False;
387         }
388         
389         if ( !(s = regsubkey_ctr_specific_key( &ctr, key_index )) )
390                 return False;
391
392         *subkey = strdup( s );
393
394         return True;
395 }
396
397
398 /***********************************************************************
399  High level wrapper function for enumerating registry values
400  Initialize the TALLOC_CTX if necessary
401  ***********************************************************************/
402
403 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
404 {
405         int result = -1;
406         
407         if ( key->hook && key->hook->ops && key->hook->ops->value_fn )
408                 result = key->hook->ops->value_fn( key->name, val );
409
410         return result;
411 }
412
413
414 /***********************************************************************
415  retreive a specific subkey specified by index.  Caller is 
416  responsible for freeing memory
417  ***********************************************************************/
418
419 BOOL fetch_reg_values_specific( REGISTRY_KEY *key, REGISTRY_VALUE **val, uint32 val_index )
420 {
421         static REGVAL_CTR       ctr;
422         static pstring          save_path;
423         static BOOL             ctr_init = False;
424         REGISTRY_VALUE          *v;
425         
426         *val = NULL;
427         
428         /* simple caching for performance; very basic heuristic */
429         
430         if ( !ctr_init ) {
431                 DEBUG(8,("fetch_reg_values_specific: Initializing cache of values for [%s]\n", key->name));
432
433                 ZERO_STRUCTP( &ctr );   
434                 regval_ctr_init( &ctr );
435                 
436                 pstrcpy( save_path, key->name );
437                 
438                 if ( fetch_reg_values( key, &ctr) == -1 )
439                         return False;
440                         
441                 ctr_init = True;
442         }
443         /* clear the cache when val_index == 0 or the path has changed */
444         else if ( !val_index || StrCaseCmp(save_path, key->name) ) {
445
446                 DEBUG(8,("fetch_reg_values_specific: Updating cache of values for [%s]\n", key->name));         
447                 
448                 regval_ctr_destroy( &ctr );     
449                 regval_ctr_init( &ctr );
450                 
451                 pstrcpy( save_path, key->name );
452                 
453                 if ( fetch_reg_values( key, &ctr) == -1 )
454                         return False;
455         }
456         
457         if ( !(v = regval_ctr_specific_value( &ctr, val_index )) )
458                 return False;
459
460         *val = dup_registry_value( v );
461
462         return True;
463 }
464
465 /***********************************************************************
466  Utility function for splitting the base path of a registry path off
467  by setting base and new_path to the apprapriate offsets withing the
468  path.
469  
470  WARNING!!  Does modify the original string!
471  ***********************************************************************/
472
473 BOOL reg_split_path( char *path, char **base, char **new_path )
474 {
475         char *p;
476         
477         *new_path = *base = NULL;
478         
479         if ( !path)
480                 return False;
481         
482         *base = path;
483         
484         p = strchr( path, '\\' );
485         
486         if ( p ) {
487                 *p = '\0';
488                 *new_path = p+1;
489         }
490         
491         return True;
492 }
493
494
495