r19777: Make regsubkey_ctr_addkey return WERROR. Nobody checks this so far, but this
[amitay/samba.git] / source3 / registry / reg_objects.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 frontend view functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /**********************************************************************
29
30  Note that the REGSUB_CTR and REGVAL_CTR objects *must* be talloc()'d
31  since the methods use the object pointer as the talloc context for 
32  internal private data.
33
34  There is no longer a regXXX_ctr_intit() and regXXX_ctr_destroy()
35  pair of functions.  Simply TALLOC_ZERO_P() and TALLOC_FREE() the 
36  object.
37
38  **********************************************************************/
39
40 /***********************************************************************
41  Add a new key to the array
42  **********************************************************************/
43
44 WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
45 {
46         char **newkeys;
47
48         if ( !keyname ) {
49                 return WERR_OK;
50         }
51
52         /* make sure the keyname is not already there */
53
54         if ( regsubkey_ctr_key_exists( ctr, keyname ) ) {
55                 return WERR_OK;
56         }
57
58         if (!(newkeys = TALLOC_REALLOC_ARRAY(ctr, ctr->subkeys, char *,
59                                              ctr->num_subkeys+1))) {
60                 return WERR_NOMEM;
61         }
62
63         ctr->subkeys = newkeys;
64
65         if (!(ctr->subkeys[ctr->num_subkeys] = talloc_strdup(ctr->subkeys,
66                                                              keyname ))) {
67                 /*
68                  * Don't shrink the new array again, this wastes a pointer
69                  */
70                 return WERR_NOMEM;
71         }
72         ctr->num_subkeys++;
73
74         return WERR_OK;
75 }
76  
77  /***********************************************************************
78  Add a new key to the array
79  **********************************************************************/
80
81 int regsubkey_ctr_delkey( REGSUBKEY_CTR *ctr, const char *keyname )
82 {
83         int i;
84
85         if ( !keyname )
86                 return ctr->num_subkeys;
87
88         /* make sure the keyname is actually already there */
89
90         for ( i=0; i<ctr->num_subkeys; i++ ) {
91                 if ( strequal( ctr->subkeys[i], keyname ) )
92                         break;
93         }
94         
95         if ( i == ctr->num_subkeys )
96                 return ctr->num_subkeys;
97
98         /* update if we have any keys left */
99         ctr->num_subkeys--;
100         if ( i < ctr->num_subkeys )
101                 memmove( &ctr->subkeys[i], &ctr->subkeys[i+1], sizeof(char*) * (ctr->num_subkeys-i) );
102         
103         return ctr->num_subkeys;
104 }
105
106 /***********************************************************************
107  Check for the existance of a key
108  **********************************************************************/
109
110 BOOL regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname )
111 {
112         int     i;
113         
114         if (!ctr->subkeys) {
115                 return False;
116         }
117
118         for ( i=0; i<ctr->num_subkeys; i++ ) {
119                 if ( strequal( ctr->subkeys[i],keyname ) )
120                         return True;
121         }
122         
123         return False;
124 }
125
126 /***********************************************************************
127  How many keys does the container hold ?
128  **********************************************************************/
129
130 int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
131 {
132         return ctr->num_subkeys;
133 }
134
135 /***********************************************************************
136  Retreive a specific key string
137  **********************************************************************/
138
139 char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index )
140 {
141         if ( ! (key_index < ctr->num_subkeys) )
142                 return NULL;
143                 
144         return ctr->subkeys[key_index];
145 }
146
147 /*
148  * Utility functions for REGVAL_CTR
149  */
150
151 /***********************************************************************
152  How many keys does the container hold ?
153  **********************************************************************/
154
155 int regval_ctr_numvals( REGVAL_CTR *ctr )
156 {
157         return ctr->num_values;
158 }
159
160 /***********************************************************************
161  allocate memory for and duplicate a REGISTRY_VALUE.
162  This is malloc'd memory so the caller should free it when done
163  **********************************************************************/
164
165 REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
166 {
167         REGISTRY_VALUE  *copy = NULL;
168         
169         if ( !val )
170                 return NULL;
171         
172         if ( !(copy = SMB_MALLOC_P( REGISTRY_VALUE)) ) {
173                 DEBUG(0,("dup_registry_value: malloc() failed!\n"));
174                 return NULL;
175         }
176         
177         /* copy all the non-pointer initial data */
178         
179         memcpy( copy, val, sizeof(REGISTRY_VALUE) );
180         
181         copy->size = 0;
182         copy->data_p = NULL;
183         
184         if ( val->data_p && val->size ) 
185         {
186                 if ( !(copy->data_p = (uint8 *)memdup( val->data_p,
187                                                        val->size )) ) {
188                         DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
189                                 val->size));
190                         SAFE_FREE( copy );
191                         return NULL;
192                 }
193                 copy->size = val->size;
194         }
195         
196         return copy;    
197 }
198
199 /**********************************************************************
200  free the memory allocated to a REGISTRY_VALUE 
201  *********************************************************************/
202  
203 void free_registry_value( REGISTRY_VALUE *val )
204 {
205         if ( !val )
206                 return;
207                 
208         SAFE_FREE( val->data_p );
209         SAFE_FREE( val );
210         
211         return;
212 }
213
214 /**********************************************************************
215  *********************************************************************/
216
217 uint8* regval_data_p( REGISTRY_VALUE *val )
218 {
219         return val->data_p;
220 }
221
222 /**********************************************************************
223  *********************************************************************/
224
225 uint32 regval_size( REGISTRY_VALUE *val )
226 {
227         return val->size;
228 }
229
230 /**********************************************************************
231  *********************************************************************/
232
233 char* regval_name( REGISTRY_VALUE *val )
234 {
235         return val->valuename;
236 }
237
238 /**********************************************************************
239  *********************************************************************/
240
241 uint32 regval_type( REGISTRY_VALUE *val )
242 {
243         return val->type;
244 }
245
246 /***********************************************************************
247  Retreive a pointer to a specific value.  Caller shoud dup the structure
248  since this memory will go away when the ctr is free()'d
249  **********************************************************************/
250
251 REGISTRY_VALUE* regval_ctr_specific_value( REGVAL_CTR *ctr, uint32 idx )
252 {
253         if ( !(idx < ctr->num_values) )
254                 return NULL;
255                 
256         return ctr->values[idx];
257 }
258
259 /***********************************************************************
260  Check for the existance of a value
261  **********************************************************************/
262
263 BOOL regval_ctr_key_exists( REGVAL_CTR *ctr, const char *value )
264 {
265         int     i;
266         
267         for ( i=0; i<ctr->num_values; i++ ) {
268                 if ( strequal( ctr->values[i]->valuename, value) )
269                         return True;
270         }
271         
272         return False;
273 }
274 /***********************************************************************
275  Add a new registry value to the array
276  **********************************************************************/
277
278 int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type, 
279                          const char *data_p, size_t size )
280 {
281         if ( !name )
282                 return ctr->num_values;
283
284         /* Delete the current value (if it exists) and add the new one */
285
286         regval_ctr_delvalue( ctr, name );
287
288         /* allocate a slot in the array of pointers */
289                 
290         if (  ctr->num_values == 0 ) {
291                 ctr->values = TALLOC_P( ctr, REGISTRY_VALUE *);
292         } else {
293                 ctr->values = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
294         }
295
296         if (!ctr->values) {
297                 ctr->num_values = 0;
298                 return 0;
299         }
300
301         /* allocate a new value and store the pointer in the arrya */
302                 
303         ctr->values[ctr->num_values] = TALLOC_P( ctr, REGISTRY_VALUE);
304         if (!ctr->values[ctr->num_values]) {
305                 ctr->num_values = 0;
306                 return 0;
307         }
308
309         /* init the value */
310         
311         fstrcpy( ctr->values[ctr->num_values]->valuename, name );
312         ctr->values[ctr->num_values]->type = type;
313         ctr->values[ctr->num_values]->data_p = (uint8 *)TALLOC_MEMDUP(
314                 ctr, data_p, size );
315         ctr->values[ctr->num_values]->size = size;
316         ctr->num_values++;
317
318         return ctr->num_values;
319 }
320
321 /***********************************************************************
322  Add a new registry value to the array
323  **********************************************************************/
324
325 int regval_ctr_copyvalue( REGVAL_CTR *ctr, REGISTRY_VALUE *val )
326 {
327         if ( val ) {
328                 /* allocate a slot in the array of pointers */
329                 
330                 if (  ctr->num_values == 0 ) {
331                         ctr->values = TALLOC_P( ctr, REGISTRY_VALUE *);
332                 } else {
333                         ctr->values = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
334                 }
335
336                 if (!ctr->values) {
337                         ctr->num_values = 0;
338                         return 0;
339                 }
340
341                 /* allocate a new value and store the pointer in the arrya */
342                 
343                 ctr->values[ctr->num_values] = TALLOC_P( ctr, REGISTRY_VALUE);
344                 if (!ctr->values[ctr->num_values]) {
345                         ctr->num_values = 0;
346                         return 0;
347                 }
348
349                 /* init the value */
350         
351                 fstrcpy( ctr->values[ctr->num_values]->valuename, val->valuename );
352                 ctr->values[ctr->num_values]->type = val->type;
353                 ctr->values[ctr->num_values]->data_p = (uint8 *)TALLOC_MEMDUP(
354                         ctr, val->data_p, val->size );
355                 ctr->values[ctr->num_values]->size = val->size;
356                 ctr->num_values++;
357         }
358
359         return ctr->num_values;
360 }
361
362 /***********************************************************************
363  Delete a single value from the registry container.
364  No need to free memory since it is talloc'd.
365  **********************************************************************/
366
367 int regval_ctr_delvalue( REGVAL_CTR *ctr, const char *name )
368 {
369         int     i;
370         
371         for ( i=0; i<ctr->num_values; i++ ) {
372                 if ( strequal( ctr->values[i]->valuename, name ) )
373                         break;
374         }
375         
376         /* just return if we don't find it */
377         
378         if ( i == ctr->num_values )
379                 return ctr->num_values;
380         
381         /* If 'i' was not the last element, just shift everything down one */
382         ctr->num_values--;
383         if ( i < ctr->num_values )
384                 memmove( &ctr->values[i], &ctr->values[i+1], sizeof(REGISTRY_VALUE*)*(ctr->num_values-i) );
385         
386         return ctr->num_values;
387 }
388
389 /***********************************************************************
390  Retrieve single value from the registry container.
391  No need to free memory since it is talloc'd.
392  **********************************************************************/
393
394 REGISTRY_VALUE* regval_ctr_getvalue( REGVAL_CTR *ctr, const char *name )
395 {
396         int     i;
397         
398         /* search for the value */
399         
400         for ( i=0; i<ctr->num_values; i++ ) {
401                 if ( strequal( ctr->values[i]->valuename, name ) )
402                         return ctr->values[i];
403         }
404         
405         return NULL;
406 }
407
408 /***********************************************************************
409  return the data_p as a uint32
410  **********************************************************************/
411
412 uint32 regval_dword( REGISTRY_VALUE *val )
413 {
414         uint32 data;
415         
416         data = IVAL( regval_data_p(val), 0 );
417         
418         return data;
419 }
420
421 /***********************************************************************
422  return the data_p as a character string
423  **********************************************************************/
424
425 char* regval_sz( REGISTRY_VALUE *val )
426 {
427         static pstring data;
428
429         rpcstr_pull( data, regval_data_p(val), sizeof(data), regval_size(val), 0 );
430         
431         return data;
432 }