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