r25000: Fix some more C++ compatibility warnings.
[kai/samba.git] / source4 / lib / registry / regf.c
1 /*
2    Samba CIFS implementation
3    Registry backend for REGF files
4    Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org
5    Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19  
20 #include "includes.h"
21 #include "lib/registry/hive.h"
22 #include "system/filesys.h"
23 #include "system/time.h"
24 #include "lib/registry/tdr_regf.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "librpc/gen_ndr/winreg.h"
27
28 static struct hive_operations reg_backend_regf;
29
30 /**
31  * There are several places on the web where the REGF format is explained; 
32  *
33  * TODO: Links
34  */
35
36 /* TODO:
37  *  - Return error codes that make more sense
38  *  - Locking
39  *  - do more things in-memory
40  */
41
42 /*
43  * Read HBIN blocks into memory
44  */
45
46 struct regf_data {
47         int fd;
48         struct hbin_block **hbins;
49         struct regf_hdr *header;
50 };
51
52 static WERROR regf_save_hbin(struct regf_data *data);
53
54 struct regf_key_data {
55         struct hive_key key;
56         struct regf_data *hive; 
57         uint32_t offset;
58         struct nk_block *nk;
59 };
60
61 static struct hbin_block *hbin_by_offset(const struct regf_data *data, 
62                                                                                  uint32_t offset, uint32_t *rel_offset)
63 {
64         int i;
65
66         for (i = 0; data->hbins[i]; i++) {
67                 if (offset >= data->hbins[i]->offset_from_first && 
68                         offset < data->hbins[i]->offset_from_first+
69                                          data->hbins[i]->offset_to_next) {
70                         if (rel_offset != NULL)
71                                 *rel_offset = offset - data->hbins[i]->offset_from_first - 0x20;
72                         return data->hbins[i];
73                 }
74         }
75
76         return NULL;
77 }
78
79 /**
80  * Validate a regf header
81  * For now, do nothing, but we should check the checksum
82  */
83 static uint32_t regf_hdr_checksum(const uint8_t *buffer)
84 {
85         uint32_t checksum = 0, x;
86         int i;
87         
88         for (i = 0; i < 0x01FB; i+= 4) {
89                 x = IVAL(buffer, i);
90                 checksum ^= x;
91         }
92
93         return checksum;
94 }
95
96 /**
97  * Obtain the contents of a HBIN block
98  */
99 static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
100 {
101         DATA_BLOB ret;
102         struct hbin_block *hbin;
103         uint32_t rel_offset;
104
105         ret.data = NULL;
106         ret.length = 0;
107
108         hbin = hbin_by_offset(data, offset, &rel_offset);
109
110         if (hbin == NULL) {
111                 DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
112                 return ret;
113         }
114
115         ret.length = IVAL(hbin->data, rel_offset);
116         if (!(ret.length & 0x80000000)) {
117                 DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset));
118                 return ret;
119         }
120
121         /* remove high bit */
122         ret.length = (ret.length ^ 0xffffffff) + 1;
123
124         ret.length -= 4; /* 4 bytes for the length... */
125         ret.data = hbin->data + 
126                 (offset - hbin->offset_from_first - 0x20) + 4;
127         
128         return ret;
129 }
130
131 static bool hbin_get_tdr (struct regf_data *regf, uint32_t offset, 
132                                                   TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
133 {
134         struct tdr_pull pull;
135
136         ZERO_STRUCT(pull);
137
138         pull.data = hbin_get(regf, offset);
139         if (!pull.data.data) {
140                 DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
141                 return false;
142         }
143         
144         if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) {
145                 DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset));
146                 return false;
147         }
148
149         return true;
150 }
151
152 /* Allocate some new data */
153 static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, 
154                                                         uint32_t *offset)
155 {
156         DATA_BLOB ret;
157         uint32_t rel_offset = -1; /* Relative offset ! */
158         struct hbin_block *hbin = NULL;
159         int i;
160
161         *offset = 0;
162
163         if (size == 0)
164                 return data_blob(NULL, 0);
165
166         size += 4; /* Need to include int32 for the length */
167
168         /* Allocate as a multiple of 8 */
169         size = (size + 7) & ~7;
170
171         ret.data = NULL;
172         ret.length = 0;
173
174         for (i = 0; (hbin = data->hbins[i]); i++) {
175                 int j;
176                 int32_t my_size;
177                 for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
178                         my_size = IVALS(hbin->data, j);
179
180                         if (my_size == 0x0) {
181                                 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
182                                 return ret;
183                         }
184
185                         if (my_size % 8 != 0) {
186                                 DEBUG(0, ("Encountered non-aligned block!\n"));
187                         }
188
189                         if (my_size < 0) { /* Used... */
190                                 my_size = -my_size;
191                         } else if (my_size == size) { /* exact match */
192                                 rel_offset = j;
193                                 DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n", size));
194                                 break;
195                         } else if (my_size > size) { /* data will remain */
196                                 rel_offset = j;
197                                 /* Split this block and mark the next block as free */
198                                 SIVAL(hbin->data, rel_offset+size, my_size-size); 
199                                 DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n", my_size, size));
200                                 break;
201                         }
202                 }
203
204                 if (rel_offset != -1)
205                         break;
206         }
207         
208         /* No space available in previous hbins, 
209          * allocate new one */
210         if (data->hbins[i] == NULL) { 
211                 DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", size));
212                 data->hbins = talloc_realloc(data, data->hbins, struct hbin_block *, i+2);
213                 hbin = talloc(data->hbins, struct hbin_block);
214                 SMB_ASSERT(hbin != NULL);
215
216                 data->hbins[i] = hbin;
217                 data->hbins[i+1] = NULL;
218
219                 hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
220                 hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
221                 hbin->offset_to_next = 0x1000;
222                 hbin->unknown[0] = 0;
223                 hbin->unknown[0] = 0;
224                 unix_to_nt_time(&hbin->last_change, time(NULL));
225                 hbin->block_size = hbin->offset_to_next;
226                 hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
227
228                 rel_offset = 0x0;
229                 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
230         }
231
232         /* Set size and mark as used */
233         SIVAL(hbin->data, rel_offset, -size);
234
235         ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
236         ret.length = size - 0x4;
237         if (offset) {
238                 uint32_t new_rel_offset;
239                 *offset = hbin->offset_from_first + rel_offset + 0x20;
240                 SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin);
241                 SMB_ASSERT(new_rel_offset == rel_offset);
242         }
243
244         return ret;
245 }
246
247 /* Store a data blob. Return the offset at which it was stored */
248 static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob)
249 {
250         uint32_t ret;
251         DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
252
253         memcpy(dest.data, blob.data, blob.length);
254
255         return ret;
256 }
257
258 static uint32_t hbin_store_tdr (struct regf_data *data, tdr_push_fn_t push_fn, void *p)
259 {
260         struct tdr_push *push = talloc_zero(data, struct tdr_push);
261         uint32_t ret;
262         
263         if (NT_STATUS_IS_ERR(push_fn(push, p))) {
264                 DEBUG(0, ("Error during push\n"));
265                 return -1;
266         }
267
268         ret = hbin_store(data, push->data);
269
270         talloc_free(push);
271
272         return ret;
273 }
274
275
276 /* Free existing data */
277 static void hbin_free (struct regf_data *data, uint32_t offset)
278 {
279         int32_t size;
280         uint32_t rel_offset;
281         int32_t next_size; 
282         struct hbin_block *hbin;
283
284         SMB_ASSERT (offset > 0);
285         
286         hbin = hbin_by_offset(data, offset, &rel_offset);
287
288         if (hbin == NULL)
289                 return;
290         
291         /* Get original size */
292         size = IVALS(hbin->data, rel_offset);
293
294         if (size > 0) {
295                 DEBUG(1, ("Trying to free already freed block at 0x%04x\n", offset));
296                 return;
297         }
298         /* Mark as unused */
299         size = -size;
300         
301         /* If the next block is free, merge into big free block */
302         if (rel_offset + size < hbin->offset_to_next) {
303                 next_size = IVALS(hbin->data, rel_offset+size);
304                 if (next_size > 0) {
305                         size += next_size;
306                 }
307         }
308
309         /* Write block size */
310         SIVALS(hbin->data, rel_offset, size);
311 }
312
313 /**
314  * Store a data blob data was already stored, but has changed in size
315  * Will try to save it at the current location if possible, otherwise 
316  * does a free + store */
317 static uint32_t hbin_store_resize(struct regf_data *data, 
318                                                                   uint32_t orig_offset, DATA_BLOB blob)
319 {
320         uint32_t rel_offset;
321         struct hbin_block *hbin = hbin_by_offset(data, orig_offset, &rel_offset);
322         int32_t my_size;
323         int32_t orig_size;
324         int32_t needed_size;
325         int32_t possible_size;
326         int i;
327
328         SMB_ASSERT(orig_offset > 0);
329
330         if (!hbin)
331                 return hbin_store(data, blob);
332
333         /* Get original size */
334         orig_size = -IVALS(hbin->data, rel_offset);
335
336         needed_size = blob.length + 4; /* Add int32 containing length */
337         needed_size = (needed_size + 7) & ~7; /* Align */
338
339         /* Fits into current allocated block */
340         if (orig_size >= needed_size) {
341                 memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
342                 /* If the difference in size is greater than 0x4, split the block
343                  * and free/merge it */
344                 if (orig_size - needed_size > 0x4) {
345                         SIVALS(hbin->data, rel_offset, -needed_size);
346                         SIVALS(hbin->data, rel_offset + needed_size, needed_size-orig_size);
347                         hbin_free(data, orig_offset + needed_size);
348                 }
349                 return orig_offset;
350         }
351
352         possible_size = orig_size;
353
354         /* Check if it can be combined with the next few free records */
355         for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
356                 if (IVALS(hbin->data, i) < 0) /* Used */
357                         break;
358
359                 my_size = IVALS(hbin->data, i);
360                 
361                 if (my_size == 0x0) {
362                         DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
363                         break;
364                 } else {
365                         possible_size += my_size;
366                 }
367
368                 if (possible_size >= blob.length) {
369                         SIVAL(hbin->data, rel_offset, -possible_size);
370                         memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
371                         return orig_offset;
372                 }
373         }
374
375         hbin_free(data, orig_offset);
376         return hbin_store(data, blob);
377 }
378
379 static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t push_fn, 
380                                                                            uint32_t orig_offset, void *p)
381 {
382         struct tdr_push *push = talloc_zero(regf, struct tdr_push);
383         uint32_t ret;
384         
385         if (NT_STATUS_IS_ERR(push_fn(push, p))) {
386                 DEBUG(0, ("Error during push\n"));
387                 return -1;
388         }
389
390         ret = hbin_store_resize(regf, orig_offset, push->data);
391
392         talloc_free(push);
393
394         return ret;
395 }
396
397 static uint32_t regf_create_lh_hash(const char *name) 
398 {
399         char *hash_name;
400         uint32_t ret = 0;
401         uint16_t i;
402
403         hash_name = strupper_talloc(NULL, name);                
404         for (i = 0; *(hash_name + i) != 0; i++) {
405                 ret *= 37;
406                 ret += *(hash_name + i);
407         }
408         talloc_free(hash_name);
409         return ret;
410 }
411
412 static WERROR regf_get_info (TALLOC_CTX *mem_ctx,
413                                                          const struct hive_key *key, 
414                                                          const char **classname,
415                                                          uint32_t *num_subkeys,
416                                                          uint32_t *num_values,
417                                                          NTTIME *last_mod_time)
418 {
419         const struct regf_key_data *private_data = 
420                 (const struct regf_key_data *)key;
421
422         if (num_subkeys != NULL)
423                 *num_subkeys = private_data->nk->num_subkeys;
424
425         if (num_values != NULL)
426                 *num_values = private_data->nk->num_values;
427
428         if (classname != NULL) {
429                 if (private_data->nk->clsname_offset != -1) {
430                         DATA_BLOB data = hbin_get(private_data->hive, 
431                                                                           private_data->nk->clsname_offset);
432                         *classname = talloc_strndup(mem_ctx, 
433                                                          (char*)data.data, private_data->nk->clsname_length);
434                 } else 
435                         *classname = NULL;
436         }
437
438         /* TODO: Last mod time */
439         
440         return WERR_OK;
441 }
442
443 static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, 
444                                                                                   struct regf_data *regf, 
445                                                                                   uint32_t offset)
446 {
447         struct nk_block *nk;
448         struct regf_key_data *ret;
449
450         ret = talloc_zero(ctx, struct regf_key_data);
451         ret->key.ops = &reg_backend_regf;
452         ret->hive = talloc_reference(ret, regf);
453         ret->offset = offset;
454         nk = talloc(ret, struct nk_block);
455         if (nk == NULL)
456                 return NULL;
457
458         ret->nk = nk;
459
460         if (!hbin_get_tdr(regf, offset, nk, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
461                 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
462                 return NULL;
463         }
464
465         if (strcmp(nk->header, "nk") != 0) {
466                 DEBUG(0, ("Expected nk record, got %s\n", nk->header));
467                 talloc_free(ret);
468                 return NULL;
469         }
470
471         return ret;
472 }
473
474
475 static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, 
476                                                           int idx, const char **name, 
477                                                           uint32_t *data_type, DATA_BLOB *data)
478 {
479         const struct regf_key_data *private_data = 
480                         (const struct regf_key_data *)key;
481         struct vk_block *vk;
482         struct regf_data *regf = private_data->hive;
483         uint32_t vk_offset;
484         DATA_BLOB tmp;
485
486         if (idx >= private_data->nk->num_values)
487                 return WERR_NO_MORE_ITEMS;
488
489         tmp = hbin_get(regf, private_data->nk->values_offset);
490         if (!tmp.data) {
491                 DEBUG(0, ("Unable to find value list\n"));
492                 return WERR_GENERAL_FAILURE;
493         }
494
495         if (tmp.length < private_data->nk->num_values * 4) {
496                 DEBUG(1, ("Value counts mismatch\n"));
497         }
498
499         vk_offset = IVAL(tmp.data, idx * 4);
500
501         vk = talloc(NULL, struct vk_block);
502         W_ERROR_HAVE_NO_MEMORY(vk);
503         
504         if (!hbin_get_tdr(regf, vk_offset, vk, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
505                 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
506                 talloc_free(vk);
507                 return WERR_GENERAL_FAILURE;
508         }
509
510         /* FIXME: name character set ?*/
511         if (name != NULL)
512                 *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
513
514         if (data_type != NULL)
515                 *data_type = vk->data_type;
516
517         if (vk->data_length & 0x80000000) { 
518                 vk->data_length &=~0x80000000;
519                 data->data = (uint8_t *)&vk->data_offset;
520                 data->length = vk->data_length;
521         } else {
522                 *data = hbin_get(regf, vk->data_offset);
523         }
524
525         if (data->length < vk->data_length) {
526                 DEBUG(1, ("Read data less than indicated data length!\n"));
527         }
528
529         talloc_free(vk);
530         
531         return WERR_OK;
532 }
533
534 static WERROR regf_get_value_by_name (TALLOC_CTX *mem_ctx, 
535                                                                  struct hive_key *key, const char *name, 
536                                                                  uint32_t *type, DATA_BLOB *data)
537 {
538         int i;
539         const char *vname;
540         WERROR error;
541
542         /* FIXME: Do binary search? Is this list sorted at all? */
543
544         for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i, 
545                                                                                          &vname, type, data)); i++) {
546                 if (!strcmp(vname, name))
547                         return WERR_OK;
548     }
549
550         if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
551                 return WERR_NOT_FOUND;
552
553         return error;
554 }
555         
556
557 static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, 
558                                                                                 const struct hive_key *key, 
559                                                                                 uint32_t idx, const char **name,
560                                                                                 const char **classname,
561                                                                                 NTTIME *last_mod_time)
562 {
563         DATA_BLOB data;
564         struct regf_key_data *ret;
565         const struct regf_key_data *private_data = (const struct regf_key_data *)key;
566         struct nk_block *nk = private_data->nk;
567         uint32_t key_off=0;
568
569         if (idx >= nk->num_subkeys)
570                 return WERR_NO_MORE_ITEMS;
571
572         data = hbin_get(private_data->hive, nk->subkeys_offset);
573         if (!data.data) {
574                 DEBUG(0, ("Unable to find subkey list\n"));
575                 return WERR_GENERAL_FAILURE;
576         }
577
578         if (!strncmp((char *)data.data, "li", 2)) {
579                 struct li_block li;
580                 struct tdr_pull pull;
581
582                 DEBUG(10, ("Subkeys in LI list\n"));
583                 ZERO_STRUCT(pull);
584                 pull.data = data;
585
586                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
587                         DEBUG(0, ("Error parsing LI list\n"));
588                         return WERR_GENERAL_FAILURE;
589                 }
590                 SMB_ASSERT(!strncmp(li.header, "li", 2));
591
592                 if (li.key_count != nk->num_subkeys) {
593                         DEBUG(0, ("Subkey counts don't match\n"));
594                         return WERR_GENERAL_FAILURE;
595                 }
596                 key_off = li.nk_offset[idx];
597         
598         } else if (!strncmp((char *)data.data, "lf", 2)) {
599                 struct lf_block lf;
600                 struct tdr_pull pull;
601
602                 DEBUG(10, ("Subkeys in LF list\n"));
603                 ZERO_STRUCT(pull);
604                 pull.data = data;
605
606                 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
607                         DEBUG(0, ("Error parsing LF list\n"));
608                         return WERR_GENERAL_FAILURE;
609                 }
610                 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
611
612                 if (lf.key_count != nk->num_subkeys) {
613                         DEBUG(0, ("Subkey counts don't match\n"));
614                         return WERR_GENERAL_FAILURE;
615                 }
616
617                 key_off = lf.hr[idx].nk_offset;
618         } else if (!strncmp((char *)data.data, "lh", 2)) {
619                 struct lh_block lh;
620                 struct tdr_pull pull;
621                 
622                 DEBUG(10, ("Subkeys in LH list\n"));
623                 ZERO_STRUCT(pull);
624                 pull.data = data;
625                 
626                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
627                         DEBUG(0, ("Error parsing LH list\n"));
628                         return WERR_GENERAL_FAILURE;
629                 }
630                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
631                 
632                 if (lh.key_count != nk->num_subkeys) {
633                         DEBUG(0, ("Subkey counts don't match\n"));
634                         return WERR_GENERAL_FAILURE;
635                 }
636                 key_off = lh.hr[idx].nk_offset;
637         } else if (!strncmp((char *)data.data, "ri", 2)) {
638                 struct ri_block ri;
639                 struct tdr_pull pull;
640                 uint16_t i;
641                 uint16_t sublist_count = 0;
642                 
643                 DEBUG(10, ("Subkeys in RI list\n"));
644                 ZERO_STRUCT(pull);
645                 pull.data = data;
646                 
647                 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) {
648                         DEBUG(0, ("Error parsing RI list\n"));
649                         return WERR_GENERAL_FAILURE;
650                 }
651                 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
652                 
653                 for (i = 0; i < ri.key_count; i++) {
654                         DATA_BLOB list_data;
655                         
656                         /* Get sublist data blob */
657                         list_data = hbin_get(private_data->hive, ri.offset[i]);
658                         if (!list_data.data) {
659                                 DEBUG(0, ("Error getting RI list."));
660                                 return WERR_GENERAL_FAILURE;
661                         }
662                         
663                         ZERO_STRUCT(pull);
664                         pull.data = list_data;
665                         
666                         if (!strncmp((char *)list_data.data, "li", 2)) {
667                                 struct li_block li;
668
669                                 DEBUG(10, ("Subkeys in RI->LI list\n"));
670
671                                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
672                                         DEBUG(0, ("Error parsing LI list from RI\n"));
673                                         return WERR_GENERAL_FAILURE;
674                                 }
675                                 SMB_ASSERT(!strncmp(li.header, "li", 2));
676                                 
677                                 /* Advance to next sublist if necessary */
678                                 if (idx >= sublist_count + li.key_count) {
679                                         sublist_count += li.key_count;
680                                         continue;
681                                 }
682                                 key_off = li.nk_offset[idx - sublist_count];
683                                 sublist_count += li.key_count;
684                                 break;
685                         } else if (!strncmp((char *)list_data.data, "lh", 2)) {
686                                 struct lh_block lh;
687                                 
688                                 DEBUG(10, ("Subkeys in RI->LH list\n"));
689
690                                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
691                                         DEBUG(0, ("Error parsing LH list from RI\n"));
692                                         return WERR_GENERAL_FAILURE;
693                                 }
694                                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
695
696                                 /* Advance to next sublist if necessary */
697                                 if (idx >= sublist_count + lh.key_count) {
698                                         sublist_count += lh.key_count;
699                                         continue;
700                                 }
701                                 key_off = lh.hr[idx - sublist_count].nk_offset;
702                                 sublist_count += lh.key_count;
703                                 break;
704                         } else {
705                                 DEBUG(0,("Unknown sublist in ri block\n"));
706
707                                 return WERR_GENERAL_FAILURE;
708                         }
709                         
710                 }
711         
712                 if (idx > sublist_count) {
713                         return WERR_NO_MORE_ITEMS;
714                 }
715
716         } else {
717                 DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", 
718                                   nk->subkeys_offset, data.data[0], data.data[1]));
719                 return WERR_GENERAL_FAILURE;
720         }
721
722         ret = regf_get_key (ctx, private_data->hive, key_off);
723
724         if (classname != NULL) {
725                 if (ret->nk->clsname_offset != -1) {
726                         DATA_BLOB db = hbin_get(ret->hive, 
727                                                                           ret->nk->clsname_offset);
728                         *classname = talloc_strndup(ctx, 
729                                                          (char*)db.data, ret->nk->clsname_length);
730                 } else 
731                         *classname = NULL;
732         }
733
734         if (last_mod_time != NULL)
735                 *last_mod_time = ret->nk->last_change;
736
737         if (name != NULL)
738                 *name = talloc_steal(ctx, ret->nk->key_name);
739
740         talloc_free(ret);
741
742         return WERR_OK;
743 }
744
745 static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, 
746                                                 const struct hive_key *key, uint32_t offset, 
747                                                 const char *name, uint32_t *ret) 
748 {
749         DATA_BLOB subkey_data;
750         struct nk_block subkey;
751         struct tdr_pull pull;
752         const struct regf_key_data *private_data = 
753                 (const struct regf_key_data *)key;
754         
755         subkey_data = hbin_get(private_data->hive, offset);
756         if (!subkey_data.data) {
757                 DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
758                 return WERR_GENERAL_FAILURE;
759         }
760
761         ZERO_STRUCT(pull);
762         pull.data = subkey_data;
763         
764         if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) {
765                 DEBUG(0, ("Error parsing NK structure.\n"));
766                 return WERR_GENERAL_FAILURE;
767         }
768
769         if (strncmp(subkey.header, "nk", 2)) {
770                 DEBUG(0, ("Not an NK structure.\n"));
771                 return WERR_GENERAL_FAILURE;
772         }
773
774         if (!strcasecmp(subkey.key_name, name)) {
775                 *ret = offset;
776         } else {
777                 *ret = 0;
778         }
779         return WERR_OK;
780 }
781         
782 static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, 
783                                                                           const struct hive_key *key, 
784                                                                           const char *name, 
785                                                                           struct hive_key **ret)
786 {
787         DATA_BLOB data;
788         const struct regf_key_data *private_data = 
789                 (const struct regf_key_data *)key;
790         struct nk_block *nk = private_data->nk;
791         uint32_t key_off = 0;
792
793         data = hbin_get(private_data->hive, nk->subkeys_offset);
794         if (!data.data) {
795                 DEBUG(0, ("Unable to find subkey list\n"));
796                 return WERR_GENERAL_FAILURE;
797         }
798
799         if (!strncmp((char *)data.data, "li", 2)) {
800                 struct li_block li;
801                 struct tdr_pull pull;
802                 uint16_t i;
803
804                 DEBUG(10, ("Subkeys in LI list\n"));
805                 ZERO_STRUCT(pull);
806                 pull.data = data;
807                 
808                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
809                         DEBUG(0, ("Error parsing LI list\n"));
810                         return WERR_GENERAL_FAILURE;
811                 }
812                 SMB_ASSERT(!strncmp(li.header, "li", 2));
813
814                 if (li.key_count != nk->num_subkeys) {
815                         DEBUG(0, ("Subkey counts don't match\n"));
816                         return WERR_GENERAL_FAILURE;
817                 }
818                 
819                 for (i = 0; i < li.key_count; i++) {
820                         W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[i], name, &key_off));
821                         if (key_off != 0)
822                                 break;
823                 }
824                 if (key_off == 0)
825                         return WERR_NOT_FOUND;
826         } else if (!strncmp((char *)data.data, "lf", 2)) {
827                 struct lf_block lf;
828                 struct tdr_pull pull;
829                 uint16_t i;
830
831                 DEBUG(10, ("Subkeys in LF list\n"));
832                 ZERO_STRUCT(pull);
833                 pull.data = data;
834                 
835                 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
836                         DEBUG(0, ("Error parsing LF list\n"));
837                         return WERR_GENERAL_FAILURE;
838                 }
839                 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
840
841                 if (lf.key_count != nk->num_subkeys) {
842                         DEBUG(0, ("Subkey counts don't match\n"));
843                         return WERR_GENERAL_FAILURE;
844                 }
845                 
846                 for (i = 0; i < lf.key_count; i++) {
847                         if (strncmp(lf.hr[i].hash, name, 4)) {
848                                 continue;
849                         }
850                         W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lf.hr[i].nk_offset, name, &key_off));
851                         if (key_off != 0)
852                                 break;
853                 }
854                 if (key_off == 0)
855                         return WERR_NOT_FOUND;
856         } else if (!strncmp((char *)data.data, "lh", 2)) {
857                 struct lh_block lh;
858                 struct tdr_pull pull;
859                 uint16_t i;
860                 uint32_t hash;
861
862                 DEBUG(10, ("Subkeys in LH list\n"));
863                 ZERO_STRUCT(pull);
864                 pull.data = data;
865                 
866                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
867                         DEBUG(0, ("Error parsing LH list\n"));
868                         return WERR_GENERAL_FAILURE;
869                 }
870                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
871
872                 if (lh.key_count != nk->num_subkeys) {
873                         DEBUG(0, ("Subkey counts don't match\n"));
874                         return WERR_GENERAL_FAILURE;
875                 }
876                 
877                 hash = regf_create_lh_hash(name);
878                 for (i = 0; i < lh.key_count; i++) {
879                         if (lh.hr[i].base37 != hash) {
880                                 continue;
881                         }
882                         W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[i].nk_offset, name, &key_off));
883                         if (key_off != 0)
884                                 break;
885                 }       
886                 if (key_off == 0)
887                         return WERR_NOT_FOUND;
888         } else if (!strncmp((char *)data.data, "ri", 2)) {
889                 struct ri_block ri;
890                 struct tdr_pull pull;
891                 uint16_t i, j;
892
893                 DEBUG(10, ("Subkeys in RI list\n"));
894                 ZERO_STRUCT(pull);
895                 pull.data = data;
896                 
897                 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) {
898                         DEBUG(0, ("Error parsing RI list\n"));
899                         return WERR_GENERAL_FAILURE;
900                 }
901                 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
902                         
903                 for (i = 0; i < ri.key_count; i++) {
904                         DATA_BLOB list_data;
905                         
906                         /* Get sublist data blob */
907                         list_data = hbin_get(private_data->hive, ri.offset[i]);
908                         if (list_data.data == NULL) {
909                                 DEBUG(0, ("Error getting RI list."));
910                                 return WERR_GENERAL_FAILURE;
911                         }
912                                 
913                         ZERO_STRUCT(pull);
914                         pull.data = list_data;
915                         
916                         if (!strncmp((char *)list_data.data, "li", 2)) {
917                                 struct li_block li;
918         
919                                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
920                                         DEBUG(0, ("Error parsing LI list from RI\n"));
921                                         return WERR_GENERAL_FAILURE;
922                                 }
923                                 SMB_ASSERT(!strncmp(li.header, "li", 2));
924                                 
925                                 for (j = 0; j < li.key_count; j++) {
926                                         W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, 
927                                                                 li.nk_offset[j], name, &key_off));
928                                         if (key_off)
929                                                 break;
930                                 }
931                         } else if (!strncmp((char *)list_data.data, "lh", 2)) {
932                                 struct lh_block lh;
933                                 uint32_t hash;
934                                 
935                                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
936                                         DEBUG(0, ("Error parsing LH list from RI\n"));
937                                         return WERR_GENERAL_FAILURE;
938                                 }
939                                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
940
941                                 hash = regf_create_lh_hash(name);
942                                 for (j = 0; j < lh.key_count; j++) {
943                                         if (lh.hr[j].base37 != hash) {
944                                                 continue;
945                                         }
946                                         W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, 
947                                                                 lh.hr[j].nk_offset, name, &key_off));
948                                         if (key_off)
949                                                 break;
950                                 }
951                         }
952                         if (key_off)
953                                 break;
954                 }
955                 if (!key_off)
956                         return WERR_NOT_FOUND;
957         } else {
958                 DEBUG(0, ("Unknown subkey list type.\n"));
959                 return WERR_GENERAL_FAILURE;
960         }
961
962         *ret = (struct hive_key *)regf_get_key (ctx, private_data->hive, key_off);
963         return WERR_OK;
964 }
965
966 static WERROR regf_set_sec_desc (struct hive_key *key, 
967                                                                  const struct security_descriptor *sec_desc)
968 {
969         const struct regf_key_data *private_data = 
970                 (const struct regf_key_data *)key;
971         struct sk_block cur_sk, sk, new_sk;
972         struct regf_data *regf = private_data->hive;
973         struct nk_block root;
974         DATA_BLOB data;
975         uint32_t sk_offset, cur_sk_offset;
976         bool update_cur_sk = false;
977
978         /* Get the root nk */
979         hbin_get_tdr(regf, regf->header->data_offset, regf, 
980                                  (tdr_pull_fn_t) tdr_pull_nk_block, &root);
981
982         /* Push the security descriptor to a blob */
983         if (NT_STATUS_IS_ERR(ndr_push_struct_blob(&data, regf, sec_desc, 
984                                         (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
985                 DEBUG(0, ("Unable to push security descriptor\n"));
986                 return WERR_GENERAL_FAILURE;
987         }
988
989         /* Get the current security descriptor for the key */   
990         if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf, 
991                                           (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
992                 DEBUG(0, ("Unable to find security descriptor for current key\n"));
993                 return WERR_BADFILE;
994         }
995         /* If there's no change, change nothing. */
996         if (memcmp(data.data, cur_sk.sec_desc, MIN(data.length, cur_sk.rec_size)) == 0) {
997                 return WERR_OK;
998         }
999
1000         /* Delete the current sk if only this key is using it */        
1001         if (cur_sk.ref_cnt == 1) {
1002                 /* Get the previous security descriptor for the key */  
1003                 if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf, 
1004                                                   (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1005                         DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1006                         return WERR_BADFILE;
1007                 }
1008                 /* Change and store the previous security descriptor */
1009                 sk.next_offset = cur_sk.next_offset;
1010                 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk);
1011                 
1012                 /* Get the next security descriptor for the key */      
1013                 if (!hbin_get_tdr(regf, cur_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1014                         DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1015                         return WERR_BADFILE;
1016                 }
1017                 /* Change and store the next security descriptor */
1018                 sk.prev_offset = cur_sk.prev_offset;
1019                 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.next_offset, &sk);
1020
1021                 hbin_free(regf, private_data->nk->sk_offset);
1022         } else {
1023                 /* This key will no longer be referring to this sk */
1024                 cur_sk.ref_cnt--;
1025                 update_cur_sk = true;
1026         }
1027
1028         sk_offset = root.sk_offset;
1029
1030         do {
1031                 cur_sk_offset = sk_offset;
1032                 if (!hbin_get_tdr(regf, sk_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1033                         DEBUG(0, ("Unable to find security descriptor\n"));
1034                         return WERR_BADFILE;
1035                 }
1036                 if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1037                         private_data->nk->sk_offset = sk_offset;
1038                         sk.ref_cnt++;
1039                         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, sk_offset, &sk);
1040                         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, private_data->nk);
1041                         return WERR_OK;
1042                 }
1043                 sk_offset = sk.next_offset;
1044         } while (sk_offset != root.sk_offset);
1045         
1046         ZERO_STRUCT(new_sk);
1047         new_sk.header = "sk";
1048         new_sk.prev_offset = cur_sk_offset;
1049         new_sk.next_offset = root.sk_offset;
1050         new_sk.ref_cnt = 1;
1051         new_sk.rec_size = data.length;
1052         new_sk.sec_desc = data.data;
1053         
1054         sk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_sk_block, &new_sk);
1055         if (sk_offset == -1) {
1056                 DEBUG(0, ("Error storing sk block\n"));
1057                 return WERR_GENERAL_FAILURE;
1058         }
1059         private_data->nk->sk_offset = sk_offset;
1060
1061         if (update_cur_sk) {
1062                 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->nk->sk_offset, &cur_sk);
1063         }
1064
1065         /* Get the previous security descriptor for the key */  
1066         if (!hbin_get_tdr(regf, new_sk.prev_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1067                 DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1068                 return WERR_BADFILE;
1069         }
1070         /* Change and store the previous security descriptor */
1071         sk.next_offset = sk_offset;
1072         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk);
1073         
1074         /* Get the next security descriptor for the key (always root, as we append) */  
1075         if (!hbin_get_tdr(regf, new_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1076                 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1077                 return WERR_BADFILE;
1078         }
1079         /* Change and store the next security descriptor (always root, as we append) */
1080         sk.prev_offset = sk_offset;
1081         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, root.sk_offset, &sk);
1082
1083
1084         /* Store the nk. */
1085         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->offset, private_data->nk);
1086         return WERR_OK;
1087 }
1088
1089 static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, 
1090                                                                 struct security_descriptor **sd)
1091 {
1092         const struct regf_key_data *private_data = 
1093                 (const struct regf_key_data *)key;
1094         struct sk_block sk;
1095         struct regf_data *regf = private_data->hive;
1096         DATA_BLOB data;
1097
1098         if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1099                 DEBUG(0, ("Unable to find security descriptor\n"));
1100                 return WERR_GENERAL_FAILURE;
1101         }
1102                 
1103         if (strcmp(sk.header, "sk") != 0) {
1104                 DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1105                 return WERR_GENERAL_FAILURE;
1106         }
1107
1108         *sd = talloc(ctx, struct security_descriptor);
1109         W_ERROR_HAVE_NO_MEMORY(*sd);
1110
1111         data.data = sk.sec_desc;
1112         data.length = sk.rec_size;
1113         if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1114                 DEBUG(0, ("Error parsing security descriptor\n"));
1115                 return WERR_GENERAL_FAILURE;
1116         }
1117
1118         return WERR_OK;
1119 }
1120
1121 static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, 
1122                                         const char *name, uint32_t key_offset, uint32_t *ret)
1123 {
1124         DATA_BLOB data;
1125
1126         /* Create a new key if necessary */
1127         if (list_offset == -1) { 
1128                 if (regf->header->version.major != 1) {
1129                         DEBUG(0, ("Can't store keys in unknown registry format\n"));
1130                         return WERR_NOT_SUPPORTED;
1131                 }
1132                 if (regf->header->version.minor < 3) { 
1133                         /* Store LI */
1134                         struct li_block li;
1135                         ZERO_STRUCT(li);
1136                         li.header = "li";
1137                         li.key_count = 1; 
1138
1139                         li.nk_offset = talloc_array(regf, uint32_t, 1);
1140                         W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1141                         li.nk_offset[0] = key_offset;
1142
1143                         *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_li_block, &li);
1144
1145                         talloc_free(li.nk_offset);
1146                 } else if (regf->header->version.minor == 3 || regf->header->version.minor == 4) {
1147                         /* Store LF */
1148                         struct lf_block lf;
1149                         ZERO_STRUCT(lf);
1150                         lf.header = "lf";
1151                         lf.key_count = 1;
1152                         
1153                         lf.hr = talloc_array(regf, struct hash_record, 1);
1154                         W_ERROR_HAVE_NO_MEMORY(lf.hr);
1155                         lf.hr[0].nk_offset = key_offset;
1156                         lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1157                         W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1158
1159                         *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lf_block, &lf);
1160
1161                         talloc_free(lf.hr);
1162                 } else if (regf->header->version.minor == 5) {
1163                         /* Store LH */
1164                         struct lh_block lh;
1165                         ZERO_STRUCT(lh);
1166                         lh.header = "lh";
1167                         lh.key_count = 1;
1168                         
1169                         lh.hr = talloc_array(regf, struct lh_hash, 1);
1170                         W_ERROR_HAVE_NO_MEMORY(lh.hr);
1171                         lh.hr[0].nk_offset = key_offset;
1172                         lh.hr[0].base37 = regf_create_lh_hash(name);
1173
1174                         *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lh_block, &lh);
1175
1176                         talloc_free(lh.hr);
1177                 }
1178                 return WERR_OK;
1179         } 
1180         
1181         data = hbin_get(regf, list_offset);
1182         if (!data.data) {
1183                 DEBUG(0, ("Unable to find subkey list\n"));
1184                 return WERR_BADFILE;
1185         }
1186
1187         if (!strncmp((char *)data.data, "li", 2)) {
1188                 struct tdr_pull pull;
1189                 struct li_block li;
1190         
1191                 ZERO_STRUCT(pull);
1192                 pull.data = data;
1193
1194                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) {
1195                         DEBUG(0, ("Error parsing LI list\n"));
1196                         return WERR_BADFILE;
1197                 }
1198
1199                 if (strncmp(li.header, "li", 2) != 0) {
1200                         abort();
1201                         DEBUG(0, ("LI header corrupt\n"));
1202                         return WERR_BADFILE;
1203                 }
1204                 
1205                 li.nk_offset = talloc_realloc(regf, li.nk_offset, uint32_t, li.key_count+1);
1206                 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1207                 li.nk_offset[li.key_count] = key_offset;
1208                 li.key_count++;
1209                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_li_block, list_offset, &li);
1210                 
1211                 talloc_free(li.nk_offset);
1212         } else if (!strncmp((char *)data.data, "lf", 2)) {
1213                 struct tdr_pull pull;
1214                 struct lf_block lf;
1215
1216                 ZERO_STRUCT(pull);
1217                 pull.data = data;
1218
1219                 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) {
1220                         DEBUG(0, ("Error parsing LF list\n"));
1221                         return WERR_BADFILE;
1222                 }
1223                 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1224                 
1225                 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1);
1226                 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1227                 lf.hr[lf.key_count].nk_offset = key_offset;
1228                 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
1229                 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1230                 lf.key_count++;
1231                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf);
1232
1233                 talloc_free(lf.hr);
1234         } else if (!strncmp((char *)data.data, "lh", 2)) {
1235                 struct tdr_pull pull;
1236                 struct lh_block lh;
1237
1238                 ZERO_STRUCT(pull);
1239                 pull.data = data;
1240
1241                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) {
1242                         DEBUG(0, ("Error parsing LH list\n"));
1243                         return WERR_BADFILE;
1244                 }
1245                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1246                 
1247                 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, lh.key_count+1);
1248                 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1249                 lh.hr[lh.key_count].nk_offset = key_offset;
1250                 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
1251                 lh.key_count++;
1252                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lh_block, list_offset, &lh);
1253
1254                 talloc_free(lh.hr);
1255         } else if (!strncmp((char *)data.data, "ri", 2)) {
1256                 /* FIXME */
1257                 DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1258                 return WERR_NOT_SUPPORTED;
1259         } else {
1260                 DEBUG(0, ("Cannot add to unknown subkey list\n"));
1261                 return WERR_BADFILE;
1262         }
1263         
1264         return WERR_OK;
1265 }
1266
1267 static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, 
1268                                                                 uint32_t key_offset, uint32_t *ret) 
1269 {
1270         DATA_BLOB data;
1271
1272         data = hbin_get(regf, list_offset);
1273         if (!data.data) {
1274                 DEBUG(0, ("Unable to find subkey list\n"));
1275                 return WERR_BADFILE;
1276         }
1277
1278         if (strncmp((char *)data.data, "li", 2) == 0) {
1279                 struct li_block li;
1280                 struct tdr_pull pull;
1281                 uint16_t i;
1282                 bool found_offset = false;
1283         
1284                 DEBUG(10, ("Subkeys in LI list\n"));
1285                 
1286                 ZERO_STRUCT(pull);
1287                 pull.data = data;       
1288                 
1289                 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) {
1290                         DEBUG(0, ("Error parsing LI list\n"));
1291                         return WERR_BADFILE;
1292                 }
1293                 
1294                 SMB_ASSERT(!strncmp(li.header, "li", 2));
1295
1296                 for (i = 0; i < li.key_count; i++) {
1297                         if (found_offset) {
1298                                 li.nk_offset[i-1] = li.nk_offset[i];
1299                         }
1300                         if (li.nk_offset[i] == key_offset) {
1301                                 found_offset = true;
1302                                 continue;
1303                         }
1304                 }
1305                 if (!found_offset) {
1306                         DEBUG(2, ("Subkey not found\n"));
1307                         return WERR_NOT_FOUND;
1308                 }
1309                 li.key_count--;
1310
1311                 /* If the there are no entries left, free the subkey list */
1312                 if (li.key_count == 0) {
1313                         hbin_free(regf, list_offset);
1314                         *ret = -1;
1315                 }
1316
1317                 /* Store li block */
1318                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_li_block, list_offset, &li);
1319         } else if (strncmp((char *)data.data, "lf", 2) == 0) {
1320                 struct lf_block lf;
1321                 struct tdr_pull pull;
1322                 uint16_t i;
1323                 bool found_offset = false;
1324                 
1325                 DEBUG(10, ("Subkeys in LF list\n"));
1326                 
1327                 ZERO_STRUCT(pull);
1328                 pull.data = data;       
1329                 
1330                 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) {
1331                         DEBUG(0, ("Error parsing LF list\n"));
1332                         return WERR_BADFILE;
1333                 }
1334                 
1335                 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1336
1337                 for (i = 0; i < lf.key_count; i++) {
1338                         if (found_offset) {
1339                                 lf.hr[i-1] = lf.hr[i];
1340                                 continue;
1341                         }
1342                         if (lf.hr[i].nk_offset == key_offset) {
1343                                 found_offset = 1;
1344                                 continue;
1345                         }
1346                 }
1347                 if (!found_offset) {
1348                         DEBUG(2, ("Subkey not found\n"));
1349                         return WERR_NOT_FOUND;
1350                 }
1351                 lf.key_count--;
1352                 
1353                 /* If the there are no entries left, free the subkey list */
1354                 if (lf.key_count == 0) {
1355                         hbin_free(regf, list_offset);
1356                         *ret = -1;
1357                         return WERR_OK;
1358                 }
1359
1360                 /* Store lf block */
1361                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lf_block, list_offset, &lf);
1362         } else if (strncmp((char *)data.data, "lh", 2) == 0) {
1363                 struct lh_block lh;
1364                 struct tdr_pull pull;
1365                 uint16_t i;
1366                 bool found_offset = false;
1367                 
1368                 DEBUG(10, ("Subkeys in LH list\n"));
1369                 
1370                 ZERO_STRUCT(pull);
1371                 pull.data = data;       
1372                 
1373                 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) {
1374                         DEBUG(0, ("Error parsing LF list\n"));
1375                         return WERR_BADFILE;
1376                 }
1377                 
1378                 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1379
1380                 for (i = 0; i < lh.key_count; i++) {
1381                         if (found_offset) {
1382                                 lh.hr[i-1] = lh.hr[i];
1383                                 continue;
1384                         }
1385                         if (lh.hr[i].nk_offset == key_offset) {
1386                                 found_offset = 1;
1387                                 continue;
1388                         }
1389                 }
1390                 if (!found_offset) {
1391                         DEBUG(0, ("Subkey not found\n"));
1392                         return WERR_NOT_FOUND;
1393                 }
1394                 lh.key_count--;
1395                 
1396                 /* If the there are no entries left, free the subkey list */
1397                 if (lh.key_count == 0) {
1398                         hbin_free(regf, list_offset);
1399                         *ret = -1;
1400                         return WERR_OK;
1401                 }
1402
1403                 /* Store lh block */
1404                 *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lh_block, list_offset, &lh);
1405         } else if (strncmp((char *)data.data, "ri", 2) == 0) {
1406                 /* FIXME */
1407                 DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1408                 return WERR_NOT_SUPPORTED;
1409         } else {
1410                 DEBUG (0, ("Unknown header found in subkey list.\n"));
1411                 return WERR_BADFILE;
1412         }
1413         return WERR_OK;
1414 }
1415
1416 static WERROR regf_del_value (struct hive_key *key, const char *name)
1417 {
1418         const struct regf_key_data *private_data = 
1419                 (const struct regf_key_data *)key;
1420         struct regf_data *regf = private_data->hive;
1421         struct nk_block *nk = private_data->nk;
1422         struct vk_block vk;
1423         uint32_t vk_offset;
1424         bool found_offset = false;
1425         DATA_BLOB values;
1426         uint32_t i;
1427
1428         if (nk->values_offset == -1) {
1429                 return WERR_NOT_FOUND;
1430         }
1431
1432         values = hbin_get(regf, nk->values_offset);
1433
1434         for (i = 0; i < nk->num_values; i++) {
1435                 if (found_offset) {
1436                         ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1437                 } else {
1438                         vk_offset = IVAL(values.data, i * 4);
1439                         if (!hbin_get_tdr(regf, vk_offset, private_data, 
1440                                                           (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) {
1441                                 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
1442                                 return WERR_BADFILE;
1443                         } 
1444                         if (strcmp(vk.data_name, name) == 0) {
1445                                 hbin_free(regf, vk_offset);
1446                                 found_offset = true;
1447                         }
1448                 }
1449         }
1450         if (!found_offset) {
1451                 return WERR_NOT_FOUND;
1452         } else {
1453                 nk->num_values--;
1454                 values.length = (nk->num_values)*4;
1455         }
1456
1457         /* Store values list and nk */
1458         if (nk->num_values == 0) {
1459                 hbin_free(regf, nk->values_offset);
1460                 nk->values_offset = -1;
1461         } else {        
1462                 nk->values_offset = hbin_store_resize(regf, nk->values_offset, values);
1463         }
1464         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk);
1465
1466         return regf_save_hbin(private_data->hive);
1467 }
1468
1469
1470 static WERROR regf_del_key(const struct hive_key *parent, const char *name)
1471 {
1472         const struct regf_key_data *private_data = 
1473                 (const struct regf_key_data *)parent;
1474         struct regf_key_data *key;
1475         struct nk_block *parent_nk;
1476         WERROR error;
1477
1478         SMB_ASSERT(private_data);
1479         
1480         parent_nk = private_data->nk;
1481
1482         if (parent_nk->subkeys_offset == -1) {
1483                 DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1484                 return WERR_NOT_FOUND;
1485         }
1486
1487         /* Find the key */
1488         if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, 
1489                                                                            (struct hive_key **)&key))) {
1490                 DEBUG(2, ("Key '%s' not found\n", name));
1491                 return WERR_NOT_FOUND;
1492         }
1493         
1494         if (key->nk->subkeys_offset != -1 || 
1495                 key->nk->values_offset != -1) {
1496                 DEBUG(0, ("Key '%s' is not empty.\n", name));
1497                 return WERR_FILE_EXISTS;
1498         }
1499         
1500         /* Delete it from the subkey list. */
1501         error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset, 
1502                                                           key->offset, &parent_nk->subkeys_offset);
1503         if (!W_ERROR_IS_OK(error)) {
1504                 DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1505                 return error;
1506         }
1507
1508         /* Re-store parent key */
1509         parent_nk->num_subkeys--;
1510         hbin_store_tdr_resize(private_data->hive, 
1511                                                   (tdr_push_fn_t) tdr_push_nk_block, 
1512                                                   private_data->offset, parent_nk);
1513
1514         if (key->nk->clsname_offset != -1) {
1515                 hbin_free(private_data->hive, key->nk->clsname_offset);
1516         }
1517         hbin_free(private_data->hive, key->offset);
1518
1519         return regf_save_hbin(private_data->hive);
1520 }
1521
1522 static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, 
1523                                                    const char *name, const char *classname,
1524                                                    struct security_descriptor *sec_desc, 
1525                                                    struct hive_key **ret)
1526 {
1527         const struct regf_key_data *private_data = 
1528                 (const struct regf_key_data *)parent;
1529         struct nk_block *parent_nk = private_data->nk, nk;
1530         struct nk_block *root;
1531         struct regf_data *regf = private_data->hive;
1532         uint32_t offset;
1533         WERROR error;
1534
1535         nk.header = "nk";
1536         nk.type = REG_SUB_KEY;
1537         unix_to_nt_time(&nk.last_change, time(NULL));
1538         nk.uk1 = 0;
1539         nk.parent_offset = private_data->offset;
1540         nk.num_subkeys = 0;
1541         nk.uk2 = 0;
1542         nk.subkeys_offset = -1;
1543         nk.unknown_offset = -1;
1544         nk.num_values = 0;
1545         nk.values_offset = -1;
1546         memset(nk.unk3, 0, 5);
1547         nk.clsname_offset = -1; /* FIXME: fill in */
1548         nk.clsname_length = 0;
1549         nk.key_name = name;
1550         
1551         /* Get the security descriptor of the root key */
1552         root = talloc_zero(ctx, struct nk_block);
1553         W_ERROR_HAVE_NO_MEMORY(root);
1554
1555         if (!hbin_get_tdr(regf, regf->header->data_offset, root, 
1556                                           (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1557                 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
1558                 return WERR_GENERAL_FAILURE;
1559         }
1560         nk.sk_offset = root->sk_offset;
1561         talloc_free(root);
1562         
1563         /* Store the new nk key */
1564         offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1565         
1566         error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset, &parent_nk->subkeys_offset);
1567         if (!W_ERROR_IS_OK(error)) {
1568                 hbin_free(regf, offset);
1569                 return error;
1570         }
1571         
1572         parent_nk->num_subkeys++;
1573
1574         /* Since the subkey offset of the parent can change, store it again */
1575         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, 
1576                                                   nk.parent_offset, parent_nk);
1577
1578         *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1579
1580         return regf_save_hbin(private_data->hive);
1581 }
1582
1583 static WERROR regf_set_value(struct hive_key *key, const char *name, 
1584                                                          uint32_t type, const DATA_BLOB data)
1585 {
1586         const struct regf_key_data *private_data = 
1587                 (const struct regf_key_data *)key;
1588         struct regf_data *regf = private_data->hive;
1589         struct nk_block *nk = private_data->nk;
1590         struct vk_block vk;
1591         uint32_t i;
1592         uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
1593         DATA_BLOB values;
1594
1595         ZERO_STRUCT(vk);
1596
1597         /* find the value offset, if it exists */
1598         if (nk->values_offset != -1) {
1599                 values = hbin_get(regf, nk->values_offset);
1600
1601                 for (i = 0; i < nk->num_values; i++) {
1602                         tmp_vk_offset = IVAL(values.data, i * 4);
1603                         if (!hbin_get_tdr(regf, tmp_vk_offset, private_data, 
1604                                                           (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) {
1605                                 DEBUG(0, ("Unable to get VK block at %d\n", tmp_vk_offset));
1606                                 return WERR_GENERAL_FAILURE;
1607                         }
1608                         if (strcmp(vk.data_name, name) == 0) {
1609                                 old_vk_offset = tmp_vk_offset;
1610                                 break;
1611                         }
1612                 }
1613                 /* Free data, if any */
1614                 if (!(vk.data_length & 0x80000000)) {
1615                         hbin_free(regf, vk.data_offset);        
1616                 }
1617         }
1618         if (old_vk_offset == -1) {
1619                 vk.header = "vk";
1620                 vk.name_length = strlen(name);
1621                 if (name != NULL && name[0] != 0) {
1622                         vk.flag = 1;
1623                         vk.data_name = name;
1624                 } else {
1625                         vk.data_name = NULL;
1626                         vk.flag = 0;
1627                 }
1628         }
1629         /* Set the type and data */
1630         vk.data_length = data.length;
1631         vk.data_type = type;
1632         if (type == REG_DWORD) {
1633                 vk.data_length |= 0x80000000;
1634                 vk.data_offset = *(uint32_t *)data.data;
1635         } else {
1636                 /* Store data somewhere */
1637                 vk.data_offset = hbin_store(regf, data);
1638         }
1639         if (old_vk_offset == -1) {
1640                 /* Store new vk */
1641                 vk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_vk_block, &vk);
1642         } else {
1643                 /* Store vk at offset */
1644                 vk_offset = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_vk_block, old_vk_offset ,&vk);
1645         }
1646
1647         /* Re-allocate the value list */
1648         if (nk->values_offset == -1) {
1649                 nk->values_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_uint32, &vk_offset);
1650                 nk->num_values = 1;
1651         } else {
1652
1653                 /* Change if we're changing, otherwise we're adding the value */
1654                 if (old_vk_offset != -1) {
1655                         /* Find and overwrite the offset. */
1656                         for (i = 0; i < nk->num_values; i++) {
1657                                 if (IVAL(values.data, i * 4) == old_vk_offset) {
1658                                         SIVAL(values.data, i * 4, vk_offset);
1659                                         break;
1660                                 }
1661                         }
1662                 } else {
1663                         /* Create a new value list */
1664                         DATA_BLOB value_list;
1665
1666                         value_list.length = (nk->num_values+1)*4;
1667                         value_list.data = talloc_array(private_data, uint32_t, nk->num_values+1);
1668                         W_ERROR_HAVE_NO_MEMORY(value_list.data);
1669                         memcpy(value_list.data, values.data, nk->num_values * 4);
1670
1671                         SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1672                         nk->num_values++;
1673                         nk->values_offset = hbin_store_resize(regf, nk->values_offset, value_list);
1674                 }
1675                 
1676         }
1677         hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk);
1678         return regf_save_hbin(private_data->hive);
1679 }
1680
1681 static WERROR regf_save_hbin(struct regf_data *regf)
1682 {
1683         struct tdr_push *push = talloc_zero(regf, struct tdr_push);
1684         int i;
1685
1686         W_ERROR_HAVE_NO_MEMORY(push);
1687
1688         if (lseek(regf->fd, 0, SEEK_SET) == -1) {
1689                 DEBUG(0, ("Error lseeking in regf file\n"));
1690                 return WERR_GENERAL_FAILURE;
1691         }
1692
1693         /* Recompute checksum */
1694         if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
1695                 DEBUG(0, ("Failed to push regf header\n"));
1696                 return WERR_GENERAL_FAILURE;
1697         }
1698         regf->header->chksum = regf_hdr_checksum(push->data.data);
1699         talloc_free(push);
1700
1701         if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, 
1702                                                 (tdr_push_fn_t)tdr_push_regf_hdr, regf->header))) {
1703                 DEBUG(0, ("Error writing registry file header\n"));
1704                 return WERR_GENERAL_FAILURE;
1705         }
1706
1707         if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
1708                 DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
1709                 return WERR_GENERAL_FAILURE;
1710         }       
1711
1712         for (i = 0; regf->hbins[i]; i++) {
1713                 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, 
1714                                                                                         (tdr_push_fn_t)tdr_push_hbin_block, 
1715                                                                                         regf->hbins[i]))) {
1716                         DEBUG(0, ("Error writing HBIN block\n"));       
1717                         return WERR_GENERAL_FAILURE;
1718                 }
1719         }
1720
1721         return WERR_OK;
1722 }
1723
1724 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, 
1725                                                          int minor_version, struct hive_key **key)
1726 {
1727         struct regf_data *regf;
1728         struct regf_hdr *regf_hdr;
1729         struct tdr_pull pull;
1730         int i;
1731         struct nk_block nk;
1732         WERROR error;
1733
1734         regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1735
1736         W_ERROR_HAVE_NO_MEMORY(regf);
1737
1738         DEBUG(5, ("Attempting to create registry file\n"));
1739
1740         /* Get the header */
1741         regf->fd = creat(location, 0644);
1742
1743         if (regf->fd == -1) {
1744                 DEBUG(0,("Could not create file: %s, %s\n", location,
1745                                  strerror(errno)));
1746                 talloc_free(regf);
1747                 return WERR_GENERAL_FAILURE;
1748         }
1749
1750         regf_hdr = talloc_zero(regf, struct regf_hdr);
1751         W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1752         regf_hdr->REGF_ID = "regf";
1753         unix_to_nt_time(&regf_hdr->modtime, time(NULL));
1754         regf_hdr->version.major = 1;
1755         regf_hdr->version.minor = minor_version;
1756         regf_hdr->last_block = 0x1000; /* Block size */
1757         regf_hdr->description = talloc_strdup(regf_hdr, "registry created by Samba 4");
1758         W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
1759         regf_hdr->chksum = 0;
1760
1761         regf->header = regf_hdr;
1762
1763         pull.offset = 0x1000;
1764
1765         i = 0;
1766         /* Create all hbin blocks */
1767         regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1768         W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1769         regf->hbins[0] = NULL;
1770
1771         regf_hdr->data_offset = -1; /* FIXME */
1772
1773         nk.header = "nk";
1774         nk.type = REG_SUB_KEY;
1775         unix_to_nt_time(&nk.last_change, time(NULL));
1776         nk.uk1 = 0;
1777         nk.parent_offset = -1;
1778         nk.num_subkeys = 0;
1779         nk.uk2 = 0;
1780         nk.subkeys_offset = -1;
1781         nk.unknown_offset = -1;
1782         nk.num_values = 0;
1783         nk.values_offset = -1;
1784         memset(nk.unk3, 0, 5);
1785         nk.clsname_offset = -1; /* FIXME: fill in */
1786         nk.clsname_length = 0;
1787         nk.key_name = "";
1788         
1789         nk.sk_offset = -1; /* FIXME: fill in */
1790         
1791         /* Store the new nk key */
1792         regf->header->data_offset = hbin_store_tdr(regf, 
1793                                                                         (tdr_push_fn_t)tdr_push_nk_block, &nk);
1794         
1795         *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset);
1796
1797         /* We can drop our own reference now that *key will have created one */
1798         talloc_free(regf);
1799
1800         error = regf_save_hbin(regf);
1801         if (!W_ERROR_IS_OK(error)) {
1802                 return error;
1803         }
1804
1805         return WERR_OK;
1806 }
1807
1808 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, 
1809                                                   const char *location, struct hive_key **key)
1810 {
1811         struct regf_data *regf;
1812         struct regf_hdr *regf_hdr;
1813         struct tdr_pull pull;
1814         int i;
1815
1816         regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1817
1818         W_ERROR_HAVE_NO_MEMORY(regf);
1819
1820         DEBUG(5, ("Attempting to load registry file\n"));
1821
1822         /* Get the header */
1823         regf->fd = open(location, O_RDWR);
1824
1825         if (regf->fd == -1) {
1826                 DEBUG(0,("Could not load file: %s, %s\n", location,
1827                                  strerror(errno)));
1828                 talloc_free(regf);
1829                 return WERR_GENERAL_FAILURE;
1830         }
1831
1832         ZERO_STRUCT(pull);
1833         pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf);
1834
1835         if (pull.data.data == NULL) {
1836                 DEBUG(0, ("Error reading data\n"));
1837                 talloc_free(regf);
1838                 return WERR_GENERAL_FAILURE;
1839         }
1840
1841         regf_hdr = talloc(regf, struct regf_hdr);
1842         W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1843
1844         if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) {
1845                 talloc_free(regf);
1846                 return WERR_GENERAL_FAILURE;
1847         }
1848
1849         regf->header = regf_hdr;
1850
1851         if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
1852                 DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
1853                                   regf_hdr->REGF_ID, location));
1854                 talloc_free(regf);
1855                 return WERR_GENERAL_FAILURE;
1856         }
1857
1858         /* Validate the header ... */
1859         if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) {
1860                 DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
1861                                   location, regf_hdr->chksum, 
1862                                   regf_hdr_checksum(pull.data.data)));
1863                 talloc_free(regf);
1864                 return WERR_GENERAL_FAILURE;
1865         }
1866
1867         pull.offset = 0x1000;
1868
1869         i = 0;
1870         /* Read in all hbin blocks */
1871         regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1872         W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1873
1874         regf->hbins[0] = NULL;
1875
1876         while (pull.offset < pull.data.length && pull.offset <= regf->header->last_block) {
1877                 struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block);
1878
1879                 W_ERROR_HAVE_NO_MEMORY(hbin);
1880
1881                 if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) {
1882                         DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
1883                         talloc_free(regf);
1884                         return WERR_FOOBAR;
1885                 }
1886
1887                 if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
1888                         DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", i, hbin->HBIN_ID));
1889                         talloc_free(regf);
1890                         return WERR_FOOBAR;
1891                 }
1892
1893                 regf->hbins[i] = hbin;
1894                 i++;
1895                 regf->hbins = talloc_realloc(regf, regf->hbins, struct hbin_block *, i+2);
1896                 regf->hbins[i] = NULL;
1897         } 
1898
1899         DEBUG(1, ("%d HBIN blocks read\n", i));
1900
1901         *key = (struct hive_key *)regf_get_key(parent_ctx, regf, 
1902                                                                                                 regf->header->data_offset);
1903
1904         /* We can drop our own reference now that *key will have created one */
1905         talloc_free(regf);
1906
1907         return WERR_OK;
1908 }
1909
1910 static struct hive_operations reg_backend_regf = {
1911         .name = "regf",
1912         .get_key_info = regf_get_info,
1913         .enum_key = regf_get_subkey_by_index,
1914         .get_key_by_name = regf_get_subkey_by_name,
1915         .get_value_by_name = regf_get_value_by_name,
1916         .enum_value = regf_get_value,
1917         .get_sec_desc = regf_get_sec_desc,
1918         .set_sec_desc = regf_set_sec_desc,
1919         .add_key = regf_add_key,
1920         .set_value = regf_set_value,
1921         .del_key = regf_del_key,
1922         .delete_value = regf_del_value,
1923 };