r7938: * move the hardcoded registry value names from _reg_query_value()
[sfrench/samba-autobuild/.git] / source / registry / reg_db.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 internal registry database functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 static TDB_CONTEXT *tdb_reg;
29
30 #define VALUE_PREFIX    "SAMBA_REGVAL"
31
32 static BOOL regdb_store_reg_keys( const char *keyname, REGSUBKEY_CTR *subkeys );
33 static BOOL regdb_store_reg_values( const char *keyname, REGVAL_CTR *values);
34 static int regdb_fetch_reg_keys( const char* key, REGSUBKEY_CTR *subkeys );
35 static int regdb_fetch_reg_values( const char* key, REGVAL_CTR *values );
36
37
38
39
40 /* List the deepest path into the registry.  All part components will be created.*/
41
42 /* If you want to have a part of the path controlled by the tdb abd part by
43    a virtual registry db (e.g. printing), then you have to list the deepest path.
44    For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" 
45    allows the reg_db backend to handle everything up to 
46    "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook 
47    the reg_printing backend onto the last component of the path (see 
48    KEY_PRINTING_2K in include/rpc_reg.h)   --jerry */
49
50 static const char *builtin_registry_paths[] = {
51         "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print",
52         "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports",
53         "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print",
54         "HKLM\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
55         "HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares",
56         "HKLM\\SYSTEM\\CurrentControlSet\\Services\\EventLog",
57         "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters",
58         "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters",
59         "HKU",
60         "HKCR",
61          NULL };
62
63 struct builtin_regkey_value {
64         const char *path;
65         const char *valuename;
66         uint32 type;
67         union {
68                 const char *string;
69                 uint32 dw_value;
70         } data;
71 };
72
73 static struct builtin_regkey_value builtin_registry_values[] = {
74         { "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",      "SystemRoot",   REG_SZ,         { "c:\\Windows" } },
75         { NULL, NULL, 0, { NULL } }
76 };
77
78 #define REGVER_V1       1       /* first db version with write support */
79         
80 /***********************************************************************
81  Open the registry data in the tdb
82  ***********************************************************************/
83  
84 static BOOL init_registry_data( void )
85 {
86         pstring path, base, remaining;
87         fstring keyname, subkeyname;
88         REGSUBKEY_CTR   subkeys;
89         REGVAL_CTR values;
90         int i;
91         const char *p, *p2;
92         UNISTR2 data;
93         
94         /* loop over all of the predefined paths and add each component */
95         
96         for ( i=0; builtin_registry_paths[i] != NULL; i++ ) {
97
98                 DEBUG(6,("init_registry_data: Adding [%s]\n", builtin_registry_paths[i]));
99
100                 pstrcpy( path, builtin_registry_paths[i] );
101                 pstrcpy( base, "" );
102                 p = path;
103                 
104                 while ( next_token(&p, keyname, "\\", sizeof(keyname)) ) {
105                 
106                         /* build up the registry path from the components */
107                         
108                         if ( *base )
109                                 pstrcat( base, "\\" );
110                         pstrcat( base, keyname );
111                         
112                         /* get the immediate subkeyname (if we have one ) */
113                         
114                         *subkeyname = '\0';
115                         if ( *p ) {
116                                 pstrcpy( remaining, p );
117                                 p2 = remaining;
118                                 
119                                 if ( !next_token(&p2, subkeyname, "\\", sizeof(subkeyname)) )
120                                         fstrcpy( subkeyname, p2 );
121                         }
122
123                         DEBUG(10,("init_registry_data: Storing key [%s] with subkey [%s]\n",
124                                 base, *subkeyname ? subkeyname : "NULL"));
125                         
126                         /* we don't really care if the lookup succeeds or not since
127                            we are about to update the record.  We just want any 
128                            subkeys already present */
129                         
130                         regsubkey_ctr_init( &subkeys );
131                                                    
132                         regdb_fetch_reg_keys( base, &subkeys );
133                         if ( *subkeyname ) 
134                                 regsubkey_ctr_addkey( &subkeys, subkeyname );
135                         if ( !regdb_store_reg_keys( base, &subkeys ))
136                                 return False;
137                         
138                         regsubkey_ctr_destroy( &subkeys );
139                 }
140         }
141
142         /* loop over all of the predefined values and add each component */
143         
144         for ( i=0; builtin_registry_values[i].path != NULL; i++ ) {
145                 regval_ctr_init( &values );
146                 
147                 regdb_fetch_reg_values( builtin_registry_values[i].path, &values );
148                 switch( builtin_registry_values[i].type ) {
149                         case REG_DWORD:
150                                 regval_ctr_addvalue( &values, 
151                                                      builtin_registry_values[i].valuename,
152                                                      REG_DWORD,
153                                                      (char*)&builtin_registry_values[i].data.dw_value,
154                                                      sizeof(uint32) );
155                                 break;
156                                 
157                         case REG_SZ:
158                                 init_unistr2( &data, builtin_registry_values[i].data.string, UNI_STR_TERMINATE);
159                                 regval_ctr_addvalue( &values, 
160                                                      builtin_registry_values[i].valuename,
161                                                      REG_SZ,
162                                                      (char*)data.buffer,
163                                                      data.uni_str_len*sizeof(uint16) );
164                                 break;
165                         
166                         default:
167                                 DEBUG(0,("init_registry_data: invalid value type in builtin_registry_values [%d]\n",
168                                         builtin_registry_values[i].type));
169                 }
170                 regdb_store_reg_values( builtin_registry_values[i].path, &values );
171                 
172                 regval_ctr_destroy( &values );
173         }
174         
175         return True;
176 }
177
178 /***********************************************************************
179  Open the registry database
180  ***********************************************************************/
181  
182 BOOL init_registry_db( void )
183 {
184         const char *vstring = "INFO/version";
185         uint32 vers_id;
186
187         if ( tdb_reg )
188                 return True;
189
190         /* placeholder tdb; reinit upon startup */
191         
192         if ( !(tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600)) )
193         {
194                 tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
195                 if ( !tdb_reg ) {
196                         DEBUG(0,("init_registry: Failed to open registry %s (%s)\n",
197                                 lock_path("registry.tdb"), strerror(errno) ));
198                         return False;
199                 }
200                 
201                 DEBUG(10,("init_registry: Successfully created registry tdb\n"));
202         }
203                 
204
205         vers_id = tdb_fetch_int32(tdb_reg, vstring);
206
207         if ( vers_id != REGVER_V1 ) {
208
209                 /* create the registry here */
210
211                 if ( !init_registry_data() ) {
212                         DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
213                         return False;
214                 }
215         }
216
217         return True;
218 }
219
220 /***********************************************************************
221  Add subkey strings to the registry tdb under a defined key
222  fmt is the same format as tdb_pack except this function only supports
223  fstrings
224  ***********************************************************************/
225  
226 static BOOL regdb_store_reg_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
227 {
228         TDB_DATA kbuf, dbuf;
229         char *buffer, *tmpbuf;
230         int i = 0;
231         uint32 len, buflen;
232         BOOL ret = True;
233         uint32 num_subkeys = regsubkey_ctr_numkeys( ctr );
234         pstring keyname;
235         
236         if ( !key )
237                 return False;
238
239         pstrcpy( keyname, key );
240         normalize_reg_path( keyname );
241
242         /* allocate some initial memory */
243                 
244         buffer = SMB_MALLOC(sizeof(pstring));
245         buflen = sizeof(pstring);
246         len = 0;
247         
248         /* store the number of subkeys */
249         
250         len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys );
251         
252         /* pack all the strings */
253         
254         for (i=0; i<num_subkeys; i++) {
255                 len += tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
256                 if ( len > buflen ) {
257                         /* allocate some extra space */
258                         if ((tmpbuf = SMB_REALLOC( buffer, len*2 )) == NULL) {
259                                 DEBUG(0,("regdb_store_reg_keys: Failed to realloc memory of size [%d]\n", len*2));
260                                 ret = False;
261                                 goto done;
262                         }
263                         buffer = tmpbuf;
264                         buflen = len*2;
265                                         
266                         len = tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
267                 }               
268         }
269         
270         /* finally write out the data */
271         
272         kbuf.dptr = keyname;
273         kbuf.dsize = strlen(keyname)+1;
274         dbuf.dptr = buffer;
275         dbuf.dsize = len;
276         if ( tdb_store( tdb_reg, kbuf, dbuf, TDB_REPLACE ) == -1) {
277                 ret = False;
278                 goto done;
279         }
280
281 done:           
282         SAFE_FREE( buffer );
283         
284         return ret;
285 }
286
287 /***********************************************************************
288  Store the new subkey record and create any child key records that 
289  do not currently exist
290  ***********************************************************************/
291
292 static BOOL regdb_store_reg_keys( const char *key, REGSUBKEY_CTR *ctr )
293 {
294         int num_subkeys, i;
295         pstring path;
296         REGSUBKEY_CTR subkeys, old_subkeys;
297         char *oldkeyname;
298         
299         /* fetch a list of the old subkeys so we can determine if any were deleted */
300         
301         regsubkey_ctr_init( &old_subkeys );
302         regdb_fetch_reg_keys( key, &old_subkeys );
303         
304         /* store the subkey list for the parent */
305         
306         if ( !regdb_store_reg_keys_internal( key, ctr ) ) {
307                 DEBUG(0,("regdb_store_reg_keys: Failed to store new subkey list for parent [%s}\n", key ));
308                 return False;
309         }
310         
311         /* now delete removed keys */
312         
313         num_subkeys = regsubkey_ctr_numkeys( &old_subkeys );
314         for ( i=0; i<num_subkeys; i++ ) {
315                 oldkeyname = regsubkey_ctr_specific_key( &old_subkeys, i );
316                 if ( !regsubkey_ctr_key_exists( ctr, oldkeyname ) ) {
317                         pstr_sprintf( path, "%s%c%s", key, '/', oldkeyname );
318                         normalize_reg_path( path );
319                         tdb_delete_bystring( tdb_reg, path );
320                 }
321         }
322
323         regsubkey_ctr_destroy( &old_subkeys );
324         
325         /* now create records for any subkeys that don't already exist */
326         
327         num_subkeys = regsubkey_ctr_numkeys( ctr );
328         for ( i=0; i<num_subkeys; i++ ) {
329                 pstr_sprintf( path, "%s%c%s", key, '/', regsubkey_ctr_specific_key( ctr, i ) );
330                 regsubkey_ctr_init( &subkeys );
331                 if ( regdb_fetch_reg_keys( path, &subkeys ) == -1 ) {
332                         /* create a record with 0 subkeys */
333                         if ( !regdb_store_reg_keys_internal( path, &subkeys ) ) {
334                                 DEBUG(0,("regdb_store_reg_keys: Failed to store new record for key [%s}\n", path ));
335                                 regsubkey_ctr_destroy( &subkeys );
336                                 return False;
337                         }
338                 }
339                 regsubkey_ctr_destroy( &subkeys );
340         }
341         
342         return True;
343 }
344
345
346 /***********************************************************************
347  Retrieve an array of strings containing subkeys.  Memory should be 
348  released by the caller.  
349  ***********************************************************************/
350
351 static int regdb_fetch_reg_keys( const char* key, REGSUBKEY_CTR *ctr )
352 {
353         pstring path;
354         uint32 num_items;
355         TDB_DATA dbuf;
356         char *buf;
357         uint32 buflen, len;
358         int i;
359         fstring subkeyname;
360
361         DEBUG(10,("regdb_fetch_reg_keys: Enter key => [%s]\n", key ? key : "NULL"));
362         
363         pstrcpy( path, key );
364         
365         /* convert to key format */
366         pstring_sub( path, "\\", "/" ); 
367         strupper_m( path );
368         
369         dbuf = tdb_fetch_bystring( tdb_reg, path );
370         
371         buf = dbuf.dptr;
372         buflen = dbuf.dsize;
373         
374         if ( !buf ) {
375                 DEBUG(5,("regdb_fetch_reg_keys: tdb lookup failed to locate key [%s]\n", key));
376                 return -1;
377         }
378         
379         len = tdb_unpack( buf, buflen, "d", &num_items);
380         
381         for (i=0; i<num_items; i++) {
382                 len += tdb_unpack( buf+len, buflen-len, "f", subkeyname );
383                 regsubkey_ctr_addkey( ctr, subkeyname );
384         }
385
386         SAFE_FREE( dbuf.dptr );
387         
388         DEBUG(10,("regdb_fetch_reg_keys: Exit [%d] items\n", num_items));
389         
390         return num_items;
391 }
392
393 /****************************************************************************
394  Unpack a list of registry values frem the TDB
395  ***************************************************************************/
396  
397 static int regdb_unpack_values(REGVAL_CTR *values, char *buf, int buflen)
398 {
399         int             len = 0;
400         uint32          type;
401         pstring         valuename;
402         int             size;
403         uint8           *data_p;
404         uint32          num_values = 0;
405         int             i;
406         
407         
408         
409         /* loop and unpack the rest of the registry values */
410         
411         len += tdb_unpack(buf+len, buflen-len, "d", &num_values);
412         
413         for ( i=0; i<num_values; i++ ) {
414                 /* unpack the next regval */
415                 
416                 len += tdb_unpack(buf+len, buflen-len, "fdB",
417                                   valuename,
418                                   &type,
419                                   &size,
420                                   &data_p);
421                                 
422                 /* add the new value */
423                 
424                 regval_ctr_addvalue( values, valuename, type, (const char *)data_p, size );
425
426                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
427
428                 DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
429         }
430
431         return len;
432 }
433
434 /****************************************************************************
435  Pack all values in all printer keys
436  ***************************************************************************/
437  
438 static int regdb_pack_values(REGVAL_CTR *values, char *buf, int buflen)
439 {
440         int             len = 0;
441         int             i;
442         REGISTRY_VALUE  *val;
443         int             num_values = regval_ctr_numvals( values );
444
445         if ( !values )
446                 return 0;
447
448         /* pack the number of values first */
449         
450         len += tdb_pack( buf+len, buflen-len, "d", num_values );
451         
452         /* loop over all values */
453                 
454         for ( i=0; i<num_values; i++ ) {                        
455                 val = regval_ctr_specific_value( values, i );
456                 len += tdb_pack(buf+len, buflen-len, "fdB",
457                                 regval_name(val),
458                                 regval_type(val),
459                                 regval_size(val),
460                                 regval_data_p(val) );
461         }
462
463         return len;
464 }
465
466 /***********************************************************************
467  Retrieve an array of strings containing subkeys.  Memory should be 
468  released by the caller.
469  ***********************************************************************/
470
471 static int regdb_fetch_reg_values( const char* key, REGVAL_CTR *values )
472 {
473         TDB_DATA data;
474         pstring keystr;
475         int len;
476
477         DEBUG(10,("regdb_fetch_reg_values: Looking for value of key [%s] \n", key));
478         
479         pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key );
480         normalize_reg_path( keystr );
481         
482         data = tdb_fetch_bystring( tdb_reg, keystr );
483         
484         if ( !data.dptr ) {
485                 /* all keys have zero values by default */
486                 return 0;
487         }
488         
489         len = regdb_unpack_values( values, data.dptr, data.dsize );
490         
491         SAFE_FREE( data.dptr );
492         
493         return regval_ctr_numvals(values);
494 }
495
496 /***********************************************************************
497  Stub function since we do not currently support storing registry 
498  values in the registry.tdb
499  ***********************************************************************/
500
501 static BOOL regdb_store_reg_values( const char *key, REGVAL_CTR *values )
502 {
503         TDB_DATA data;
504         pstring keystr;
505         int len, ret;
506         
507         DEBUG(10,("regdb_store_reg_values: Looking for value of key [%s] \n", key));
508         
509         ZERO_STRUCT( data );
510         
511         len = regdb_pack_values( values, data.dptr, data.dsize );
512         if ( len <= 0 ) {
513                 DEBUG(0,("regdb_store_reg_values: unable to pack values. len <= 0\n"));
514                 return False;
515         }
516         
517         data.dptr = SMB_MALLOC_ARRAY( char, len );
518         data.dsize = len;
519         
520         len = regdb_pack_values( values, data.dptr, data.dsize );
521         
522         SMB_ASSERT( len == data.dsize );
523         
524         pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key );
525         normalize_reg_path( keystr );
526         
527         ret = tdb_store_bystring(tdb_reg, keystr, data, TDB_REPLACE);
528         
529         SAFE_FREE( data.dptr );
530         
531         return ret != -1 ;
532 }
533
534
535 /* 
536  * Table of function pointers for default access
537  */
538  
539 REGISTRY_OPS regdb_ops = {
540         regdb_fetch_reg_keys,
541         regdb_fetch_reg_values,
542         regdb_store_reg_keys,
543         regdb_store_reg_values,
544         NULL
545 };
546
547