b0917c8f603a545d504e628ae0e1e3b019c0e3e1
[samba.git] / source / registry / reg_db.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 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
31 /***********************************************************************
32  Open the registry data in the tdb
33  ***********************************************************************/
34  
35 static BOOL init_registry_data( void )
36 {
37         pstring         keyname;
38         REGSUBKEY_CTR   subkeys;
39
40         ZERO_STRUCTP( &subkeys );
41
42         /* HKEY_LOCAL_MACHINE */
43         
44         regsubkey_ctr_init( &subkeys );
45         pstrcpy( keyname, KEY_HKLM );
46         regsubkey_ctr_addkey( &subkeys, "SYSTEM" );
47         if ( !regdb_store_reg_keys( keyname, &subkeys ))
48                 return False;
49         regsubkey_ctr_destroy( &subkeys );
50                 
51         regsubkey_ctr_init( &subkeys );
52         pstrcpy( keyname, KEY_HKLM );
53         pstrcat( keyname, "/SYSTEM" );
54         regsubkey_ctr_addkey( &subkeys, "CurrentControlSet" );
55         if ( !regdb_store_reg_keys( keyname, &subkeys ))
56                 return False;
57         regsubkey_ctr_destroy( &subkeys );
58                 
59         regsubkey_ctr_init( &subkeys );
60         pstrcpy( keyname, KEY_HKLM );
61         pstrcat( keyname, "/SYSTEM/CurrentControlSet" );
62         regsubkey_ctr_addkey( &subkeys, "Control" );
63         regsubkey_ctr_addkey( &subkeys, "Services" );
64         if ( !regdb_store_reg_keys( keyname, &subkeys ))
65                 return False;
66         regsubkey_ctr_destroy( &subkeys );
67
68         regsubkey_ctr_init( &subkeys );
69         pstrcpy( keyname, KEY_HKLM );
70         pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control" );
71         regsubkey_ctr_addkey( &subkeys, "Print" );
72         regsubkey_ctr_addkey( &subkeys, "ProductOptions" );
73         if ( !regdb_store_reg_keys( keyname, &subkeys ))
74                 return False;
75         regsubkey_ctr_destroy( &subkeys );
76
77         pstrcpy( keyname, KEY_HKLM );
78         pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/ProductOptions" );
79         if ( !regdb_store_reg_keys( keyname, &subkeys ))
80                 return False;
81
82         regsubkey_ctr_init( &subkeys );
83         pstrcpy( keyname, KEY_HKLM );
84         pstrcat( keyname, "/SYSTEM/CurrentControlSet/Services" );
85         regsubkey_ctr_addkey( &subkeys, "Netlogon" );
86         if ( !regdb_store_reg_keys( keyname, &subkeys ))
87                 return False;
88         regsubkey_ctr_destroy( &subkeys );
89                 
90         regsubkey_ctr_init( &subkeys );
91         pstrcpy( keyname, KEY_HKLM );
92         pstrcat( keyname, "/SYSTEM/CurrentControlSet/Services/Netlogon" );
93         regsubkey_ctr_addkey( &subkeys, "Parameters" );
94         if ( !regdb_store_reg_keys( keyname, &subkeys ))
95                 return False;
96         regsubkey_ctr_destroy( &subkeys );
97                 
98         pstrcpy( keyname, KEY_HKLM );
99         pstrcat( keyname, "/SYSTEM/CurrentControlSet/Services/Netlogon/Parameters" );
100         if ( !regdb_store_reg_keys( keyname, &subkeys ))
101                 return False;
102         
103         /* HKEY_USER */
104                 
105         pstrcpy( keyname, KEY_HKU );
106         if ( !regdb_store_reg_keys( keyname, &subkeys ) )
107                 return False;
108                 
109         /* HKEY_CLASSES_ROOT*/
110                 
111         pstrcpy( keyname, KEY_HKCR );
112         if ( !regdb_store_reg_keys( keyname, &subkeys ) )
113                 return False;
114                 
115         return True;
116 }
117
118 /***********************************************************************
119  Open the registry database
120  ***********************************************************************/
121  
122 BOOL init_registry_db( void )
123 {
124         static pid_t local_pid;
125
126         if (tdb_reg && local_pid == sys_getpid())
127                 return True;
128
129         /* 
130          * try to open first without creating so we can determine
131          * if we need to init the data in the registry
132          */
133         
134         tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
135         if ( !tdb_reg ) 
136         {
137                 tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
138                 if ( !tdb_reg ) {
139                         DEBUG(0,("init_registry: Failed to open registry %s (%s)\n",
140                                 lock_path("registry.tdb"), strerror(errno) ));
141                         return False;
142                 }
143                 
144                 DEBUG(10,("init_registry: Successfully created registry tdb\n"));
145                 
146                 /* create the registry here */
147                 if ( !init_registry_data() ) {
148                         DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
149                         return False;
150                 }
151         }
152
153         local_pid = sys_getpid();
154                 
155         return True;
156 }
157
158
159
160 /***********************************************************************
161  Add subkey strings to the registry tdb under a defined key
162  fmt is the same format as tdb_pack except this function only supports
163  fstrings
164
165  The full path to the registry key is used as database after the 
166  \'s are converted to /'s.  Key string is also normalized to UPPER
167  case.
168  ***********************************************************************/
169  
170 BOOL regdb_store_reg_keys( char *keyname, REGSUBKEY_CTR *ctr )
171 {
172         TDB_DATA kbuf, dbuf;
173         char *buffer, *tmpbuf;
174         int i = 0;
175         uint32 len, buflen;
176         BOOL ret = True;
177         uint32 num_subkeys = regsubkey_ctr_numkeys( ctr );
178         
179         if ( !keyname )
180                 return False;
181         
182         strupper_m( keyname  );
183         
184         /* allocate some initial memory */
185                 
186         buffer = malloc(sizeof(pstring));
187         buflen = sizeof(pstring);
188         len = 0;
189         
190         /* store the number of subkeys */
191         
192         len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys );
193         
194         /* pack all the strings */
195         
196         for (i=0; i<num_subkeys; i++) {
197                 len += tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
198                 if ( len > buflen ) {
199                         /* allocate some extra space */
200                         if ((tmpbuf = Realloc( buffer, len*2 )) == NULL) {
201                                 DEBUG(0,("regdb_store_reg_keys: Failed to realloc memory of size [%d]\n", len*2));
202                                 ret = False;
203                                 goto done;
204                         }
205                         buffer = tmpbuf;
206                         buflen = len*2;
207                                         
208                         len = tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
209                 }               
210         }
211         
212         /* finally write out the data */
213         
214         kbuf.dptr = keyname;
215         kbuf.dsize = strlen(keyname)+1;
216         dbuf.dptr = buffer;
217         dbuf.dsize = len;
218         if ( tdb_store( tdb_reg, kbuf, dbuf, TDB_REPLACE ) == -1) {
219                 ret = False;
220                 goto done;
221         }
222
223 done:           
224         SAFE_FREE( buffer );
225         
226         return ret;
227 }
228
229 /***********************************************************************
230  Retrieve an array of strings containing subkeys.  Memory should be 
231  released by the caller.  The subkeys are stored in a catenated string
232  of null terminated character strings
233  ***********************************************************************/
234
235 int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr )
236 {
237         pstring path;
238         uint32 num_items;
239         TDB_DATA dbuf;
240         char *buf;
241         uint32 buflen, len;
242         int i;
243         fstring subkeyname;
244
245         DEBUG(10,("regdb_fetch_reg_keys: Enter key => [%s]\n", key ? key : "NULL"));
246         
247         pstrcpy( path, key );
248         
249         /* convert to key format */
250         pstring_sub( path, "\\", "/" ); 
251         strupper_m( path );
252         
253         dbuf = tdb_fetch_by_string( tdb_reg, path );
254         
255         buf = dbuf.dptr;
256         buflen = dbuf.dsize;
257         
258         if ( !buf ) {
259                 DEBUG(5,("regdb_fetch_reg_keys: tdb lookup failed to locate key [%s]\n", key));
260                 return -1;
261         }
262         
263         len = tdb_unpack( buf, buflen, "d", &num_items);
264         
265         for (i=0; i<num_items; i++) {
266                 len += tdb_unpack( buf+len, buflen-len, "f", subkeyname );
267                 regsubkey_ctr_addkey( ctr, subkeyname );
268         }
269
270         SAFE_FREE( dbuf.dptr );
271         
272         DEBUG(10,("regdb_fetch_reg_keys: Exit [%d] items\n", num_items));
273         
274         return num_items;
275 }
276
277
278 /***********************************************************************
279  Retrieve an array of strings containing subkeys.  Memory should be 
280  released by the caller.  The subkeys are stored in a catenated string
281  of null terminated character strings
282  ***********************************************************************/
283
284 int regdb_fetch_reg_values( char* key, REGVAL_CTR *val )
285 {
286         return 0;
287 }
288
289 /***********************************************************************
290  Stub function since we do not currently support storing registry 
291  values in the registry.tdb
292  ***********************************************************************/
293
294 BOOL regdb_store_reg_values( char *key, REGVAL_CTR *val )
295 {
296         return False;
297 }
298
299
300 /* 
301  * Table of function pointers for default access
302  */
303  
304 REGISTRY_OPS regdb_ops = {
305         regdb_fetch_reg_keys,
306         regdb_fetch_reg_values,
307         regdb_store_reg_keys,
308         regdb_store_reg_values
309 };
310
311