79539598ab92044629f8732906164f7cc3cb07cd
[kai/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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* Implementation of registry frontend view functions. */
21
22 #include "includes.h"
23
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_REGISTRY
26
27 struct regsubkey_ctr {
28         uint32_t        num_subkeys;
29         char            **subkeys;
30         struct db_context *subkeys_hash;
31         int seqnum;
32 };
33
34 /**********************************************************************
35
36  Note that the struct regsubkey_ctr and struct regval_ctr objects *must* be
37  talloc()'d since the methods use the object pointer as the talloc
38  context for internal private data.
39
40  There is no longer a regval_ctr_intit() and regval_ctr_destroy()
41  pair of functions.  Simply TALLOC_ZERO_P() and TALLOC_FREE() the
42  object.
43
44  **********************************************************************/
45
46 WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr)
47 {
48         if (ctr == NULL) {
49                 return WERR_INVALID_PARAM;
50         }
51
52         *ctr = talloc_zero(mem_ctx, struct regsubkey_ctr);
53         if (*ctr == NULL) {
54                 return WERR_NOMEM;
55         }
56
57         (*ctr)->subkeys_hash = db_open_rbt(*ctr);
58         if ((*ctr)->subkeys_hash == NULL) {
59                 talloc_free(*ctr);
60                 return WERR_NOMEM;
61         }
62
63         return WERR_OK;
64 }
65
66 WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum)
67 {
68         if (ctr == NULL) {
69                 return WERR_INVALID_PARAM;
70         }
71
72         ctr->seqnum = seqnum;
73
74         return WERR_OK;
75 }
76
77 int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr)
78 {
79         if (ctr == NULL) {
80                 return -1;
81         }
82
83         return ctr->seqnum;
84 }
85
86 static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr,
87                                          const char *keyname,
88                                          uint32 idx)
89 {
90         WERROR werr;
91
92         werr = ntstatus_to_werror(dbwrap_store_bystring(ctr->subkeys_hash,
93                                                 keyname,
94                                                 make_tdb_data((uint8 *)&idx,
95                                                               sizeof(idx)),
96                                                 TDB_REPLACE));
97         if (!W_ERROR_IS_OK(werr)) {
98                 DEBUG(1, ("error hashing new key '%s' in container: %s\n",
99                           keyname, win_errstr(werr)));
100         }
101
102         return werr;
103 }
104
105 static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr,
106                                            const char *keyname)
107 {
108         WERROR werr;
109
110         werr = ntstatus_to_werror(dbwrap_delete_bystring(ctr->subkeys_hash,
111                                   keyname));
112         if (!W_ERROR_IS_OK(werr)) {
113                 DEBUG(1, ("error unhashing key '%s' in container: %s\n",
114                           keyname, win_errstr(werr)));
115         }
116
117         return werr;
118 }
119
120 static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr,
121                                               const char *keyname,
122                                               uint32 *idx)
123 {
124         TDB_DATA data;
125
126         if ((ctr == NULL) || (keyname == NULL)) {
127                 return WERR_INVALID_PARAM;
128         }
129
130         data = dbwrap_fetch_bystring(ctr->subkeys_hash, ctr, keyname);
131         if (data.dptr == NULL) {
132                 return WERR_NOT_FOUND;
133         }
134
135         if (data.dsize != sizeof(*idx)) {
136                 talloc_free(data.dptr);
137                 return WERR_INVALID_DATATYPE;
138         }
139
140         if (idx != NULL) {
141                 *idx = *(uint32 *)data.dptr;
142         }
143
144         talloc_free(data.dptr);
145         return WERR_OK;
146 }
147
148 /***********************************************************************
149  Add a new key to the array
150  **********************************************************************/
151
152 WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname )
153 {
154         char **newkeys;
155         WERROR werr;
156
157         if ( !keyname ) {
158                 return WERR_OK;
159         }
160
161         /* make sure the keyname is not already there */
162
163         if ( regsubkey_ctr_key_exists( ctr, keyname ) ) {
164                 return WERR_OK;
165         }
166
167         if (!(newkeys = TALLOC_REALLOC_ARRAY(ctr, ctr->subkeys, char *,
168                                              ctr->num_subkeys+1))) {
169                 return WERR_NOMEM;
170         }
171
172         ctr->subkeys = newkeys;
173
174         if (!(ctr->subkeys[ctr->num_subkeys] = talloc_strdup(ctr->subkeys,
175                                                              keyname ))) {
176                 /*
177                  * Don't shrink the new array again, this wastes a pointer
178                  */
179                 return WERR_NOMEM;
180         }
181
182         werr = regsubkey_ctr_hash_keyname(ctr, keyname, ctr->num_subkeys);
183         W_ERROR_NOT_OK_RETURN(werr);
184
185         ctr->num_subkeys++;
186
187         return WERR_OK;
188 }
189
190  /***********************************************************************
191  Delete a key from the array
192  **********************************************************************/
193
194 WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname )
195 {
196         WERROR werr;
197         uint32 idx, j;
198
199         if (keyname == NULL) {
200                 return WERR_INVALID_PARAM;
201         }
202
203         /* make sure the keyname is actually already there */
204
205         werr = regsubkey_ctr_index_for_keyname(ctr, keyname, &idx);
206         W_ERROR_NOT_OK_RETURN(werr);
207
208         werr = regsubkey_ctr_unhash_keyname(ctr, keyname);
209         W_ERROR_NOT_OK_RETURN(werr);
210
211         /* update if we have any keys left */
212         ctr->num_subkeys--;
213         if (idx < ctr->num_subkeys) {
214                 memmove(&ctr->subkeys[idx], &ctr->subkeys[idx+1],
215                         sizeof(char *) * (ctr->num_subkeys - idx));
216
217                 /* we have to re-hash rest of the array...  :-( */
218                 for (j = idx; j < ctr->num_subkeys; j++) {
219                         werr = regsubkey_ctr_hash_keyname(ctr, ctr->subkeys[j], j);
220                         W_ERROR_NOT_OK_RETURN(werr);
221                 }
222         }
223
224         return WERR_OK;
225 }
226
227 /***********************************************************************
228  Check for the existance of a key
229  **********************************************************************/
230
231 bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname )
232 {
233         WERROR werr;
234
235         if (!ctr->subkeys) {
236                 return False;
237         }
238
239         werr = regsubkey_ctr_index_for_keyname(ctr, keyname, NULL);
240         if (!W_ERROR_IS_OK(werr)) {
241                 return false;
242         }
243
244         return true;
245 }
246
247 /***********************************************************************
248  How many keys does the container hold ?
249  **********************************************************************/
250
251 int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr )
252 {
253         return ctr->num_subkeys;
254 }
255
256 /***********************************************************************
257  Retreive a specific key string
258  **********************************************************************/
259
260 char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32_t key_index )
261 {
262         if ( ! (key_index < ctr->num_subkeys) )
263                 return NULL;
264
265         return ctr->subkeys[key_index];
266 }
267
268 /*
269  * Utility functions for struct regval_ctr
270  */
271
272 /***********************************************************************
273  How many keys does the container hold ?
274  **********************************************************************/
275
276 int regval_ctr_numvals(struct regval_ctr *ctr)
277 {
278         return ctr->num_values;
279 }
280
281 /***********************************************************************
282  allocate memory for and duplicate a REGISTRY_VALUE.
283  This is malloc'd memory so the caller should free it when done
284  **********************************************************************/
285
286 REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
287 {
288         REGISTRY_VALUE  *copy = NULL;
289
290         if ( !val )
291                 return NULL;
292
293         if ( !(copy = SMB_MALLOC_P( REGISTRY_VALUE)) ) {
294                 DEBUG(0,("dup_registry_value: malloc() failed!\n"));
295                 return NULL;
296         }
297
298         /* copy all the non-pointer initial data */
299
300         memcpy( copy, val, sizeof(REGISTRY_VALUE) );
301
302         copy->size = 0;
303         copy->data_p = NULL;
304
305         if ( val->data_p && val->size )
306         {
307                 if ( !(copy->data_p = (uint8 *)memdup( val->data_p,
308                                                        val->size )) ) {
309                         DEBUG(0,("dup_registry_value: memdup() failed for [%d] "
310                                  "bytes!\n", val->size));
311                         SAFE_FREE( copy );
312                         return NULL;
313                 }
314                 copy->size = val->size;
315         }
316
317         return copy;
318 }
319
320 /**********************************************************************
321  free the memory allocated to a REGISTRY_VALUE
322  *********************************************************************/
323
324 void free_registry_value( REGISTRY_VALUE *val )
325 {
326         if ( !val )
327                 return;
328
329         SAFE_FREE( val->data_p );
330         SAFE_FREE( val );
331
332         return;
333 }
334
335 /**********************************************************************
336  *********************************************************************/
337
338 uint8* regval_data_p( REGISTRY_VALUE *val )
339 {
340         return val->data_p;
341 }
342
343 /**********************************************************************
344  *********************************************************************/
345
346 uint32 regval_size( REGISTRY_VALUE *val )
347 {
348         return val->size;
349 }
350
351 /**********************************************************************
352  *********************************************************************/
353
354 char* regval_name( REGISTRY_VALUE *val )
355 {
356         return val->valuename;
357 }
358
359 /**********************************************************************
360  *********************************************************************/
361
362 uint32 regval_type( REGISTRY_VALUE *val )
363 {
364         return val->type;
365 }
366
367 /***********************************************************************
368  Retreive a pointer to a specific value.  Caller shoud dup the structure
369  since this memory will go away when the ctr is free()'d
370  **********************************************************************/
371
372 REGISTRY_VALUE* regval_ctr_specific_value(struct regval_ctr *ctr, uint32 idx)
373 {
374         if ( !(idx < ctr->num_values) )
375                 return NULL;
376
377         return ctr->values[idx];
378 }
379
380 /***********************************************************************
381  Check for the existance of a value
382  **********************************************************************/
383
384 bool regval_ctr_key_exists(struct regval_ctr *ctr, const char *value)
385 {
386         int     i;
387
388         for ( i=0; i<ctr->num_values; i++ ) {
389                 if ( strequal( ctr->values[i]->valuename, value) )
390                         return True;
391         }
392
393         return False;
394 }
395
396 /***********************************************************************
397  * compose a REGISTRY_VALUE from input data
398  **********************************************************************/
399
400 REGISTRY_VALUE *regval_compose(TALLOC_CTX *ctx, const char *name, uint16 type,
401                                const char *data_p, size_t size)
402 {
403         REGISTRY_VALUE *regval = TALLOC_P(ctx, REGISTRY_VALUE);
404
405         if (regval == NULL) {
406                 return NULL;
407         }
408
409         fstrcpy(regval->valuename, name);
410         regval->type = type;
411         if (size) {
412                 regval->data_p = (uint8 *)TALLOC_MEMDUP(regval, data_p, size);
413                 if (!regval->data_p) {
414                         TALLOC_FREE(regval);
415                         return NULL;
416                 }
417         } else {
418                 regval->data_p = NULL;
419         }
420         regval->size = size;
421
422         return regval;
423 }
424
425 /***********************************************************************
426  Add a new registry value to the array
427  **********************************************************************/
428
429 int regval_ctr_addvalue(struct regval_ctr *ctr, const char *name, uint16 type,
430                         const char *data_p, size_t size)
431 {
432         if ( !name )
433                 return ctr->num_values;
434
435         /* Delete the current value (if it exists) and add the new one */
436
437         regval_ctr_delvalue( ctr, name );
438
439         /* allocate a slot in the array of pointers */
440
441         if (  ctr->num_values == 0 ) {
442                 ctr->values = TALLOC_P( ctr, REGISTRY_VALUE *);
443         } else {
444                 ctr->values = TALLOC_REALLOC_ARRAY(ctr, ctr->values,
445                                                    REGISTRY_VALUE *,
446                                                    ctr->num_values+1);
447         }
448
449         if (!ctr->values) {
450                 ctr->num_values = 0;
451                 return 0;
452         }
453
454         /* allocate a new value and store the pointer in the arrya */
455
456         ctr->values[ctr->num_values] = regval_compose(ctr, name, type, data_p,
457                                                       size);
458         if (ctr->values[ctr->num_values] == NULL) {
459                 ctr->num_values = 0;
460                 return 0;
461         }
462         ctr->num_values++;
463
464         return ctr->num_values;
465 }
466
467 /***********************************************************************
468  Add a new registry value to the array
469  **********************************************************************/
470
471 int regval_ctr_copyvalue(struct regval_ctr *ctr, REGISTRY_VALUE *val)
472 {
473         if ( val ) {
474                 regval_ctr_addvalue(ctr, val->valuename, val->type,
475                                     (char *)val->data_p, val->size);
476         }
477
478         return ctr->num_values;
479 }
480
481 /***********************************************************************
482  Delete a single value from the registry container.
483  No need to free memory since it is talloc'd.
484  **********************************************************************/
485
486 int regval_ctr_delvalue(struct regval_ctr *ctr, const char *name)
487 {
488         int     i;
489
490         for ( i=0; i<ctr->num_values; i++ ) {
491                 if ( strequal( ctr->values[i]->valuename, name ) )
492                         break;
493         }
494
495         /* just return if we don't find it */
496
497         if ( i == ctr->num_values )
498                 return ctr->num_values;
499
500         /* If 'i' was not the last element, just shift everything down one */
501         ctr->num_values--;
502         if ( i < ctr->num_values )
503                 memmove(&ctr->values[i], &ctr->values[i+1],
504                         sizeof(REGISTRY_VALUE*)*(ctr->num_values-i));
505
506         return ctr->num_values;
507 }
508
509 /***********************************************************************
510  Retrieve single value from the registry container.
511  No need to free memory since it is talloc'd.
512  **********************************************************************/
513
514 REGISTRY_VALUE* regval_ctr_getvalue(struct regval_ctr *ctr, const char *name)
515 {
516         int     i;
517
518         /* search for the value */
519
520         for ( i=0; i<ctr->num_values; i++ ) {
521                 if ( strequal( ctr->values[i]->valuename, name ) )
522                         return ctr->values[i];
523         }
524
525         return NULL;
526 }
527
528 /***********************************************************************
529  return the data_p as a uint32
530  **********************************************************************/
531
532 uint32 regval_dword( REGISTRY_VALUE *val )
533 {
534         uint32 data;
535
536         data = IVAL( regval_data_p(val), 0 );
537
538         return data;
539 }
540
541 /***********************************************************************
542  return the data_p as a character string
543  **********************************************************************/
544
545 char *regval_sz(REGISTRY_VALUE *val)
546 {
547         char *data = NULL;
548
549         rpcstr_pull_talloc(talloc_tos(), &data,
550                         regval_data_p(val), regval_size(val),0);
551         return data;
552 }