2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/regfile.c
5 * PURPOSE: Registry file manipulation routines
12 #include <ddk/ntddk.h>
13 #include <ddk/ntifs.h>
15 #include <internal/ob.h>
18 #include <internal/pool.h>
19 #include <internal/registry.h>
22 #include <internal/debug.h>
27 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
29 BOOLEAN CmiDoVerify
= FALSE
;
31 /* FUNCTIONS ****************************************************************/
34 CmiCreateDefaultHiveHeader(PHIVE_HEADER Header
)
37 RtlZeroMemory(Header
, sizeof(HIVE_HEADER
));
38 Header
->BlockId
= REG_HIVE_ID
;
39 Header
->DateModified
.dwLowDateTime
= 0;
40 Header
->DateModified
.dwHighDateTime
= 0;
47 Header
->RootKeyCell
= 0;
48 Header
->BlockSize
= REG_BLOCK_SIZE
;
55 CmiCreateDefaultBinCell(PHBIN BinCell
)
58 RtlZeroMemory(BinCell
, sizeof(HBIN
));
59 BinCell
->BlockId
= REG_BIN_ID
;
60 BinCell
->DateModified
.dwLowDateTime
= 0;
61 BinCell
->DateModified
.dwHighDateTime
= 0;
62 BinCell
->BlockSize
= REG_BLOCK_SIZE
;
67 CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell
)
70 RtlZeroMemory(RootKeyCell
, sizeof(KEY_CELL
));
72 RootKeyCell
->CellSize
= -(LONG
)sizeof(KEY_CELL
);
74 RootKeyCell
->CellSize
= -sizeof(KEY_CELL
);
76 RootKeyCell
->Id
= REG_KEY_CELL_ID
;
77 RootKeyCell
->Type
= REG_ROOT_KEY_CELL_TYPE
;
78 ZwQuerySystemTime((PTIME
) &RootKeyCell
->LastWriteTime
);
79 RootKeyCell
->ParentKeyOffset
= 0;
80 RootKeyCell
->NumberOfSubKeys
= 0;
81 RootKeyCell
->HashTableOffset
= -1;
82 RootKeyCell
->NumberOfValues
= 0;
83 RootKeyCell
->ValuesOffset
= -1;
84 RootKeyCell
->SecurityKeyOffset
= 0;
85 RootKeyCell
->ClassNameOffset
= -1;
86 RootKeyCell
->NameSize
= 0;
87 RootKeyCell
->ClassSize
= 0;
92 CmiVerifyBinCell(PHBIN BinCell
)
99 if (BinCell
->BlockId
!= REG_BIN_ID
)
101 DbgPrint("BlockId is %.08x (should be %.08x)\n",
102 BinCell
->BlockId
, REG_BIN_ID
);
103 assert(BinCell
->BlockId
== REG_BIN_ID
);
106 //BinCell->DateModified.dwLowDateTime
108 //BinCell->DateModified.dwHighDateTime
111 if (BinCell
->BlockSize
!= REG_BLOCK_SIZE
)
113 DbgPrint("BlockSize is %.08x (should be %.08x)\n",
114 BinCell
->BlockSize
, REG_BLOCK_SIZE
);
115 assert(BinCell
->BlockSize
== REG_BLOCK_SIZE
);
123 CmiVerifyKeyCell(PKEY_CELL KeyCell
)
130 if (KeyCell
->CellSize
== 0)
132 DbgPrint("CellSize is %d (must not be 0)\n",
134 assert(KeyCell
->CellSize
!= 0);
137 if (KeyCell
->Id
!= REG_KEY_CELL_ID
)
139 DbgPrint("Id is %.08x (should be %.08x)\n",
140 KeyCell
->Id
, REG_KEY_CELL_ID
);
141 assert(KeyCell
->Id
== REG_KEY_CELL_ID
);
144 if ((KeyCell
->Type
!= REG_KEY_CELL_TYPE
)
145 && (KeyCell
->Type
!= REG_ROOT_KEY_CELL_TYPE
))
147 DbgPrint("Type is %.08x (should be %.08x or %.08x)\n",
148 KeyCell
->Type
, REG_KEY_CELL_TYPE
, REG_ROOT_KEY_CELL_TYPE
);
152 //KeyCell->LastWriteTime;
154 if (KeyCell
->ParentKeyOffset
< 0)
156 DbgPrint("ParentKeyOffset is %d (must not be < 0)\n",
157 KeyCell
->ParentKeyOffset
);
158 assert(KeyCell
->ParentKeyOffset
>= 0);
161 if (KeyCell
->NumberOfSubKeys
< 0)
163 DbgPrint("NumberOfSubKeys is %d (must not be < 0)\n",
164 KeyCell
->NumberOfSubKeys
);
165 assert(KeyCell
->NumberOfSubKeys
>= 0);
168 //KeyCell->HashTableOffset;
170 if (KeyCell
->NumberOfValues
< 0)
172 DbgPrint("NumberOfValues is %d (must not be < 0)\n",
173 KeyCell
->NumberOfValues
);
174 assert(KeyCell
->NumberOfValues
>= 0);
177 //KeyCell->ValuesOffset = -1;
179 if (KeyCell
->SecurityKeyOffset
< 0)
181 DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n",
182 KeyCell
->SecurityKeyOffset
);
183 assert(KeyCell
->SecurityKeyOffset
>= 0);
186 //KeyCell->ClassNameOffset = -1;
197 CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell
)
202 CmiVerifyKeyCell(RootKeyCell
);
204 if (RootKeyCell
->Type
!= REG_ROOT_KEY_CELL_TYPE
)
206 DbgPrint("Type is %.08x (should be %.08x)\n",
207 RootKeyCell
->Type
, REG_ROOT_KEY_CELL_TYPE
);
208 assert(RootKeyCell
->Type
== REG_ROOT_KEY_CELL_TYPE
);
216 CmiVerifyValueCell(PVALUE_CELL ValueCell
)
223 if (ValueCell
->CellSize
== 0)
225 DbgPrint("CellSize is %d (must not be 0)\n",
226 ValueCell
->CellSize
);
227 assert(ValueCell
->CellSize
!= 0);
230 if (ValueCell
->Id
!= REG_VALUE_CELL_ID
)
232 DbgPrint("Id is %.08x (should be %.08x)\n",
233 ValueCell
->Id
, REG_VALUE_CELL_ID
);
234 assert(ValueCell
->Id
== REG_VALUE_CELL_ID
);
237 //ValueCell->NameSize;
238 //ValueCell->LONG DataSize;
239 //ValueCell->DataOffset;
240 //ValueCell->ULONG DataType;
241 //ValueCell->USHORT Flags;
242 //ValueCell->USHORT Unused1;
243 //ValueCell->UCHAR Name[0];
249 CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell
)
254 if (ValueListCell
->CellSize
== 0)
256 DbgPrint("CellSize is %d (must not be 0)\n",
257 ValueListCell
->CellSize
);
258 assert(ValueListCell
->CellSize
!= 0);
266 CmiVerifyKeyObject(PKEY_OBJECT KeyObject
)
271 if (KeyObject
->RegistryHive
== NULL
)
273 DbgPrint("RegistryHive is NULL (must not be NULL)\n",
274 KeyObject
->RegistryHive
);
275 assert(KeyObject
->RegistryHive
!= NULL
);
278 if (KeyObject
->KeyCell
== NULL
)
280 DbgPrint("KeyCell is NULL (must not be NULL)\n",
282 assert(KeyObject
->KeyCell
!= NULL
);
285 if (KeyObject
->ParentKey
== NULL
)
287 DbgPrint("ParentKey is NULL (must not be NULL)\n",
288 KeyObject
->ParentKey
);
289 assert(KeyObject
->ParentKey
!= NULL
);
297 CmiVerifyHiveHeader(PHIVE_HEADER Header
)
302 if (Header
->BlockId
!= REG_HIVE_ID
)
304 DbgPrint("BlockId is %.08x (must be %.08x)\n",
307 assert(Header
->BlockId
== REG_HIVE_ID
);
310 if (Header
->Unused3
!= 1)
312 DbgPrint("Unused3 is %.08x (must be 1)\n",
314 assert(Header
->Unused3
== 1);
317 if (Header
->Unused4
!= 3)
319 DbgPrint("Unused4 is %.08x (must be 3)\n",
321 assert(Header
->Unused4
== 3);
324 if (Header
->Unused5
!= 0)
326 DbgPrint("Unused5 is %.08x (must be 0)\n",
328 assert(Header
->Unused5
== 0);
331 if (Header
->Unused6
!= 1)
333 DbgPrint("Unused6 is %.08x (must be 1)\n",
335 assert(Header
->Unused6
== 1);
338 if (Header
->Unused7
!= 1)
340 DbgPrint("Unused7 is %.08x (must be 1)\n",
342 assert(Header
->Unused7
== 1);
350 CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive
)
355 CmiVerifyHiveHeader(RegistryHive
->HiveHeader
);
362 CmiPopulateHive(HANDLE FileHandle
)
364 IO_STATUS_BLOCK IoStatusBlock
;
365 LARGE_INTEGER FileOffset
;
366 PCELL_HEADER FreeCell
;
372 tBuf
= (PCHAR
) ExAllocatePool(NonPagedPool
, REG_BLOCK_SIZE
);
374 return STATUS_INSUFFICIENT_RESOURCES
;
376 BinCell
= (PHBIN
) tBuf
;
377 FreeCell
= (PCELL_HEADER
) (tBuf
+ REG_HBIN_DATA_OFFSET
);
379 CmiCreateDefaultBinCell(BinCell
);
381 // The whole block is free
382 FreeCell
->CellSize
= REG_BLOCK_SIZE
- REG_HBIN_DATA_OFFSET
;
384 // Add free blocks so we don't need to expand
385 // the file for a while
386 for (i
= 0; i
< 50; i
++)
388 // Block offset of this bin
389 BinCell
->BlockOffset
= (2 + i
) * REG_BLOCK_SIZE
;
391 FileOffset
.u
.HighPart
= 0;
392 FileOffset
.u
.LowPart
= (2 + i
) * REG_BLOCK_SIZE
;
394 Status
= ZwWriteFile(FileHandle
,
403 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
404 if (!NT_SUCCESS(Status
))
418 CmiCreateNewRegFile(HANDLE FileHandle
)
420 IO_STATUS_BLOCK IoStatusBlock
;
421 PCELL_HEADER FreeCell
;
422 PHIVE_HEADER HiveHeader
;
423 PKEY_CELL RootKeyCell
;
428 Buffer
= (PCHAR
) ExAllocatePool(NonPagedPool
, 2 * REG_BLOCK_SIZE
);
430 return STATUS_INSUFFICIENT_RESOURCES
;
432 HiveHeader
= (PHIVE_HEADER
)Buffer
;
433 BinCell
= (PHBIN
)((ULONG_PTR
)Buffer
+ REG_BLOCK_SIZE
);
434 RootKeyCell
= (PKEY_CELL
)((ULONG_PTR
)Buffer
+ REG_BLOCK_SIZE
+ REG_HBIN_DATA_OFFSET
);
435 FreeCell
= (PCELL_HEADER
)((ULONG_PTR
)Buffer
+ REG_BLOCK_SIZE
+ REG_HBIN_DATA_OFFSET
+ sizeof(KEY_CELL
));
437 CmiCreateDefaultHiveHeader(HiveHeader
);
438 CmiCreateDefaultBinCell(BinCell
);
439 CmiCreateDefaultRootKeyCell(RootKeyCell
);
442 BinCell
->BlockOffset
= 0;
444 /* Offset to root key block */
445 HiveHeader
->RootKeyCell
= REG_HBIN_DATA_OFFSET
;
447 /* The rest of the block is free */
448 FreeCell
->CellSize
= REG_BLOCK_SIZE
- (REG_HBIN_DATA_OFFSET
+ sizeof(KEY_CELL
));
450 Status
= ZwWriteFile(FileHandle
,
462 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
465 if (NT_SUCCESS(Status
))
467 CmiPopulateHive(FileHandle
);
476 CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive
,
480 OBJECT_ATTRIBUTES ObjectAttributes
;
481 FILE_STANDARD_INFORMATION fsi
;
482 PCELL_HEADER FreeBlock
;
483 LARGE_INTEGER FileOffset
;
484 BLOCK_OFFSET BlockOffset
;
485 ULONG CreateDisposition
;
486 IO_STATUS_BLOCK IoSB
;
495 DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive
, Filename
, CreateNew
);
497 /* Duplicate Filename */
498 Status
= RtlCreateUnicodeString(&RegistryHive
->Filename
, Filename
);
499 if (!NT_SUCCESS(Status
))
501 DPRINT1("CmiInitPermanentRegistryHive() - Failed 1.\n");
505 InitializeObjectAttributes(&ObjectAttributes
,
506 &RegistryHive
->Filename
,
513 * This is a workaround to prevent a BSOD because of missing registry hives.
514 * The workaround is only useful for developers. An implementation for the
515 * ordinary user must bail out on missing registry hives because they are
516 * essential to booting and configuring the OS.
519 if (CreateNew
== TRUE
)
520 CreateDisposition
= FILE_OPEN_IF
;
522 CreateDisposition
= FILE_OPEN
;
524 CreateDisposition
= FILE_OPEN_IF
;
526 Status
= NtCreateFile(&FileHandle
,
531 FILE_ATTRIBUTE_NORMAL
,
534 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
537 if (!NT_SUCCESS(Status
))
539 RtlFreeUnicodeString(&RegistryHive
->Filename
);
540 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
544 /* Note: Another workaround! See the note above! */
546 if ((CreateNew
) && (IoSB
.Information
== FILE_CREATED
))
548 if (IoSB
.Information
!= FILE_OPENED
)
550 Status
= CmiCreateNewRegFile(FileHandle
);
551 if (!NT_SUCCESS(Status
))
553 DPRINT1("CmiCreateNewRegFile() failed (Status %lx)\n", Status
);
554 RtlFreeUnicodeString(&RegistryHive
->Filename
);
559 Status
= ObReferenceObjectByHandle(FileHandle
,
563 (PVOID
*)&RegistryHive
->FileObject
,
566 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
568 if (!NT_SUCCESS(Status
))
571 RtlFreeUnicodeString(&RegistryHive
->Filename
);
572 DPRINT1("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status
);
576 /* Read hive header */
577 FileOffset
.u
.HighPart
= 0;
578 FileOffset
.u
.LowPart
= 0;
579 DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle
, sizeof(HIVE_HEADER
), RegistryHive
->HiveHeader
);
580 Status
= NtReadFile(FileHandle
,
585 RegistryHive
->HiveHeader
,
589 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
590 if (!NT_SUCCESS(Status
))
592 ObDereferenceObject(RegistryHive
->FileObject
);
593 RtlFreeUnicodeString(&RegistryHive
->Filename
);
594 DPRINT("CmiInitPermanentRegistryHive() - Failed 4.\n");
598 Status
= NtQueryInformationFile(FileHandle
,
602 FileStandardInformation
);
604 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
606 if (!NT_SUCCESS(Status
))
608 ObDereferenceObject(RegistryHive
->FileObject
);
609 RtlFreeUnicodeString(&RegistryHive
->Filename
);
610 DPRINT("CmiInitPermanentRegistryHive() - Failed 5.\n");
615 /* We have a reference to the file object so we don't need the handle anymore */
619 RegistryHive
->FileSize
= fsi
.EndOfFile
.u
.LowPart
;
621 // assert(RegistryHive->FileSize);
622 if (RegistryHive
->FileSize
)
624 RegistryHive
->BlockListSize
= (RegistryHive
->FileSize
/ 4096) - 1;
628 ObDereferenceObject(RegistryHive
->FileObject
);
629 RtlFreeUnicodeString(&RegistryHive
->Filename
);
630 DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
631 return STATUS_INSUFFICIENT_RESOURCES
;
634 RegistryHive
->BlockListSize
= (RegistryHive
->FileSize
/ 4096) - 1;
637 DPRINT("Space needed for block list describing hive: 0x%x\n",
638 sizeof(PHBIN
*) * RegistryHive
->BlockListSize
);
640 RegistryHive
->BlockList
= ExAllocatePool(NonPagedPool
,
641 sizeof(PHBIN
*) * RegistryHive
->BlockListSize
);
643 if (RegistryHive
->BlockList
== NULL
)
645 ExFreePool(RegistryHive
->BlockList
);
646 ObDereferenceObject(RegistryHive
->FileObject
);
647 RtlFreeUnicodeString(&RegistryHive
->Filename
);
648 DPRINT("CmiInitPermanentRegistryHive() - Failed 6.\n");
649 return STATUS_INSUFFICIENT_RESOURCES
;
653 /* Map hive into cache memory (readonly) (skip the base block) */
654 FileOffset
.u
.HighPart
= 0;
655 FileOffset
.u
.LowPart
= 4096;
656 Success
= CcMapData(RegistryHive
->FileObject
, /* File object */
657 &FileOffset
, /* File offset */
658 RegistryHive
->FileSize
- 4096, /* Region length */
659 TRUE
, /* Wait if needed */
660 &RegistryHive
->Bcb
, /* OUT: Buffer Control Block */
661 (PVOID
*) &RegistryHive
->BlockList
[0]); /* OUT: Mapped data pointer */
663 assertmsg(Success
, ("Success: %d\n", Success
));
667 ExFreePool(RegistryHive
->BlockList
);
668 ObDereferenceObject(RegistryHive
->FileObject
);
669 RtlFreeUnicodeString(&RegistryHive
->Filename
);
670 DPRINT("CmiInitPermanentRegistryHive() - Failed 7.\n");
676 RegistryHive
->BlockList
[0] = ExAllocatePool(PagedPool
,
677 RegistryHive
->FileSize
- 4096);
679 RtlZeroMemory(RegistryHive
->BlockList
[0], RegistryHive
->FileSize
- 4096);
682 if (RegistryHive
->BlockList
[0] == NULL
)
684 ExFreePool(RegistryHive
->BlockList
);
685 ObDereferenceObject(RegistryHive
->FileObject
);
686 RtlFreeUnicodeString(&RegistryHive
->Filename
);
687 DPRINT("CmiInitPermanentRegistryHive() - Failed 8.\n");
688 return STATUS_INSUFFICIENT_RESOURCES
;
691 FileOffset
.u
.HighPart
= 0;
692 FileOffset
.u
.LowPart
= 4096;
694 DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle
, RegistryHive
->FileSize
- 4096, (PVOID
)RegistryHive
->BlockList
[0]);
695 Status
= NtReadFile(FileHandle
,
700 (PVOID
) RegistryHive
->BlockList
[0],
701 RegistryHive
->FileSize
- 4096,
705 assertmsg(NT_SUCCESS(Status
), ("Status: 0x%X\n", Status
));
710 RegistryHive
->FreeListSize
= 0;
711 RegistryHive
->FreeListMax
= 0;
712 RegistryHive
->FreeList
= NULL
;
715 for (i
= 0; i
< RegistryHive
->BlockListSize
; i
++)
717 RegistryHive
->BlockList
[i
] = (PHBIN
) (((ULONG_PTR
) RegistryHive
->BlockList
[0]) + BlockOffset
);
718 tmpBin
= (PHBIN
) (((ULONG_PTR
) RegistryHive
->BlockList
[i
]));
719 if (tmpBin
->BlockId
!= REG_BIN_ID
)
721 DPRINT("Bad BlockId %x, offset %x\n", tmpBin
->BlockId
, BlockOffset
);
723 return STATUS_INSUFFICIENT_RESOURCES
;
726 assertmsg((tmpBin
->BlockSize
% 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin
->BlockSize
));
728 if (tmpBin
->BlockSize
> 4096)
730 for (j
= 1; j
< tmpBin
->BlockSize
/ 4096; j
++)
732 RegistryHive
->BlockList
[i
+ j
] = RegistryHive
->BlockList
[i
];
737 /* Search free blocks and add to list */
738 FreeOffset
= REG_HBIN_DATA_OFFSET
;
739 while (FreeOffset
< tmpBin
->BlockSize
)
741 FreeBlock
= (PCELL_HEADER
) ((ULONG_PTR
) RegistryHive
->BlockList
[i
] + FreeOffset
);
742 if (FreeBlock
->CellSize
> 0)
744 Status
= CmiAddFree(RegistryHive
,
746 RegistryHive
->BlockList
[i
]->BlockOffset
+ FreeOffset
,
749 if (!NT_SUCCESS(Status
))
755 FreeOffset
+= FreeBlock
->CellSize
;
759 FreeOffset
-= FreeBlock
->CellSize
;
762 BlockOffset
+= tmpBin
->BlockSize
;
765 /* Create block bitmap and clear all bits */
767 /* Calculate bitmap size in bytes (always a multiple of 32 bits) */
768 BitmapSize
= ROUND_UP(RegistryHive
->BlockListSize
, sizeof(ULONG
) * 8) / 8;
769 DPRINT1("RegistryHive->BlockListSize: %lu\n", RegistryHive
->BlockListSize
);
770 DPRINT1("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize
, BitmapSize
* 8);
771 BitmapBuffer
= (PULONG
)ExAllocatePool(PagedPool
,
773 RtlInitializeBitMap(&RegistryHive
->DirtyBitMap
,
776 RtlClearAllBits(&RegistryHive
->DirtyBitMap
);
777 RegistryHive
->HiveDirty
= FALSE
;
779 DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive
, Filename
, CreateNew
);
781 return(STATUS_SUCCESS
);
786 CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive
)
788 PKEY_CELL RootKeyCell
;
790 RegistryHive
->Flags
|= HIVE_VOLATILE
;
792 CmiCreateDefaultHiveHeader(RegistryHive
->HiveHeader
);
794 RootKeyCell
= (PKEY_CELL
) ExAllocatePool(NonPagedPool
, sizeof(KEY_CELL
));
796 if (RootKeyCell
== NULL
)
797 return STATUS_INSUFFICIENT_RESOURCES
;
799 CmiCreateDefaultRootKeyCell(RootKeyCell
);
801 RegistryHive
->HiveHeader
->RootKeyCell
= (BLOCK_OFFSET
) RootKeyCell
;
803 return STATUS_SUCCESS
;
808 CmiCreateRegistryHive(PWSTR Filename
,
809 PREGISTRY_HIVE
*RegistryHive
,
815 DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename
);
817 *RegistryHive
= NULL
;
819 Hive
= ExAllocatePool(NonPagedPool
, sizeof(REGISTRY_HIVE
));
821 return(STATUS_INSUFFICIENT_RESOURCES
);
823 DPRINT("Hive %x\n", Hive
);
825 RtlZeroMemory(Hive
, sizeof(REGISTRY_HIVE
));
827 Hive
->HiveHeader
= (PHIVE_HEADER
)
828 ExAllocatePool(NonPagedPool
, sizeof(HIVE_HEADER
));
830 if (Hive
->HiveHeader
== NULL
)
833 return(STATUS_INSUFFICIENT_RESOURCES
);
836 if (Filename
!= NULL
)
838 Status
= CmiInitPermanentRegistryHive(Hive
, Filename
, CreateNew
);
842 Status
= CmiInitVolatileRegistryHive(Hive
);
845 if (!NT_SUCCESS(Status
))
847 ExFreePool(Hive
->HiveHeader
);
852 ExInitializeResourceLite(&Hive
->HiveResource
);
854 /* Acquire hive list lock exclusively */
855 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
857 /* Add the new hive to the hive list */
858 InsertHeadList(&CmiHiveListHead
, &Hive
->HiveList
);
860 /* Release hive list lock */
861 ExReleaseResourceLite(&CmiHiveListLock
);
863 VERIFY_REGISTRY_HIVE(Hive
);
865 *RegistryHive
= Hive
;
867 DPRINT("CmiCreateRegistryHive(Filename %S) - Finished.\n", Filename
);
869 return(STATUS_SUCCESS
);
874 CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive
)
876 /* Acquire hive list lock exclusively */
877 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
879 /* Remove hive from hive list */
880 RemoveEntryList(&RegistryHive
->HiveList
);
882 /* Release hive list lock */
883 ExReleaseResourceLite(&CmiHiveListLock
);
886 /* FIXME: Remove attached keys and values */
889 /* Release hive header */
890 ExFreePool(RegistryHive
->HiveHeader
);
893 ExFreePool(RegistryHive
);
895 return(STATUS_SUCCESS
);
900 CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive
)
905 LARGE_INTEGER FileOffset
;
906 OBJECT_ATTRIBUTES ObjectAttributes
;
907 IO_STATUS_BLOCK IoStatusBlock
;
914 DPRINT("CmiFlushRegistryHive() called\n");
916 if (RegistryHive
->HiveDirty
== FALSE
)
918 return(STATUS_SUCCESS
);
921 DPRINT1("Hive '%wZ' is dirty\n", &RegistryHive
->Filename
);
924 /* Open hive for writing */
925 InitializeObjectAttributes(&ObjectAttributes
,
926 &RegistryHive
->Filename
,
931 Status
= NtCreateFile(&FileHandle
,
936 FILE_ATTRIBUTE_NORMAL
,
939 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
942 if (!NT_SUCCESS(Status
))
944 DPRINT1("NtCreateFile() failed (Status %lx)\n", Status
);
953 BlockIndex
= RtlFindSetBitsAndClear(&RegistryHive
->DirtyBitMap
,
956 if (BlockIndex
== (ULONG
)-1)
958 DPRINT("No more set bits\n");
962 DPRINT1("Block %lu is dirty\n", BlockIndex
);
964 BlockOffset
= RegistryHive
->BlockList
[BlockIndex
]->BlockOffset
;
965 DPRINT1("Block offset %lx\n", BlockOffset
);
967 BlockPtr
= RegistryHive
->BlockList
[BlockIndex
] + ((BlockIndex
* 4096) - BlockOffset
);
968 DPRINT1("BlockPtr %p\n", BlockPtr
);
970 FileOffset
.QuadPart
= (ULONGLONG
)(BlockIndex
+ 1) * 4096ULL;
971 DPRINT1("File offset %I64x\n", FileOffset
.QuadPart
);
974 /* Write hive block */
975 Status
= NtWriteFile(FileHandle
,
984 if (!NT_SUCCESS(Status
))
986 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status
);
997 /* Clear dirty flag */
998 RegistryHive
->HiveDirty
= FALSE
;
1000 DPRINT("CmiFlushRegistryHive() done\n");
1002 return(STATUS_SUCCESS
);
1007 CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive
,
1010 PHASH_TABLE_CELL HashBlock
;
1011 PKEY_CELL CurSubKeyCell
;
1015 VERIFY_KEY_CELL(KeyCell
);
1018 HashBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
1019 if (HashBlock
== NULL
)
1024 for (i
= 0; i
< HashBlock
->HashTableSize
; i
++)
1026 if (HashBlock
->Table
[i
].KeyOffset
!= 0)
1028 CurSubKeyCell
= CmiGetBlock(RegistryHive
,
1029 HashBlock
->Table
[i
].KeyOffset
,
1031 if (MaxName
< CurSubKeyCell
->NameSize
)
1033 MaxName
= CurSubKeyCell
->NameSize
;
1035 CmiReleaseBlock(RegistryHive
, CurSubKeyCell
);
1039 CmiReleaseBlock(RegistryHive
, HashBlock
);
1046 CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive
,
1049 PHASH_TABLE_CELL HashBlock
;
1050 PKEY_CELL CurSubKeyCell
;
1054 VERIFY_KEY_CELL(KeyCell
);
1057 HashBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
1058 if (HashBlock
== NULL
)
1063 for (i
= 0; i
< HashBlock
->HashTableSize
; i
++)
1065 if (HashBlock
->Table
[i
].KeyOffset
!= 0)
1067 CurSubKeyCell
= CmiGetBlock(RegistryHive
,
1068 HashBlock
->Table
[i
].KeyOffset
,
1070 if (MaxClass
< CurSubKeyCell
->ClassSize
)
1072 MaxClass
= CurSubKeyCell
->ClassSize
;
1074 CmiReleaseBlock(RegistryHive
, CurSubKeyCell
);
1078 CmiReleaseBlock(RegistryHive
, HashBlock
);
1085 CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive
,
1088 PVALUE_LIST_CELL ValueListCell
;
1089 PVALUE_CELL CurValueCell
;
1093 VERIFY_KEY_CELL(KeyCell
);
1095 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1097 if (ValueListCell
== NULL
)
1102 for (i
= 0; i
< KeyCell
->NumberOfValues
; i
++)
1104 CurValueCell
= CmiGetBlock(RegistryHive
,
1105 ValueListCell
->Values
[i
],
1107 if (CurValueCell
!= NULL
&&
1108 MaxValueName
< CurValueCell
->NameSize
)
1110 MaxValueName
= CurValueCell
->NameSize
;
1112 CmiReleaseBlock(RegistryHive
, CurValueCell
);
1115 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1117 return MaxValueName
;
1122 CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive
,
1125 PVALUE_LIST_CELL ValueListCell
;
1126 PVALUE_CELL CurValueCell
;
1130 VERIFY_KEY_CELL(KeyCell
);
1132 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1134 if (ValueListCell
== NULL
)
1139 for (i
= 0; i
< KeyCell
->NumberOfValues
; i
++)
1141 CurValueCell
= CmiGetBlock(RegistryHive
,
1142 ValueListCell
->Values
[i
],NULL
);
1143 if ((CurValueCell
!= NULL
) &&
1144 (MaxValueData
< (CurValueCell
->DataSize
& LONG_MAX
)))
1146 MaxValueData
= CurValueCell
->DataSize
& LONG_MAX
;
1148 CmiReleaseBlock(RegistryHive
, CurValueCell
);
1151 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1153 return MaxValueData
;
1158 CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive
,
1159 IN PKEY_CELL KeyCell
,
1160 OUT PKEY_CELL
*SubKeyCell
,
1161 OUT BLOCK_OFFSET
*BlockOffset
,
1163 IN ACCESS_MASK DesiredAccess
,
1164 IN ULONG Attributes
)
1166 PHASH_TABLE_CELL HashBlock
;
1167 PKEY_CELL CurSubKeyCell
;
1171 VERIFY_KEY_CELL(KeyCell
);
1173 //DPRINT("Scanning for sub key %s\n", KeyName);
1175 assert(RegistryHive
);
1177 KeyLength
= strlen(KeyName
);
1179 HashBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
1181 if (HashBlock
== NULL
)
1183 return STATUS_SUCCESS
;
1186 for (i
= 0; (i
< KeyCell
->NumberOfSubKeys
)
1187 && (i
< HashBlock
->HashTableSize
); i
++)
1189 if (Attributes
& OBJ_CASE_INSENSITIVE
)
1191 if ((HashBlock
->Table
[i
].KeyOffset
!= 0) &&
1192 (HashBlock
->Table
[i
].KeyOffset
!= (ULONG_PTR
)-1) &&
1193 (_strnicmp(KeyName
, (PCHAR
) &HashBlock
->Table
[i
].HashValue
, 4) == 0))
1195 CurSubKeyCell
= CmiGetBlock(RegistryHive
,
1196 HashBlock
->Table
[i
].KeyOffset
,
1198 if ((CurSubKeyCell
->NameSize
== KeyLength
)
1199 && (_strnicmp(KeyName
, CurSubKeyCell
->Name
, KeyLength
) == 0))
1201 *SubKeyCell
= CurSubKeyCell
;
1202 *BlockOffset
= HashBlock
->Table
[i
].KeyOffset
;
1207 CmiReleaseBlock(RegistryHive
, CurSubKeyCell
);
1213 if (HashBlock
->Table
[i
].KeyOffset
!= 0 &&
1214 HashBlock
->Table
[i
].KeyOffset
!= (ULONG_PTR
) -1 &&
1215 !strncmp(KeyName
, (PCHAR
) &HashBlock
->Table
[i
].HashValue
, 4))
1217 CurSubKeyCell
= CmiGetBlock(RegistryHive
,
1218 HashBlock
->Table
[i
].KeyOffset
,NULL
);
1219 if (CurSubKeyCell
->NameSize
== KeyLength
1220 && !_strnicmp(KeyName
, CurSubKeyCell
->Name
, KeyLength
))
1222 *SubKeyCell
= CurSubKeyCell
;
1223 *BlockOffset
= HashBlock
->Table
[i
].KeyOffset
;
1228 CmiReleaseBlock(RegistryHive
, CurSubKeyCell
);
1234 CmiReleaseBlock(RegistryHive
, HashBlock
);
1236 return STATUS_SUCCESS
;
1241 CmiAddSubKey(PREGISTRY_HIVE RegistryHive
,
1244 PWSTR NewSubKeyName
,
1245 USHORT NewSubKeyNameSize
,
1247 PUNICODE_STRING Class
,
1248 ULONG CreateOptions
)
1250 PHASH_TABLE_CELL NewHashBlock
;
1251 PHASH_TABLE_CELL HashBlock
;
1252 BLOCK_OFFSET NKBOffset
;
1253 PKEY_CELL NewKeyCell
;
1259 KeyCell
= Parent
->KeyCell
;
1261 VERIFY_KEY_CELL(KeyCell
);
1263 if (NewSubKeyName
[0] == L
'\\')
1266 NameSize
= NewSubKeyNameSize
/ 2 - 1;
1270 NameSize
= NewSubKeyNameSize
/ 2;
1272 Status
= STATUS_SUCCESS
;
1274 NewBlockSize
= sizeof(KEY_CELL
) + NameSize
;
1275 Status
= CmiAllocateBlock(RegistryHive
,
1276 (PVOID
) &NewKeyCell
,
1280 if (NewKeyCell
== NULL
)
1282 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1286 NewKeyCell
->Id
= REG_KEY_CELL_ID
;
1287 NewKeyCell
->Type
= REG_KEY_CELL_TYPE
;
1288 ZwQuerySystemTime((PTIME
) &NewKeyCell
->LastWriteTime
);
1289 NewKeyCell
->ParentKeyOffset
= -1;
1290 NewKeyCell
->NumberOfSubKeys
= 0;
1291 NewKeyCell
->HashTableOffset
= -1;
1292 NewKeyCell
->NumberOfValues
= 0;
1293 NewKeyCell
->ValuesOffset
= -1;
1294 NewKeyCell
->SecurityKeyOffset
= -1;
1295 NewKeyCell
->NameSize
= NameSize
;
1296 wcstombs(NewKeyCell
->Name
, NewSubKeyName
, NameSize
);
1297 NewKeyCell
->ClassNameOffset
= -1;
1299 VERIFY_KEY_CELL(NewKeyCell
);
1305 NewKeyCell
->ClassSize
= Class
->Length
+ sizeof(WCHAR
);
1306 Status
= CmiAllocateBlock(RegistryHive
,
1308 NewKeyCell
->ClassSize
,
1309 &NewKeyCell
->ClassNameOffset
);
1310 wcsncpy((PWSTR
) pClass
->Data
, Class
->Buffer
, Class
->Length
);
1311 ((PWSTR
) (pClass
->Data
))[Class
->Length
] = 0;
1315 if (!NT_SUCCESS(Status
))
1320 SubKey
->KeyCell
= NewKeyCell
;
1321 SubKey
->BlockOffset
= NKBOffset
;
1323 /* Don't modify hash table if key is volatile and parent is not */
1324 if (IsVolatileHive(RegistryHive
) && (!IsVolatileHive(Parent
->RegistryHive
)))
1329 if (KeyCell
->HashTableOffset
== (ULONG_PTR
) -1)
1331 Status
= CmiAllocateHashTableBlock(RegistryHive
,
1333 &KeyCell
->HashTableOffset
,
1334 REG_INIT_HASH_TABLE_SIZE
);
1335 if (!NT_SUCCESS(Status
))
1342 HashBlock
= CmiGetBlock(RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
1343 if (((KeyCell
->NumberOfSubKeys
+ 1) >= HashBlock
->HashTableSize
))
1345 BLOCK_OFFSET HTOffset
;
1347 /* Reallocate the hash table block */
1348 Status
= CmiAllocateHashTableBlock(RegistryHive
,
1351 HashBlock
->HashTableSize
+
1352 REG_EXTEND_HASH_TABLE_SIZE
);
1353 if (!NT_SUCCESS(Status
))
1358 RtlZeroMemory(&NewHashBlock
->Table
[0],
1359 sizeof(NewHashBlock
->Table
[0]) * NewHashBlock
->HashTableSize
);
1360 RtlCopyMemory(&NewHashBlock
->Table
[0],
1361 &HashBlock
->Table
[0],
1362 sizeof(NewHashBlock
->Table
[0]) * HashBlock
->HashTableSize
);
1363 CmiDestroyBlock(RegistryHive
,
1365 KeyCell
->HashTableOffset
);
1366 KeyCell
->HashTableOffset
= HTOffset
;
1367 HashBlock
= NewHashBlock
;
1371 Status
= CmiAddKeyToHashTable(RegistryHive
,
1375 if (NT_SUCCESS(Status
))
1377 KeyCell
->NumberOfSubKeys
++;
1385 CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive
,
1386 PKEY_OBJECT ParentKey
,
1389 PHASH_TABLE_CELL HashBlock
;
1391 DPRINT1("CmiRemoveSubKey() called\n");
1393 /* Remove the key from the parent key's hash block */
1394 if (ParentKey
->KeyCell
->HashTableOffset
!= -1)
1396 DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey
->KeyCell
->HashTableOffset
)
1397 HashBlock
= CmiGetBlock(RegistryHive
,
1398 ParentKey
->KeyCell
->HashTableOffset
,
1400 DPRINT1("ParentKey HashBlock %p\n", HashBlock
)
1401 if (HashBlock
!= NULL
)
1403 CmiRemoveKeyFromHashTable(RegistryHive
,
1405 SubKey
->BlockOffset
);
1406 CmiMarkBlockDirty(RegistryHive
,
1407 ParentKey
->KeyCell
->HashTableOffset
);
1411 /* Remove the key's hash block */
1412 if (SubKey
->KeyCell
->HashTableOffset
!= -1)
1414 DPRINT1("SubKey HashTableOffset %lx\n", SubKey
->KeyCell
->HashTableOffset
)
1415 HashBlock
= CmiGetBlock(RegistryHive
,
1416 SubKey
->KeyCell
->HashTableOffset
,
1418 DPRINT1("SubKey HashBlock %p\n", HashBlock
)
1419 if (HashBlock
!= NULL
)
1421 CmiDestroyBlock(RegistryHive
,
1423 SubKey
->KeyCell
->HashTableOffset
);
1424 SubKey
->KeyCell
->HashTableOffset
= -1;
1428 /* Decrement the number of the parent key's sub keys */
1429 if (ParentKey
!= NULL
)
1431 DPRINT1("ParentKey %p\n", ParentKey
)
1432 ParentKey
->KeyCell
->NumberOfSubKeys
--;
1434 /* Remove the parent key's hash table */
1435 if (ParentKey
->KeyCell
->NumberOfSubKeys
== 0)
1437 DPRINT1("ParentKey HashTableOffset %lx\n", ParentKey
->KeyCell
->HashTableOffset
)
1438 HashBlock
= CmiGetBlock(RegistryHive
,
1439 ParentKey
->KeyCell
->HashTableOffset
,
1441 DPRINT1("ParentKey HashBlock %p\n", HashBlock
)
1442 if (HashBlock
!= NULL
)
1444 CmiDestroyBlock(RegistryHive
,
1446 ParentKey
->KeyCell
->HashTableOffset
);
1447 ParentKey
->KeyCell
->HashTableOffset
= -1;
1451 NtQuerySystemTime((PTIME
)&ParentKey
->KeyCell
->LastWriteTime
);
1452 CmiMarkBlockDirty(RegistryHive
,
1453 ParentKey
->BlockOffset
);
1456 /* Destroy key cell */
1457 CmiDestroyBlock(RegistryHive
,
1459 SubKey
->BlockOffset
);
1460 SubKey
->BlockOffset
= -1;
1461 SubKey
->KeyCell
= NULL
;
1463 return(STATUS_SUCCESS
);
1468 CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive
,
1469 IN PKEY_CELL KeyCell
,
1470 IN PUNICODE_STRING ValueName
,
1471 OUT PVALUE_CELL
*ValueCell
,
1472 OUT BLOCK_OFFSET
*VBOffset
)
1474 PVALUE_LIST_CELL ValueListCell
;
1475 PVALUE_CELL CurValueCell
;
1478 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1482 if (ValueListCell
== NULL
)
1484 DPRINT("ValueListCell is NULL\n");
1485 return STATUS_SUCCESS
;
1488 VERIFY_VALUE_LIST_CELL(ValueListCell
);
1490 for (i
= 0; i
< KeyCell
->NumberOfValues
; i
++)
1492 CurValueCell
= CmiGetBlock(RegistryHive
,
1493 ValueListCell
->Values
[i
],
1496 if ((CurValueCell
!= NULL
) &&
1497 CmiComparePackedNames(ValueName
,
1499 CurValueCell
->NameSize
,
1500 CurValueCell
->Flags
& REG_VALUE_NAME_PACKED
))
1502 *ValueCell
= CurValueCell
;
1504 *VBOffset
= ValueListCell
->Values
[i
];
1505 //DPRINT("Found value %s\n", ValueName);
1508 CmiReleaseBlock(RegistryHive
, CurValueCell
);
1511 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1513 return STATUS_SUCCESS
;
1518 CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive
,
1519 IN PKEY_CELL KeyCell
,
1521 OUT PVALUE_CELL
*ValueCell
)
1523 PVALUE_LIST_CELL ValueListCell
;
1524 PVALUE_CELL CurValueCell
;
1526 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1530 if (ValueListCell
== NULL
)
1532 return STATUS_NO_MORE_ENTRIES
;
1535 VERIFY_VALUE_LIST_CELL(ValueListCell
);
1537 if (Index
>= KeyCell
->NumberOfValues
)
1539 return STATUS_NO_MORE_ENTRIES
;
1542 CurValueCell
= CmiGetBlock(RegistryHive
,
1543 ValueListCell
->Values
[Index
],
1546 if (CurValueCell
!= NULL
)
1548 *ValueCell
= CurValueCell
;
1551 CmiReleaseBlock(RegistryHive
, CurValueCell
);
1552 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1554 return STATUS_SUCCESS
;
1559 CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive
,
1560 IN PKEY_CELL KeyCell
,
1561 IN PUNICODE_STRING ValueName
,
1562 OUT PVALUE_CELL
*pValueCell
,
1563 OUT BLOCK_OFFSET
*pVBOffset
)
1565 PVALUE_LIST_CELL NewValueListCell
;
1566 PVALUE_LIST_CELL ValueListCell
;
1567 PVALUE_CELL NewValueCell
;
1568 BLOCK_OFFSET VLBOffset
;
1569 BLOCK_OFFSET VBOffset
;
1572 Status
= CmiAllocateValueCell(RegistryHive
,
1576 *pVBOffset
= VBOffset
;
1578 if (!NT_SUCCESS(Status
))
1583 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1585 if (ValueListCell
== NULL
)
1587 Status
= CmiAllocateBlock(RegistryHive
,
1588 (PVOID
) &ValueListCell
,
1589 sizeof(BLOCK_OFFSET
) * 3,
1592 if (!NT_SUCCESS(Status
))
1594 CmiDestroyValueCell(RegistryHive
, NewValueCell
, VBOffset
);
1597 KeyCell
->ValuesOffset
= VLBOffset
;
1599 else if ((KeyCell
->NumberOfValues
1600 >= (ULONG
) ((LONG
) (ValueListCell
->CellSize
- 4)) / (LONG
) sizeof(BLOCK_OFFSET
)))
1602 Status
= CmiAllocateBlock(RegistryHive
,
1603 (PVOID
) &NewValueListCell
,
1604 sizeof(BLOCK_OFFSET
) * (KeyCell
->NumberOfValues
+ REG_VALUE_LIST_CELL_MULTIPLE
),
1607 if (!NT_SUCCESS(Status
))
1609 CmiDestroyValueCell(RegistryHive
, NewValueCell
, VBOffset
);
1613 RtlCopyMemory(&NewValueListCell
->Values
[0],
1614 &ValueListCell
->Values
[0],
1615 sizeof(BLOCK_OFFSET
) * KeyCell
->NumberOfValues
);
1616 CmiDestroyBlock(RegistryHive
, ValueListCell
, KeyCell
->ValuesOffset
);
1617 KeyCell
->ValuesOffset
= VLBOffset
;
1618 ValueListCell
= NewValueListCell
;
1621 DPRINT("KeyCell->NumberOfValues %d, ValueListCell->CellSize %d (%d %x)\n",
1622 KeyCell
->NumberOfValues
, ValueListCell
->CellSize
,
1623 -(ValueListCell
->CellSize
- 4) / sizeof(BLOCK_OFFSET
),
1624 -(ValueListCell
->CellSize
- 4) / sizeof(BLOCK_OFFSET
));
1626 ValueListCell
->Values
[KeyCell
->NumberOfValues
] = VBOffset
;
1627 KeyCell
->NumberOfValues
++;
1628 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1629 CmiReleaseBlock(RegistryHive
, NewValueCell
);
1630 *pValueCell
= NewValueCell
;
1632 return STATUS_SUCCESS
;
1637 CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive
,
1638 IN PKEY_CELL KeyCell
,
1639 IN BLOCK_OFFSET KeyCellOffset
,
1640 IN PUNICODE_STRING ValueName
)
1642 PVALUE_LIST_CELL ValueListCell
;
1643 PVALUE_CELL CurValueCell
;
1646 ValueListCell
= CmiGetBlock(RegistryHive
, KeyCell
->ValuesOffset
, NULL
);
1648 if (ValueListCell
== NULL
)
1650 return STATUS_SUCCESS
;
1653 VERIFY_VALUE_LIST_CELL(ValueListCell
);
1655 for (i
= 0; i
< KeyCell
->NumberOfValues
; i
++)
1657 CurValueCell
= CmiGetBlock(RegistryHive
, ValueListCell
->Values
[i
], NULL
);
1659 if ((CurValueCell
!= NULL
) &&
1660 CmiComparePackedNames(ValueName
,
1662 CurValueCell
->NameSize
,
1663 CurValueCell
->Flags
& REG_VALUE_NAME_PACKED
))
1665 CmiDestroyValueCell(RegistryHive
, CurValueCell
, ValueListCell
->Values
[i
]);
1667 if ((KeyCell
->NumberOfValues
- 1) < i
)
1669 RtlCopyMemory(&ValueListCell
->Values
[i
],
1670 &ValueListCell
->Values
[i
+ 1],
1671 sizeof(BLOCK_OFFSET
) * (KeyCell
->NumberOfValues
- 1 - i
));
1675 RtlZeroMemory(&ValueListCell
->Values
[i
], sizeof(BLOCK_OFFSET
));
1678 KeyCell
->NumberOfValues
-= 1;
1681 CmiReleaseBlock(RegistryHive
, CurValueCell
);
1684 CmiReleaseBlock(RegistryHive
, ValueListCell
);
1686 if (KeyCell
->NumberOfValues
== 0)
1688 CmiDestroyBlock(RegistryHive
,
1690 KeyCell
->ValuesOffset
);
1694 CmiMarkBlockDirty(RegistryHive
,
1695 KeyCell
->ValuesOffset
);
1698 CmiMarkBlockDirty(RegistryHive
,
1701 return STATUS_SUCCESS
;
1706 CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive
,
1707 OUT PHASH_TABLE_CELL
*HashBlock
,
1708 OUT BLOCK_OFFSET
*HBOffset
,
1709 IN ULONG HashTableSize
)
1711 PHASH_TABLE_CELL NewHashBlock
;
1715 Status
= STATUS_SUCCESS
;
1717 NewHashSize
= sizeof(HASH_TABLE_CELL
) +
1718 (HashTableSize
- 1) * sizeof(HASH_RECORD
);
1719 Status
= CmiAllocateBlock(RegistryHive
,
1720 (PVOID
*) &NewHashBlock
,
1724 if ((NewHashBlock
== NULL
) || (!NT_SUCCESS(Status
)))
1726 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1730 NewHashBlock
->Id
= REG_HASH_TABLE_BLOCK_ID
;
1731 NewHashBlock
->HashTableSize
= HashTableSize
;
1732 *HashBlock
= NewHashBlock
;
1740 CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive
,
1741 PHASH_TABLE_CELL HashBlock
,
1744 BLOCK_OFFSET KeyOffset
;
1747 if (HashBlock
== NULL
)
1750 if (IsVolatileHive(RegistryHive
))
1752 KeyCell
= (PKEY_CELL
) HashBlock
->Table
[Index
].KeyOffset
;
1756 KeyOffset
= HashBlock
->Table
[Index
].KeyOffset
;
1757 KeyCell
= CmiGetBlock(RegistryHive
, KeyOffset
, NULL
);
1759 CmiLockBlock(RegistryHive
, KeyCell
);
1766 CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive
,
1767 PHASH_TABLE_CELL HashBlock
,
1768 PKEY_CELL NewKeyCell
,
1769 BLOCK_OFFSET NKBOffset
)
1773 for (i
= 0; i
< HashBlock
->HashTableSize
; i
++)
1775 if (HashBlock
->Table
[i
].KeyOffset
== 0)
1777 HashBlock
->Table
[i
].KeyOffset
= NKBOffset
;
1778 RtlCopyMemory(&HashBlock
->Table
[i
].HashValue
, NewKeyCell
->Name
, 4);
1779 return STATUS_SUCCESS
;
1783 return STATUS_UNSUCCESSFUL
;
1788 CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive
,
1789 PHASH_TABLE_CELL HashBlock
,
1790 BLOCK_OFFSET NKBOffset
)
1794 for (i
= 0; i
< HashBlock
->HashTableSize
; i
++)
1796 if (HashBlock
->Table
[i
].KeyOffset
== NKBOffset
)
1798 HashBlock
->Table
[i
].KeyOffset
= 0;
1799 RtlZeroMemory(&HashBlock
->Table
[i
].HashValue
, 4);
1800 return STATUS_SUCCESS
;
1804 return STATUS_UNSUCCESSFUL
;
1809 CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive
,
1810 PVALUE_CELL
*ValueCell
,
1811 BLOCK_OFFSET
*VBOffset
,
1812 IN PUNICODE_STRING ValueName
)
1814 PVALUE_CELL NewValueCell
;
1820 Status
= STATUS_SUCCESS
;
1822 NameSize
= CmiGetPackedNameLength(ValueName
,
1825 DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName
->Length
, NameSize
);
1827 Status
= CmiAllocateBlock(RegistryHive
,
1828 (PVOID
*) &NewValueCell
,
1829 sizeof(VALUE_CELL
) + NameSize
,
1831 if ((NewValueCell
== NULL
) || (!NT_SUCCESS(Status
)))
1833 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1837 NewValueCell
->Id
= REG_VALUE_CELL_ID
;
1838 NewValueCell
->NameSize
= NameSize
;
1841 /* Pack the value name */
1842 for (i
= 0; i
< NameSize
; i
++)
1843 NewValueCell
->Name
[i
] = (CHAR
)ValueName
->Buffer
[i
];
1844 NewValueCell
->Flags
|= REG_VALUE_NAME_PACKED
;
1848 /* Copy the value name */
1849 RtlCopyMemory(NewValueCell
->Name
,
1852 NewValueCell
->Flags
= 0;
1854 NewValueCell
->DataType
= 0;
1855 NewValueCell
->DataSize
= 0;
1856 NewValueCell
->DataOffset
= 0xffffffff;
1857 *ValueCell
= NewValueCell
;
1865 CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive
,
1866 PVALUE_CELL ValueCell
,
1867 BLOCK_OFFSET VBOffset
)
1873 DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell
, VBOffset
);
1875 VERIFY_VALUE_CELL(ValueCell
);
1877 /* Destroy the data cell */
1878 if (ValueCell
->DataSize
> 4)
1880 pBlock
= CmiGetBlock(RegistryHive
, ValueCell
->DataOffset
, &pBin
);
1881 Status
= CmiDestroyBlock(RegistryHive
, pBlock
, ValueCell
->DataOffset
);
1882 if (!NT_SUCCESS(Status
))
1887 /* Update time of heap */
1888 if (IsPermanentHive(RegistryHive
))
1889 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1892 /* Destroy the value cell */
1893 Status
= CmiDestroyBlock(RegistryHive
, ValueCell
, VBOffset
);
1895 /* Update time of heap */
1896 if (IsPermanentHive(RegistryHive
) && CmiGetBlock(RegistryHive
, VBOffset
, &pBin
))
1898 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
1906 CmiAddBin(PREGISTRY_HIVE RegistryHive
,
1908 BLOCK_OFFSET
*NewBlockOffset
)
1910 PCELL_HEADER tmpBlock
;
1911 PHBIN
* tmpBlockList
;
1914 tmpBin
= ExAllocatePool(PagedPool
, REG_BLOCK_SIZE
);
1917 return STATUS_INSUFFICIENT_RESOURCES
;
1920 tmpBin
->BlockId
= REG_BIN_ID
;
1921 tmpBin
->BlockOffset
= RegistryHive
->FileSize
- REG_BLOCK_SIZE
;
1922 RegistryHive
->FileSize
+= REG_BLOCK_SIZE
;
1923 tmpBin
->BlockSize
= REG_BLOCK_SIZE
;
1924 tmpBin
->Unused1
= 0;
1925 ZwQuerySystemTime((PTIME
) &tmpBin
->DateModified
);
1926 tmpBin
->Unused2
= 0;
1928 /* Increase size of list of blocks */
1929 tmpBlockList
= ExAllocatePool(NonPagedPool
,
1930 sizeof(PHBIN
*) * (RegistryHive
->BlockListSize
+ 1));
1931 if (tmpBlockList
== NULL
)
1934 return STATUS_INSUFFICIENT_RESOURCES
;
1937 if (RegistryHive
->BlockListSize
> 0)
1939 memcpy(tmpBlockList
,
1940 RegistryHive
->BlockList
,
1941 sizeof(PHBIN
*)*(RegistryHive
->BlockListSize
));
1942 ExFreePool(RegistryHive
->BlockList
);
1945 RegistryHive
->BlockList
= tmpBlockList
;
1946 RegistryHive
->BlockList
[RegistryHive
->BlockListSize
++] = tmpBin
;
1948 /* Initialize a free block in this heap : */
1949 tmpBlock
= (PCELL_HEADER
)((ULONG_PTR
) tmpBin
+ REG_HBIN_DATA_OFFSET
);
1950 tmpBlock
->CellSize
= (REG_BLOCK_SIZE
- REG_HBIN_DATA_OFFSET
);
1952 /* Grow bitmap if necessary */
1953 if (IsVolatileHive(RegistryHive
) &&
1954 (RegistryHive
->BlockListSize
% (sizeof(ULONG
) * 8) == 0))
1956 DPRINT1("Grow hive bitmap - BlockListSize %lu\n", RegistryHive
->BlockListSize
);
1962 *NewBlock
= (PVOID
) tmpBlock
;
1965 *NewBlockOffset
= tmpBin
->BlockOffset
+ REG_HBIN_DATA_OFFSET
;
1967 /* FIXME: set first dword to block_offset of another free bloc */
1969 return STATUS_SUCCESS
;
1974 CmiAllocateBlock(PREGISTRY_HIVE RegistryHive
,
1977 BLOCK_OFFSET
* pBlockOffset
)
1979 PCELL_HEADER NewBlock
;
1983 Status
= STATUS_SUCCESS
;
1985 /* Round to 16 bytes multiple */
1986 BlockSize
= (BlockSize
+ sizeof(DWORD
) + 15) & 0xfffffff0;
1988 /* Handle volatile hives first */
1989 if (IsVolatileHive(RegistryHive
))
1991 NewBlock
= ExAllocatePool(NonPagedPool
, BlockSize
);
1993 if (NewBlock
== NULL
)
1995 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1999 RtlZeroMemory(NewBlock
, BlockSize
);
2000 NewBlock
->CellSize
= BlockSize
;
2001 CmiLockBlock(RegistryHive
, NewBlock
);
2004 *pBlockOffset
= (BLOCK_OFFSET
) NewBlock
;
2011 /* first search in free blocks */
2013 for (i
= 0; i
< RegistryHive
->FreeListSize
; i
++)
2015 if (RegistryHive
->FreeList
[i
]->CellSize
>= BlockSize
)
2019 NewBlock
= RegistryHive
->FreeList
[i
];
2021 *pBlockOffset
= RegistryHive
->FreeListOffset
[i
];
2023 /* Update time of heap */
2024 Temp
= CmiGetBlock(RegistryHive
, RegistryHive
->FreeListOffset
[i
], &pBin
);
2028 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
2029 CmiMarkBlockDirty(RegistryHive
, RegistryHive
->FreeListOffset
[i
]);
2032 if ((i
+ 1) < RegistryHive
->FreeListSize
)
2034 RtlMoveMemory(&RegistryHive
->FreeList
[i
],
2035 &RegistryHive
->FreeList
[i
+ 1],
2036 sizeof(RegistryHive
->FreeList
[0])
2037 * (RegistryHive
->FreeListSize
- i
- 1));
2038 RtlMoveMemory(&RegistryHive
->FreeListOffset
[i
],
2039 &RegistryHive
->FreeListOffset
[i
+ 1],
2040 sizeof(RegistryHive
->FreeListOffset
[0])
2041 * (RegistryHive
->FreeListSize
- i
- 1));
2043 RegistryHive
->FreeListSize
--;
2048 /* Need to extend hive file : */
2049 if (NewBlock
== NULL
)
2051 /* Add a new block */
2052 Status
= CmiAddBin(RegistryHive
, (PVOID
*) &NewBlock
, pBlockOffset
);
2055 if (NT_SUCCESS(Status
))
2059 /* Split the block in two parts */
2060 if (NewBlock
->CellSize
> BlockSize
)
2062 NewBlock
= (PCELL_HEADER
) ((ULONG_PTR
) NewBlock
+BlockSize
);
2063 NewBlock
->CellSize
= ((PCELL_HEADER
) (*Block
))->CellSize
- BlockSize
;
2064 CmiAddFree(RegistryHive
,
2066 *pBlockOffset
+ BlockSize
,
2068 CmiMarkBlockDirty(RegistryHive
,
2069 *pBlockOffset
+ BlockSize
);
2071 else if (NewBlock
->CellSize
< BlockSize
)
2073 return(STATUS_UNSUCCESSFUL
);
2076 RtlZeroMemory(*Block
, BlockSize
);
2077 ((PCELL_HEADER
) (*Block
))->CellSize
= -BlockSize
;
2078 CmiLockBlock(RegistryHive
, *Block
);
2087 CmiDestroyBlock(PREGISTRY_HIVE RegistryHive
,
2089 BLOCK_OFFSET Offset
)
2094 Status
= STATUS_SUCCESS
;
2096 if (IsVolatileHive(RegistryHive
))
2098 CmiReleaseBlock(RegistryHive
, Block
);
2103 PCELL_HEADER pFree
= Block
;
2105 if (pFree
->CellSize
< 0)
2106 pFree
->CellSize
= -pFree
->CellSize
;
2108 /* Clear block (except the block size) */
2109 RtlZeroMemory(((PVOID
)pFree
) + sizeof(ULONG
),
2110 pFree
->CellSize
- sizeof(ULONG
));
2112 /* add block to the list of free blocks */
2113 CmiAddFree(RegistryHive
, Block
, Offset
, TRUE
);
2114 CmiReleaseBlock(RegistryHive
, Block
);
2116 /* Update time of heap */
2117 if (IsPermanentHive(RegistryHive
) && CmiGetBlock(RegistryHive
, Offset
,&pBin
))
2118 ZwQuerySystemTime((PTIME
) &pBin
->DateModified
);
2120 CmiMarkBlockDirty(RegistryHive
, Offset
);
2122 /* FIXME: Set first dword to block_offset of another free block ? */
2123 /* FIXME: Concatenate with previous and next block if free */
2131 CmiMergeFree(PREGISTRY_HIVE RegistryHive
,
2132 PCELL_HEADER FreeBlock
,
2133 BLOCK_OFFSET FreeOffset
)
2135 BLOCK_OFFSET BlockOffset
;
2136 BLOCK_OFFSET BinOffset
;
2142 DPRINT("CmiMergeFree(Block %lx Offset %lx Size %lx) called\n",
2143 FreeBlock
, FreeOffset
, FreeBlock
->CellSize
);
2145 CmiGetBlock(RegistryHive
,
2148 DPRINT("Bin %p\n", Bin
);
2152 BinOffset
= Bin
->BlockOffset
;
2153 BinSize
= Bin
->BlockSize
;
2154 DPRINT("Bin %p Offset %lx Size %lx\n", Bin
, BinOffset
, BinSize
);
2156 for (i
= 0; i
< RegistryHive
->FreeListSize
; i
++)
2158 BlockOffset
= RegistryHive
->FreeListOffset
[i
];
2159 BlockSize
= RegistryHive
->FreeList
[i
]->CellSize
;
2160 if (BlockOffset
> BinOffset
&&
2161 BlockOffset
< BinOffset
+ BinSize
)
2163 DPRINT("Free block: Offset %lx Size %lx\n",
2164 BlockOffset
, BlockSize
);
2166 if ((i
< (RegistryHive
->FreeListSize
- 1)) &&
2167 (BlockOffset
+ BlockSize
== FreeOffset
) &&
2168 (FreeOffset
+ FreeBlock
->CellSize
== RegistryHive
->FreeListOffset
[i
+ 1]))
2170 DPRINT("Merge current block with previous and next block\n");
2172 RegistryHive
->FreeList
[i
]->CellSize
+=
2173 (FreeBlock
->CellSize
+ RegistryHive
->FreeList
[i
+ 1]->CellSize
);
2175 FreeBlock
->CellSize
= 0;
2176 RegistryHive
->FreeList
[i
+ 1]->CellSize
= 0;
2179 if ((i
+ 2) < RegistryHive
->FreeListSize
)
2181 RtlMoveMemory(&RegistryHive
->FreeListOffset
[i
+ 1],
2182 &RegistryHive
->FreeListOffset
[i
+ 2],
2183 sizeof(RegistryHive
->FreeListOffset
[0])
2184 * (RegistryHive
->FreeListSize
- i
- 2));
2186 RegistryHive
->FreeListSize
--;
2188 CmiMarkBlockDirty(RegistryHive
, BlockOffset
);
2192 else if (BlockOffset
+ BlockSize
== FreeOffset
)
2194 DPRINT("Merge current block with previous block\n");
2196 RegistryHive
->FreeList
[i
]->CellSize
+= FreeBlock
->CellSize
;
2197 FreeBlock
->CellSize
= 0;
2199 CmiMarkBlockDirty(RegistryHive
, BlockOffset
);
2203 else if (FreeOffset
+ FreeBlock
->CellSize
== BlockOffset
)
2205 DPRINT("Merge current block with next block\n");
2207 FreeBlock
->CellSize
+= RegistryHive
->FreeList
[i
]->CellSize
;
2208 RegistryHive
->FreeList
[i
]->CellSize
= 0;
2209 RegistryHive
->FreeList
[i
] = FreeBlock
;
2210 RegistryHive
->FreeListOffset
[i
] = FreeOffset
;
2212 CmiMarkBlockDirty(RegistryHive
, FreeOffset
);
2224 CmiAddFree(PREGISTRY_HIVE RegistryHive
,
2225 PCELL_HEADER FreeBlock
,
2226 BLOCK_OFFSET FreeOffset
,
2227 BOOLEAN MergeFreeBlocks
)
2229 PCELL_HEADER
*tmpList
;
2230 BLOCK_OFFSET
*tmpListOffset
;
2235 assert(RegistryHive
);
2238 DPRINT("FreeBlock %.08lx FreeOffset %.08lx\n",
2239 FreeBlock
, FreeOffset
);
2241 /* Merge free blocks */
2242 if (MergeFreeBlocks
== TRUE
)
2244 if (CmiMergeFree(RegistryHive
, FreeBlock
, FreeOffset
))
2245 return(STATUS_SUCCESS
);
2248 if ((RegistryHive
->FreeListSize
+ 1) > RegistryHive
->FreeListMax
)
2250 tmpList
= ExAllocatePool(PagedPool
,
2251 sizeof(PCELL_HEADER
) * (RegistryHive
->FreeListMax
+ 32));
2252 if (tmpList
== NULL
)
2253 return STATUS_INSUFFICIENT_RESOURCES
;
2255 tmpListOffset
= ExAllocatePool(PagedPool
,
2256 sizeof(BLOCK_OFFSET
*) * (RegistryHive
->FreeListMax
+ 32));
2258 if (tmpListOffset
== NULL
)
2260 ExFreePool(tmpList
);
2261 return STATUS_INSUFFICIENT_RESOURCES
;
2264 if (RegistryHive
->FreeListMax
)
2266 RtlMoveMemory(tmpList
,
2267 RegistryHive
->FreeList
,
2268 sizeof(PCELL_HEADER
) * (RegistryHive
->FreeListMax
));
2269 RtlMoveMemory(tmpListOffset
,
2270 RegistryHive
->FreeListOffset
,
2271 sizeof(BLOCK_OFFSET
*) * (RegistryHive
->FreeListMax
));
2272 ExFreePool(RegistryHive
->FreeList
);
2273 ExFreePool(RegistryHive
->FreeListOffset
);
2275 RegistryHive
->FreeList
= tmpList
;
2276 RegistryHive
->FreeListOffset
= tmpListOffset
;
2277 RegistryHive
->FreeListMax
+= 32;
2280 /* Add new offset to free list, maintaining list in ascending order */
2281 if ((RegistryHive
->FreeListSize
== 0)
2282 || (RegistryHive
->FreeListOffset
[RegistryHive
->FreeListSize
-1] < FreeOffset
))
2284 /* Add to end of list */
2285 RegistryHive
->FreeList
[RegistryHive
->FreeListSize
] = FreeBlock
;
2286 RegistryHive
->FreeListOffset
[RegistryHive
->FreeListSize
++] = FreeOffset
;
2288 else if (RegistryHive
->FreeListOffset
[0] > FreeOffset
)
2290 /* Add to begin of list */
2291 RtlMoveMemory(&RegistryHive
->FreeList
[1],
2292 &RegistryHive
->FreeList
[0],
2293 sizeof(RegistryHive
->FreeList
[0]) * RegistryHive
->FreeListSize
);
2294 RtlMoveMemory(&RegistryHive
->FreeListOffset
[1],
2295 &RegistryHive
->FreeListOffset
[0],
2296 sizeof(RegistryHive
->FreeListOffset
[0]) * RegistryHive
->FreeListSize
);
2297 RegistryHive
->FreeList
[0] = FreeBlock
;
2298 RegistryHive
->FreeListOffset
[0] = FreeOffset
;
2299 RegistryHive
->FreeListSize
++;
2303 /* Search where to insert */
2305 maxInd
= RegistryHive
->FreeListSize
- 1;
2306 while ((maxInd
- minInd
) > 1)
2308 medInd
= (minInd
+ maxInd
) / 2;
2309 if (RegistryHive
->FreeListOffset
[medInd
] > FreeOffset
)
2315 /* Insert before maxInd */
2316 RtlMoveMemory(&RegistryHive
->FreeList
[maxInd
+1],
2317 &RegistryHive
->FreeList
[maxInd
],
2318 sizeof(RegistryHive
->FreeList
[0]) * (RegistryHive
->FreeListSize
- minInd
));
2319 RtlMoveMemory(&RegistryHive
->FreeListOffset
[maxInd
+ 1],
2320 &RegistryHive
->FreeListOffset
[maxInd
],
2321 sizeof(RegistryHive
->FreeListOffset
[0]) * (RegistryHive
->FreeListSize
-minInd
));
2322 RegistryHive
->FreeList
[maxInd
] = FreeBlock
;
2323 RegistryHive
->FreeListOffset
[maxInd
] = FreeOffset
;
2324 RegistryHive
->FreeListSize
++;
2327 return STATUS_SUCCESS
;
2332 CmiGetBlock(PREGISTRY_HIVE RegistryHive
,
2333 BLOCK_OFFSET BlockOffset
,
2339 if ((BlockOffset
== 0) || (BlockOffset
== (ULONG_PTR
) -1))
2342 if (IsVolatileHive(RegistryHive
))
2344 return (PVOID
) BlockOffset
;
2350 pBin
= RegistryHive
->BlockList
[BlockOffset
/ 4096];
2353 return((PVOID
)((ULONG_PTR
)pBin
+ (BlockOffset
- pBin
->BlockOffset
)));
2359 CmiLockBlock(PREGISTRY_HIVE RegistryHive
,
2362 if (IsPermanentHive(RegistryHive
))
2364 /* FIXME: Implement */
2370 CmiReleaseBlock(PREGISTRY_HIVE RegistryHive
,
2373 if (IsPermanentHive(RegistryHive
))
2375 /* FIXME: Implement */
2381 CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive
,
2382 BLOCK_OFFSET BlockOffset
)
2386 if (IsVolatileHive(RegistryHive
))
2389 Index
= (ULONG
)BlockOffset
/ 4096;
2391 DPRINT1("CmiMarkBlockDirty(Offset 0x%lx) Index %lu\n",
2392 (ULONG
)BlockOffset
, Index
);
2394 RegistryHive
->HiveDirty
= TRUE
;
2395 RtlSetBits(&RegistryHive
->DirtyBitMap
,
2402 CmiGetPackedNameLength(IN PUNICODE_STRING Name
,
2403 OUT PBOOLEAN Packable
)
2407 if (Packable
!= NULL
)
2410 for (i
= 0; i
< Name
->Length
; i
++)
2412 if (Name
->Buffer
[i
] > 0xFF)
2414 if (Packable
!= NULL
)
2416 return(Name
->Length
);
2420 return(Name
->Length
/ sizeof(WCHAR
));
2425 CmiComparePackedNames(IN PUNICODE_STRING Name
,
2426 IN PCHAR NameBuffer
,
2427 IN USHORT NameBufferSize
,
2428 IN BOOLEAN NamePacked
)
2433 if (NamePacked
== TRUE
)
2435 if (Name
->Length
!= NameBufferSize
* sizeof(WCHAR
))
2438 for (i
= 0; i
< Name
->Length
/ sizeof(WCHAR
); i
++)
2440 if (RtlUpcaseUnicodeChar(Name
->Buffer
[i
]) != RtlUpcaseUnicodeChar((WCHAR
)NameBuffer
[i
]))
2446 if (Name
->Length
!= NameBufferSize
)
2449 UNameBuffer
= (PWCHAR
)NameBuffer
;
2451 for (i
= 0; i
< Name
->Length
/ sizeof(WCHAR
); i
++)
2453 if (RtlUpcaseUnicodeChar(Name
->Buffer
[i
]) != RtlUpcaseUnicodeChar(UNameBuffer
[i
]))
2463 CmiCopyPackedName(PWCHAR NameBuffer
,
2464 PCHAR PackedNameBuffer
,
2465 ULONG PackedNameSize
)
2469 for (i
= 0; i
< PackedNameSize
; i
++)
2470 NameBuffer
[i
] = (WCHAR
)PackedNameBuffer
[i
];