2 * Unix SMB/CIFS implementation.
3 * Virtual Windows Registry Layer
4 * Copyright (C) Gerald Carter 2002-2005
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.
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.
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.
21 /* Implementation of internal registry database functions. */
26 #define DBGC_CLASS DBGC_RPC_SRV
28 static TDB_CONTEXT
*tdb_reg
;
31 static BOOL
regdb_store_reg_keys( char *keyname
, REGSUBKEY_CTR
*ctr
);
32 static int regdb_fetch_reg_keys( char* key
, REGSUBKEY_CTR
*ctr
);
36 /* List the deepest path into the registry. All part components will be created.*/
38 /* If you want to have a part of the path controlled by the tdb abd part by
39 a virtual registry db (e.g. printing), then you have to list the deepest path.
40 For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print"
41 allows the reg_db backend to handle everything up to
42 "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook
43 the reg_printing backend onto the last component of the path (see
44 KEY_PRINTING_2K in include/rpc_reg.h) --jerry */
46 static const char *builtin_registry_paths
[] = {
47 "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print",
48 "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports",
49 "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print",
50 "HKLM\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
51 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares",
52 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\EventLog",
53 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters",
54 "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters",
59 #if 0 /* not used yet */
60 struct builtin_regkey_value
{
62 const char *valuename
;
70 static struct builtin_regkey_value builtin_values
[] = {
71 { "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "SystemRoot", REG_SZ
, { "c:\\Windows" } },
75 #define REGVER_V1 1 /* first db version with write support */
77 /***********************************************************************
78 Open the registry data in the tdb
79 ***********************************************************************/
81 static BOOL
init_registry_data( void )
83 pstring path
, base
, remaining
;
84 fstring keyname
, subkeyname
;
85 REGSUBKEY_CTR subkeys
;
89 /* loop over all of the predefined paths and add each component */
91 for ( i
=0; builtin_registry_paths
[i
] != NULL
; i
++ ) {
93 DEBUG(6,("init_registry_data: Adding [%s]\n", builtin_registry_paths
[i
]));
95 pstrcpy( path
, builtin_registry_paths
[i
] );
99 while ( next_token(&p
, keyname
, "\\", sizeof(keyname
)) ) {
101 /* build up the registry path from the components */
104 pstrcat( base
, "\\" );
105 pstrcat( base
, keyname
);
107 /* get the immediate subkeyname (if we have one ) */
111 pstrcpy( remaining
, p
);
114 if ( !next_token(&p2
, subkeyname
, "\\", sizeof(subkeyname
)) )
115 fstrcpy( subkeyname
, p2
);
118 DEBUG(10,("init_registry_data: Storing key [%s] with subkey [%s]\n",
119 base
, *subkeyname
? subkeyname
: "NULL"));
121 /* we don't really care if the lookup succeeds or not since
122 we are about to update the record. We just want any
123 subkeys already present */
125 regsubkey_ctr_init( &subkeys
);
127 regdb_fetch_reg_keys( base
, &subkeys
);
129 regsubkey_ctr_addkey( &subkeys
, subkeyname
);
130 if ( !regdb_store_reg_keys( base
, &subkeys
))
133 regsubkey_ctr_destroy( &subkeys
);
140 /***********************************************************************
141 Open the registry database
142 ***********************************************************************/
144 BOOL
init_registry_db( void )
146 const char *vstring
= "INFO/version";
152 /* placeholder tdb; reinit upon startup */
154 if ( !(tdb_reg
= tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0600)) )
156 tdb_reg
= tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
158 DEBUG(0,("init_registry: Failed to open registry %s (%s)\n",
159 lock_path("registry.tdb"), strerror(errno
) ));
163 DEBUG(10,("init_registry: Successfully created registry tdb\n"));
167 vers_id
= tdb_fetch_int32(tdb_reg
, vstring
);
169 if ( vers_id
!= REGVER_V1
) {
171 /* create the registry here */
173 if ( !init_registry_data() ) {
174 DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
182 /**********************************************************************
183 The full path to the registry key is used as database after the
184 \'s are converted to /'s. Key string is also normalized to UPPER
186 **********************************************************************/
188 static void normalize_reg_path( pstring keyname
)
190 pstring_sub( keyname
, "\\", "/" );
191 strupper_m( keyname
);
194 /***********************************************************************
195 Add subkey strings to the registry tdb under a defined key
196 fmt is the same format as tdb_pack except this function only supports
198 ***********************************************************************/
200 static BOOL
regdb_store_reg_keys_internal( char *key
, REGSUBKEY_CTR
*ctr
)
203 char *buffer
, *tmpbuf
;
207 uint32 num_subkeys
= regsubkey_ctr_numkeys( ctr
);
213 pstrcpy( keyname
, key
);
214 normalize_reg_path( keyname
);
216 /* allocate some initial memory */
218 buffer
= SMB_MALLOC(sizeof(pstring
));
219 buflen
= sizeof(pstring
);
222 /* store the number of subkeys */
224 len
+= tdb_pack(buffer
+len
, buflen
-len
, "d", num_subkeys
);
226 /* pack all the strings */
228 for (i
=0; i
<num_subkeys
; i
++) {
229 len
+= tdb_pack( buffer
+len
, buflen
-len
, "f", regsubkey_ctr_specific_key(ctr
, i
) );
230 if ( len
> buflen
) {
231 /* allocate some extra space */
232 if ((tmpbuf
= SMB_REALLOC( buffer
, len
*2 )) == NULL
) {
233 DEBUG(0,("regdb_store_reg_keys: Failed to realloc memory of size [%d]\n", len
*2));
240 len
= tdb_pack( buffer
+len
, buflen
-len
, "f", regsubkey_ctr_specific_key(ctr
, i
) );
244 /* finally write out the data */
247 kbuf
.dsize
= strlen(keyname
)+1;
250 if ( tdb_store( tdb_reg
, kbuf
, dbuf
, TDB_REPLACE
) == -1) {
261 /***********************************************************************
262 Store the new subkey record and create any child key records that
263 do not currently exist
264 ***********************************************************************/
266 static BOOL
regdb_store_reg_keys( char *key
, REGSUBKEY_CTR
*ctr
)
270 REGSUBKEY_CTR subkeys
, old_subkeys
;
273 /* fetch a list of the old subkeys so we can difure out if any were deleted */
275 regsubkey_ctr_init( &old_subkeys
);
276 regdb_fetch_reg_keys( key
, &old_subkeys
);
278 /* store the subkey list for the parent */
280 if ( !regdb_store_reg_keys_internal( key
, ctr
) ) {
281 DEBUG(0,("regdb_store_reg_keys: Failed to store new subkey list for parent [%s}\n", key
));
285 /* now delete removed keys */
287 num_subkeys
= regsubkey_ctr_numkeys( &old_subkeys
);
288 for ( i
=0; i
<num_subkeys
; i
++ ) {
289 oldkeyname
= regsubkey_ctr_specific_key( &old_subkeys
, i
);
290 if ( !regsubkey_ctr_key_exists( ctr
, oldkeyname
) ) {
291 pstr_sprintf( path
, "%s%c%s", key
, '/', oldkeyname
);
292 normalize_reg_path( path
);
293 tdb_delete_bystring( tdb_reg
, path
);
297 /* now create records for any subkeys that don't already exist */
299 num_subkeys
= regsubkey_ctr_numkeys( ctr
);
300 for ( i
=0; i
<num_subkeys
; i
++ ) {
301 pstr_sprintf( path
, "%s%c%s", key
, '/', regsubkey_ctr_specific_key( ctr
, i
) );
302 regsubkey_ctr_init( &subkeys
);
303 if ( regdb_fetch_reg_keys( path
, &subkeys
) == -1 ) {
304 /* create a record with 0 subkeys */
305 if ( !regdb_store_reg_keys_internal( path
, &subkeys
) ) {
306 DEBUG(0,("regdb_store_reg_keys: Failed to store new record for key [%s}\n", path
));
307 regsubkey_ctr_destroy( &subkeys
);
311 regsubkey_ctr_destroy( &subkeys
);
318 /***********************************************************************
319 Retrieve an array of strings containing subkeys. Memory should be
320 released by the caller. The subkeys are stored in a catenated string
321 of null terminated character strings
322 ***********************************************************************/
324 static int regdb_fetch_reg_keys( char* key
, REGSUBKEY_CTR
*ctr
)
334 DEBUG(10,("regdb_fetch_reg_keys: Enter key => [%s]\n", key
? key
: "NULL"));
336 pstrcpy( path
, key
);
338 /* convert to key format */
339 pstring_sub( path
, "\\", "/" );
342 dbuf
= tdb_fetch_bystring( tdb_reg
, path
);
348 DEBUG(5,("regdb_fetch_reg_keys: tdb lookup failed to locate key [%s]\n", key
));
352 len
= tdb_unpack( buf
, buflen
, "d", &num_items
);
354 for (i
=0; i
<num_items
; i
++) {
355 len
+= tdb_unpack( buf
+len
, buflen
-len
, "f", subkeyname
);
356 regsubkey_ctr_addkey( ctr
, subkeyname
);
359 SAFE_FREE( dbuf
.dptr
);
361 DEBUG(10,("regdb_fetch_reg_keys: Exit [%d] items\n", num_items
));
367 /***********************************************************************
368 Retrieve an array of strings containing subkeys. Memory should be
369 released by the caller. The subkeys are stored in a catenated string
370 of null terminated character strings
371 ***********************************************************************/
373 static int regdb_fetch_reg_values( char* key
, REGVAL_CTR
*val
)
377 DEBUG(10,("regdb_fetch_reg_values: Looking for value of key [%s] \n", key
));
382 /***********************************************************************
383 Stub function since we do not currently support storing registry
384 values in the registry.tdb
385 ***********************************************************************/
387 static BOOL
regdb_store_reg_values( char *key
, REGVAL_CTR
*val
)
394 * Table of function pointers for default access
397 REGISTRY_OPS regdb_ops
= {
398 regdb_fetch_reg_keys
,
399 regdb_fetch_reg_values
,
400 regdb_store_reg_keys
,
401 regdb_store_reg_values
,