Added hive flushing.

- Only keys are supported (create / delete).
- No log-file support yet.
- Still a little buggy.

svn path=/trunk/; revision=4122
This commit is contained in:
Eric Kohl 2003-02-09 11:57:14 +00:00
parent 652669005d
commit 8a23cc7a5b
5 changed files with 504 additions and 238 deletions

View file

@ -55,7 +55,7 @@
#define MAX_REG_STD_HANDLE_NAME 19 #define MAX_REG_STD_HANDLE_NAME 19
// BLOCK_OFFSET = offset in file after header block // BLOCK_OFFSET = offset in file after header block
typedef DWORD BLOCK_OFFSET; typedef ULONG BLOCK_OFFSET;
/* header for registry hive file : */ /* header for registry hive file : */
typedef struct _HIVE_HEADER typedef struct _HIVE_HEADER
@ -256,6 +256,9 @@ typedef struct _REGISTRY_HIVE
BLOCK_OFFSET *FreeListOffset; BLOCK_OFFSET *FreeListOffset;
ERESOURCE HiveResource; ERESOURCE HiveResource;
RTL_BITMAP DirtyBitMap;
BOOLEAN HiveDirty;
// NTSTATUS (*Extend)(ULONG NewSize); // NTSTATUS (*Extend)(ULONG NewSize);
// PVOID (*Flush)(VOID); // PVOID (*Flush)(VOID);
} REGISTRY_HIVE, *PREGISTRY_HIVE; } REGISTRY_HIVE, *PREGISTRY_HIVE;
@ -396,6 +399,9 @@ CmiCreateRegistryHive(PWSTR Filename,
NTSTATUS NTSTATUS
CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive); CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive);
NTSTATUS
CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive);
ULONG ULONG
CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive, CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell); IN PKEY_CELL KeyCell);
@ -473,6 +479,11 @@ CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
PKEY_CELL NewKeyCell, PKEY_CELL NewKeyCell,
BLOCK_OFFSET NKBOffset); BLOCK_OFFSET NKBOffset);
NTSTATUS
CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
BLOCK_OFFSET NKBOffset);
NTSTATUS NTSTATUS
CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive,
OUT PVALUE_CELL *ValueCell, OUT PVALUE_CELL *ValueCell,
@ -508,6 +519,10 @@ VOID
CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, CmiReleaseBlock(PREGISTRY_HIVE RegistryHive,
PVOID Block); PVOID Block);
VOID
CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
BLOCK_OFFSET BlockOffset);
NTSTATUS NTSTATUS
CmiAddFree(PREGISTRY_HIVE RegistryHive, CmiAddFree(PREGISTRY_HIVE RegistryHive,
PCELL_HEADER FreeBlock, PCELL_HEADER FreeBlock,

View file

@ -112,7 +112,6 @@ NtCreateKey(OUT PHANDLE KeyHandle,
NULL, NULL,
CmiKeyType, CmiKeyType,
(PVOID*)&KeyObject); (PVOID*)&KeyObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return(Status);
@ -142,7 +141,6 @@ NtCreateKey(OUT PHANDLE KeyHandle,
TitleIndex, TitleIndex,
Class, Class,
CreateOptions); CreateOptions);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
@ -203,12 +201,11 @@ NtDeleteKey(IN HANDLE KeyHandle)
KEY_WRITE, KEY_WRITE,
CmiKeyType, CmiKeyType,
UserMode, UserMode,
(PVOID *) &KeyObject, (PVOID *)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return(Status);
} }
/* Acquire hive lock */ /* Acquire hive lock */
@ -219,21 +216,26 @@ NtDeleteKey(IN HANDLE KeyHandle)
/* Set the marked for delete bit in the key object */ /* Set the marked for delete bit in the key object */
KeyObject->Flags |= KO_MARKED_FOR_DELETE; KeyObject->Flags |= KO_MARKED_FOR_DELETE;
/* Release hive lock */
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
/* Dereference the object */ /* Dereference the object */
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive) if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
/* Close the handle */
ObDeleteHandle(PsGetCurrentProcess(), KeyHandle);
/* FIXME: I think that ObDeleteHandle should dereference the object */
ObDereferenceObject(KeyObject);
/* Release hive lock */ DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
CmiSyncHives(); /*
* Note:
* Hive-Synchronization will not be triggered here. This is done in
* CmiObjectDelete() (in regobj.c) after all key-related structures
* have been released.
*/
return STATUS_SUCCESS; return(STATUS_SUCCESS);
} }
@ -678,6 +680,7 @@ NtFlushKey(IN HANDLE KeyHandle)
NTSTATUS Status; NTSTATUS Status;
PKEY_OBJECT KeyObject; PKEY_OBJECT KeyObject;
PREGISTRY_HIVE RegistryHive; PREGISTRY_HIVE RegistryHive;
#if 0
WCHAR LogName[MAX_PATH]; WCHAR LogName[MAX_PATH];
UNICODE_STRING TmpFileName; UNICODE_STRING TmpFileName;
HANDLE FileHandle; HANDLE FileHandle;
@ -686,6 +689,7 @@ NtFlushKey(IN HANDLE KeyHandle)
LARGE_INTEGER fileOffset; LARGE_INTEGER fileOffset;
DWORD * pEntDword; DWORD * pEntDword;
ULONG i; ULONG i;
#endif
DPRINT("KeyHandle %x\n", KeyHandle); DPRINT("KeyHandle %x\n", KeyHandle);
@ -694,21 +698,33 @@ NtFlushKey(IN HANDLE KeyHandle)
KEY_QUERY_VALUE, KEY_QUERY_VALUE,
CmiKeyType, CmiKeyType,
UserMode, UserMode,
(PVOID *) &KeyObject, (PVOID *)&KeyObject,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return(Status);
} }
/* Acquire hive lock */
ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
VERIFY_KEY_OBJECT(KeyObject); VERIFY_KEY_OBJECT(KeyObject);
RegistryHive = KeyObject->RegistryHive; RegistryHive = KeyObject->RegistryHive;
/* Acquire hive lock */
ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
TRUE);
if (IsPermanentHive(RegistryHive))
{
/* Flush non-volatile hive */
Status = CmiFlushRegistryHive(RegistryHive);
}
else
{
Status = STATUS_SUCCESS;
}
#if 0
/* Then write changed blocks in .log */ /* Then write changed blocks in .log */
wcscpy(LogName,RegistryHive->Filename.Buffer); wcscpy(LogName,RegistryHive->Filename.Buffer);
wcscat(LogName,L".log"); wcscat(LogName,L".log");
@ -891,8 +907,12 @@ END FIXME*/
} }
ZwClose(FileHandle); ZwClose(FileHandle);
ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); #endif
ExReleaseResourceLite(&RegistryHive->HiveResource);
ObDereferenceObject(KeyObject); ObDereferenceObject(KeyObject);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1424,6 +1444,7 @@ NtSetValueKey(IN HANDLE KeyHandle,
{ {
/* If new data size is <= current then overwrite current data */ /* If new data size is <= current then overwrite current data */
DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
RtlCopyMemory(DataCell->Data, Data, DataSize); RtlCopyMemory(DataCell->Data, Data, DataSize);
ValueCell->DataSize = DataSize; ValueCell->DataSize = DataSize;
ValueCell->DataType = Type; ValueCell->DataType = Type;

View file

@ -24,10 +24,12 @@
#include "cm.h" #include "cm.h"
#endif #endif
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
BOOLEAN CmiDoVerify = FALSE; BOOLEAN CmiDoVerify = FALSE;
/* FUNCTIONS ****************************************************************/
VOID VOID
CmiCreateDefaultHiveHeader(PHIVE_HEADER Header) CmiCreateDefaultHiveHeader(PHIVE_HEADER Header)
{ {
@ -421,28 +423,28 @@ CmiCreateNewRegFile(HANDLE FileHandle)
PKEY_CELL RootKeyCell; PKEY_CELL RootKeyCell;
NTSTATUS Status; NTSTATUS Status;
PHBIN BinCell; PHBIN BinCell;
PCHAR tBuf; PCHAR Buffer;
tBuf = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); Buffer = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE);
if (tBuf == NULL) if (Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
HiveHeader = (PHIVE_HEADER) tBuf; HiveHeader = (PHIVE_HEADER)Buffer;
BinCell = (PHBIN) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE); BinCell = (PHBIN)((ULONG_PTR)Buffer + REG_BLOCK_SIZE);
RootKeyCell = (PKEY_CELL) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET); RootKeyCell = (PKEY_CELL)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET);
FreeCell = (PCELL_HEADER) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); FreeCell = (PCELL_HEADER)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
CmiCreateDefaultHiveHeader(HiveHeader); CmiCreateDefaultHiveHeader(HiveHeader);
CmiCreateDefaultBinCell(BinCell); CmiCreateDefaultBinCell(BinCell);
CmiCreateDefaultRootKeyCell(RootKeyCell); CmiCreateDefaultRootKeyCell(RootKeyCell);
// First block /* First block */
BinCell->BlockOffset = 0; BinCell->BlockOffset = 0;
// Offset to root key block /* Offset to root key block */
HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET; HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET;
// The rest of the block is free /* The rest of the block is free */
FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL));
Status = ZwWriteFile(FileHandle, Status = ZwWriteFile(FileHandle,
@ -450,12 +452,12 @@ CmiCreateNewRegFile(HANDLE FileHandle)
NULL, NULL,
NULL, NULL,
&IoStatusBlock, &IoStatusBlock,
tBuf, Buffer,
2 * REG_BLOCK_SIZE, 2 * REG_BLOCK_SIZE,
0, 0,
NULL); NULL);
ExFreePool(tBuf); ExFreePool(Buffer);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
@ -487,14 +489,16 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
NTSTATUS Status; NTSTATUS Status;
PHBIN tmpBin; PHBIN tmpBin;
ULONG i, j; ULONG i, j;
ULONG BitmapSize;
PULONG BitmapBuffer;
DPRINT("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew); DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew);
/* Duplicate Filename */ /* Duplicate Filename */
Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename); Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("CmiInitPermanentRegistryHive() - Failed 1.\n"); DPRINT1("CmiInitPermanentRegistryHive() - Failed 1.\n");
return Status; return Status;
} }
@ -504,7 +508,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
NULL, NULL,
NULL); NULL);
if (CreateNew) if (CreateNew == TRUE)
CreateDisposition = FILE_OPEN_IF; CreateDisposition = FILE_OPEN_IF;
else else
CreateDisposition = FILE_OPEN; CreateDisposition = FILE_OPEN;
@ -532,8 +536,8 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
Status = CmiCreateNewRegFile(FileHandle); Status = CmiCreateNewRegFile(FileHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("CmiCreateNewRegFile() failed (Status %lx)\n", Status);
RtlFreeUnicodeString(&RegistryHive->Filename); RtlFreeUnicodeString(&RegistryHive->Filename);
DPRINT1("CmiCreateNewRegFile() - Failed with status %x.\n", Status);
return(Status); return(Status);
} }
} }
@ -542,7 +546,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
FILE_ALL_ACCESS, FILE_ALL_ACCESS,
IoFileObjectType, IoFileObjectType,
UserMode, UserMode,
(PVOID*) &RegistryHive->FileObject, (PVOID*)&RegistryHive->FileObject,
NULL); NULL);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
@ -551,10 +555,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
{ {
NtClose(FileHandle); NtClose(FileHandle);
RtlFreeUnicodeString(&RegistryHive->Filename); RtlFreeUnicodeString(&RegistryHive->Filename);
DPRINT("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status); DPRINT1("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status);
return Status; return Status;
} }
/* Read hive header */
FileOffset.u.HighPart = 0; FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = 0; FileOffset.u.LowPart = 0;
DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, sizeof(HIVE_HEADER), RegistryHive->HiveHeader); DPRINT(" Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, sizeof(HIVE_HEADER), RegistryHive->HiveHeader);
@ -567,9 +572,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
sizeof(HIVE_HEADER), sizeof(HIVE_HEADER),
&FileOffset, &FileOffset,
0); 0);
assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ObDereferenceObject(RegistryHive->FileObject); ObDereferenceObject(RegistryHive->FileObject);
@ -744,7 +747,21 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
BlockOffset += tmpBin->BlockSize; BlockOffset += tmpBin->BlockSize;
} }
DPRINT("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive, Filename, CreateNew); /* Create block bitmap and clear all bits */
/* Calculate bitmap size in bytes (always a multiple of 32 bits) */
BitmapSize = ROUND_UP(RegistryHive->BlockListSize, sizeof(ULONG) * 8) / 8;
DPRINT1("RegistryHive->BlockListSize: %lu\n", RegistryHive->BlockListSize);
DPRINT1("BitmapSize: %lu Bytes %lu Bits\n", BitmapSize, BitmapSize * 8);
BitmapBuffer = (PULONG)ExAllocatePool(PagedPool,
BitmapSize);
RtlInitializeBitMap(&RegistryHive->DirtyBitMap,
BitmapBuffer,
BitmapSize * 8);
RtlClearAllBits(&RegistryHive->DirtyBitMap);
RegistryHive->HiveDirty = FALSE;
DPRINT1("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive, Filename, CreateNew);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -859,6 +876,113 @@ CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
} }
NTSTATUS
CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive)
{
ULONG BlockIndex;
ULONG BlockOffset;
PVOID BlockPtr;
LARGE_INTEGER FileOffset;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
DPRINT("CmiFlushRegistryHive() called\n");
if (RegistryHive->HiveDirty == FALSE)
{
return(STATUS_SUCCESS);
}
DPRINT1("Hive '%wZ' is dirty\n", &RegistryHive->Filename);
/* Open hive for writing */
InitializeObjectAttributes(&ObjectAttributes,
&RegistryHive->Filename,
0,
NULL,
NULL);
Status = NtCreateFile(&FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
return(Status);
}
BlockIndex = 0;
while (TRUE)
{
BlockIndex = RtlFindSetBitsAndClear(&RegistryHive->DirtyBitMap,
1,
BlockIndex);
if (BlockIndex == (ULONG)-1)
{
DPRINT("No more set bits\n");
break;
}
DPRINT1("Block %lu is dirty\n", BlockIndex);
BlockOffset = RegistryHive->BlockList[BlockIndex]->BlockOffset;
DPRINT1("Block offset %lx\n", BlockOffset);
BlockPtr = RegistryHive->BlockList[BlockIndex] + ((BlockIndex * 4096) - BlockOffset);
DPRINT1("BlockPtr %p\n", BlockPtr);
FileOffset.QuadPart = (ULONGLONG)(BlockIndex + 1) * 4096ULL;
DPRINT1("File offset %I64x\n", FileOffset.QuadPart);
/* Write hive block */
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
BlockPtr,
REG_BLOCK_SIZE,
&FileOffset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
NtClose(FileHandle);
return(Status);
}
}
NtClose(FileHandle);
/* Clear dirty flag */
RegistryHive->HiveDirty = FALSE;
DPRINT("CmiFlushRegistryHive() done\n");
return(STATUS_SUCCESS);
}
ULONG ULONG
CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive, CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive,
PKEY_CELL KeyCell) PKEY_CELL KeyCell)
@ -1188,7 +1312,6 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
&HashBlock, &HashBlock,
&KeyCell->HashTableOffset, &KeyCell->HashTableOffset,
REG_INIT_HASH_TABLE_SIZE); REG_INIT_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -1207,7 +1330,6 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive,
&HTOffset, &HTOffset,
HashBlock->HashTableSize + HashBlock->HashTableSize +
REG_EXTEND_HASH_TABLE_SIZE); REG_EXTEND_HASH_TABLE_SIZE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -1537,6 +1659,27 @@ CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive,
} }
NTSTATUS
CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive,
PHASH_TABLE_CELL HashBlock,
BLOCK_OFFSET NKBOffset)
{
ULONG i;
for (i = 0; i < HashBlock->HashTableSize; i++)
{
if (HashBlock->Table[i].KeyOffset == NKBOffset)
{
HashBlock->Table[i].KeyOffset = 0;
RtlZeroMemory(&HashBlock->Table[i].HashValue, 4);
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS NTSTATUS
CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
PVALUE_CELL *ValueCell, PVALUE_CELL *ValueCell,
@ -1677,6 +1820,17 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive,
/* Initialize a free block in this heap : */ /* Initialize a free block in this heap : */
tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET); tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET);
tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET); tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET);
/* Grow bitmap if necessary */
if (IsVolatileHive(RegistryHive) &&
(RegistryHive->BlockListSize % (sizeof(ULONG) * 8) == 0))
{
DPRINT1("Grow hive bitmap - BlockListSize %lu\n", RegistryHive->BlockListSize);
/* FIXME */
}
*NewBlock = (PVOID) tmpBlock; *NewBlock = (PVOID) tmpBlock;
if (NewBlockOffset) if (NewBlockOffset)
@ -1742,7 +1896,10 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin);
if (Temp) if (Temp)
{
ZwQuerySystemTime((PTIME) &pBin->DateModified); ZwQuerySystemTime((PTIME) &pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]);
}
if ((i + 1) < RegistryHive->FreeListSize) if ((i + 1) < RegistryHive->FreeListSize)
{ {
@ -1777,6 +1934,7 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive,
NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize);
NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize;
CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize);
CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize);
} }
else if (NewBlock->CellSize < BlockSize) else if (NewBlock->CellSize < BlockSize)
{ {
@ -1815,6 +1973,10 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
if (pFree->CellSize < 0) if (pFree->CellSize < 0)
pFree->CellSize = -pFree->CellSize; pFree->CellSize = -pFree->CellSize;
/* Clear block (except the block size) */
RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG),
pFree->CellSize - sizeof(ULONG));
CmiAddFree(RegistryHive, Block, Offset); CmiAddFree(RegistryHive, Block, Offset);
CmiReleaseBlock(RegistryHive, Block); CmiReleaseBlock(RegistryHive, Block);
@ -1822,6 +1984,8 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive,
if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin))
ZwQuerySystemTime((PTIME) &pBin->DateModified); ZwQuerySystemTime((PTIME) &pBin->DateModified);
CmiMarkBlockDirty(RegistryHive, Offset);
/* FIXME: Set first dword to block_offset of another free block ? */ /* FIXME: Set first dword to block_offset of another free block ? */
/* FIXME: Concatenate with previous and next block if free */ /* FIXME: Concatenate with previous and next block if free */
} }
@ -1872,10 +2036,12 @@ DPRINT("\n");
if (RegistryHive->FreeListMax) if (RegistryHive->FreeListMax)
{ {
DPRINT("\n"); DPRINT("\n");
RtlMoveMemory(tmpList, RegistryHive->FreeList, RtlMoveMemory(tmpList,
RegistryHive->FreeList,
sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax));
DPRINT("\n"); DPRINT("\n");
RtlMoveMemory(tmpListOffset, RegistryHive->FreeListOffset, RtlMoveMemory(tmpListOffset,
RegistryHive->FreeListOffset,
sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax));
DPRINT("\n"); DPRINT("\n");
ExFreePool(RegistryHive->FreeList); ExFreePool(RegistryHive->FreeList);
@ -1973,22 +2139,6 @@ CmiGetBlock(PREGISTRY_HIVE RegistryHive,
} }
VOID
CmiPrepareForWrite(PREGISTRY_HIVE RegistryHive,
PHBIN pBin)
{
if (IsVolatileHive(RegistryHive))
{
/* No need to do anything special for volatile hives */
return;
}
else
{
}
}
VOID VOID
CmiLockBlock(PREGISTRY_HIVE RegistryHive, CmiLockBlock(PREGISTRY_HIVE RegistryHive,
PVOID Block) PVOID Block)
@ -2011,6 +2161,26 @@ CmiReleaseBlock(PREGISTRY_HIVE RegistryHive,
} }
VOID
CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive,
BLOCK_OFFSET BlockOffset)
{
ULONG Index;
if (IsVolatileHive(RegistryHive))
return;
Index = (ULONG)BlockOffset / 4096;
DPRINT1("CmiMarkBlockDirty(Offset 0x%lx) Index %lu\n", (ULONG)BlockOffset, Index);
RegistryHive->HiveDirty = TRUE;
RtlSetBits(&RegistryHive->DirtyBitMap,
Index,
1);
}
ULONG ULONG
CmiGetPackedNameLength(IN PUNICODE_STRING Name, CmiGetPackedNameLength(IN PUNICODE_STRING Name,
OUT PBOOLEAN Packable) OUT PBOOLEAN Packable)
@ -2043,12 +2213,10 @@ CmiComparePackedNames(IN PUNICODE_STRING Name,
PWCHAR UNameBuffer; PWCHAR UNameBuffer;
ULONG i; ULONG i;
if (NamePacked) if (NamePacked == TRUE)
{ {
if (Name->Length != NameBufferSize * sizeof(WCHAR)) if (Name->Length != NameBufferSize * sizeof(WCHAR))
{
return(FALSE); return(FALSE);
}
for (i = 0; i < Name->Length / sizeof(WCHAR); i++) for (i = 0; i < Name->Length / sizeof(WCHAR); i++)
{ {

View file

@ -1,4 +1,4 @@
/* $Id: registry.c,v 1.81 2002/12/08 18:54:45 ekohl Exp $ /* $Id: registry.c,v 1.82 2003/02/09 11:57:14 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -659,7 +659,11 @@ CmiConnectHive(PWSTR FileName,
Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew); Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
KeBugCheck(0);
return(Status); return(Status);
}
RtlInitUnicodeString(&uKeyName, FullName); RtlInitUnicodeString(&uKeyName, FullName);
@ -675,7 +679,12 @@ CmiConnectHive(PWSTR FileName,
CmiKeyType, CmiKeyType,
(PVOID*)&NewKey); (PVOID*)&NewKey);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
DPRINT1("ObCreateObject() failed (Status %lx)\n", Status);
KeBugCheck(0);
CmiRemoveRegistryHive(RegistryHive);
return(Status); return(Status);
}
NewKey->RegistryHive = RegistryHive; NewKey->RegistryHive = RegistryHive;
NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell; NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell;
@ -731,7 +740,9 @@ CmiInitializeHive(PWSTR FileName,
//Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE); //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE);
Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew); Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status))
{
#if 0
#ifdef WIN32_REGDBG #ifdef WIN32_REGDBG
WCHAR AltFileName[MAX_PATH]; WCHAR AltFileName[MAX_PATH];
@ -749,6 +760,7 @@ CmiInitializeHive(PWSTR FileName,
CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName);
//DPRINT("Status %.08x\n", Status); //DPRINT("Status %.08x\n", Status);
} }
#endif
#endif #endif
} }
@ -865,7 +877,6 @@ CmiInitHives(BOOLEAN SetUpBoot)
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
return(Status); return(Status);
} }
//assert(NT_SUCCESS(Status));
/* Connect the SAM hive */ /* Connect the SAM hive */
wcscpy(EndPtr, REG_SAM_FILE_NAME); wcscpy(EndPtr, REG_SAM_FILE_NAME);
@ -881,7 +892,6 @@ CmiInitHives(BOOLEAN SetUpBoot)
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
return(Status); return(Status);
} }
//assert(NT_SUCCESS(Status));
/* Connect the SECURITY hive */ /* Connect the SECURITY hive */
wcscpy(EndPtr, REG_SEC_FILE_NAME); wcscpy(EndPtr, REG_SEC_FILE_NAME);
@ -896,7 +906,6 @@ CmiInitHives(BOOLEAN SetUpBoot)
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
return(Status); return(Status);
} }
//assert(NT_SUCCESS(Status));
/* Connect the DEFAULT hive */ /* Connect the DEFAULT hive */
wcscpy(EndPtr, REG_USER_FILE_NAME); wcscpy(EndPtr, REG_USER_FILE_NAME);
@ -912,7 +921,6 @@ CmiInitHives(BOOLEAN SetUpBoot)
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
return(Status); return(Status);
} }
//assert(NT_SUCCESS(Status));
/* FIXME : initialize standards symbolic links */ /* FIXME : initialize standards symbolic links */
@ -936,42 +944,41 @@ CmShutdownRegistry(VOID)
{ {
PREGISTRY_HIVE Hive; PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
KIRQL oldlvl; // KIRQL oldlvl;
DPRINT1("CmShutdownRegistry() called\n"); DPRINT1("CmShutdownRegistry() called\n");
/* Stop automatic hive synchronization */ /* Stop automatic hive synchronization */
CmiHiveSyncEnabled = FALSE; CmiHiveSyncEnabled = FALSE;
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl); // KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
Entry = CmiHiveListHead.Flink; Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead) while (Entry != &CmiHiveListHead)
{ {
Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
if (Hive->Flags & HIVE_VOLATILE) if (IsPermanentHive(Hive))
{ {
DPRINT("Volatile hive\n"); /* Acquire hive resource exclusively */
} ExAcquireResourceExclusiveLite(&Hive->HiveResource,
else TRUE);
{
DPRINT("Flush non-volatile hive '%wZ'\n", &Hive->Filename);
/* Flush non-volatile hive */ /* Flush non-volatile hive */
CmiFlushRegistryHive(Hive);
/* Dereference file */ /* Dereference file */
ObDereferenceObject(Hive->FileObject); ObDereferenceObject(Hive->FileObject);
Hive->FileObject = NULL; Hive->FileObject = NULL;
/* Release hive resource */
ExReleaseResourceLite(&Hive->HiveResource);
} }
Entry = Entry->Flink; Entry = Entry->Flink;
} }
KeReleaseSpinLock(&CmiHiveListLock,oldlvl); // KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
/* Note: DPRINT1("CmShutdownRegistry() called\n");
* Don't call UNIMPLEMENTED() here since this function is
* called by NtShutdownSystem().
*/
} }
@ -981,9 +988,36 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc,
PVOID SystemArgument1, PVOID SystemArgument1,
PVOID SystemArgument2) PVOID SystemArgument2)
{ {
DPRINT("CmiHiveSyncDpcRoutine() called\n"); PREGISTRY_HIVE Hive;
PLIST_ENTRY Entry;
KIRQL oldlvl;
DPRINT1("CmiHiveSyncDpcRoutine() called\n");
CmiHiveSyncPending = FALSE; CmiHiveSyncPending = FALSE;
KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
Entry = CmiHiveListHead.Flink;
while (Entry != &CmiHiveListHead)
{
Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
if (IsPermanentHive(Hive))
{
/* Acquire hive resource exclusively */
ExAcquireResourceExclusiveLite(&Hive->HiveResource,
TRUE);
/* Flush non-volatile hive */
CmiFlushRegistryHive(Hive);
/* Release hive resource */
ExReleaseResourceLite(&Hive->HiveResource);
}
Entry = Entry->Flink;
}
KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
} }
@ -992,6 +1026,8 @@ CmiSyncHives(VOID)
{ {
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
DPRINT("CmiSyncHives() called\n");
if (CmiHiveSyncEnabled == FALSE || if (CmiHiveSyncEnabled == FALSE ||
CmiHiveSyncPending == TRUE) CmiHiveSyncPending == TRUE)
return; return;

View file

@ -277,10 +277,36 @@ CmiObjectDelete(PVOID DeletedObject)
if (KeyObject->Flags & KO_MARKED_FOR_DELETE) if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
{ {
PHASH_TABLE_CELL HashBlock;
DPRINT("delete really key\n"); DPRINT("delete really key\n");
/* FIXME: Destroy the key's hash block */
/* Remove the key from the parent key's hash block */
HashBlock = CmiGetBlock(KeyObject->RegistryHive,
KeyObject->ParentKey->KeyCell->HashTableOffset, NULL);
DPRINT1("HashBlock %p\n", HashBlock);
if (HashBlock != NULL)
{
CmiRemoveKeyFromHashTable(KeyObject->RegistryHive,
HashBlock,
KeyObject->BlockOffset);
CmiMarkBlockDirty(KeyObject->RegistryHive,
KeyObject->ParentKey->KeyCell->HashTableOffset);
}
/* Remove the key from the parent key's hash block */
KeyObject->ParentKey->KeyCell->NumberOfSubKeys--;
CmiMarkBlockDirty(KeyObject->RegistryHive,
KeyObject->ParentKey->BlockOffset);
/* Destroy key cell */
CmiDestroyBlock(KeyObject->RegistryHive, CmiDestroyBlock(KeyObject->RegistryHive,
KeyObject->KeyCell, KeyObject->KeyCell,
KeyObject->BlockOffset); KeyObject->BlockOffset);
if (IsPermanentHive(KeyObject->RegistryHive))
CmiSyncHives();
} }
else else
{ {