diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index ffcd26cc284..07cb91933d3 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -55,7 +55,7 @@ #define MAX_REG_STD_HANDLE_NAME 19 // BLOCK_OFFSET = offset in file after header block -typedef DWORD BLOCK_OFFSET; +typedef ULONG BLOCK_OFFSET; /* header for registry hive file : */ typedef struct _HIVE_HEADER @@ -256,6 +256,9 @@ typedef struct _REGISTRY_HIVE BLOCK_OFFSET *FreeListOffset; ERESOURCE HiveResource; + RTL_BITMAP DirtyBitMap; + BOOLEAN HiveDirty; + // NTSTATUS (*Extend)(ULONG NewSize); // PVOID (*Flush)(VOID); } REGISTRY_HIVE, *PREGISTRY_HIVE; @@ -396,6 +399,9 @@ CmiCreateRegistryHive(PWSTR Filename, NTSTATUS CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive); +NTSTATUS +CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive); + ULONG CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell); @@ -473,6 +479,11 @@ CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, PKEY_CELL NewKeyCell, BLOCK_OFFSET NKBOffset); +NTSTATUS +CmiRemoveKeyFromHashTable(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + BLOCK_OFFSET NKBOffset); + NTSTATUS CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, OUT PVALUE_CELL *ValueCell, @@ -497,8 +508,8 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, PVOID CmiGetBlock(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BlockOffset, - OUT PHBIN * ppBin); + BLOCK_OFFSET BlockOffset, + OUT PHBIN * ppBin); VOID CmiLockBlock(PREGISTRY_HIVE RegistryHive, @@ -506,7 +517,11 @@ CmiLockBlock(PREGISTRY_HIVE RegistryHive, VOID CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, - PVOID Block); + PVOID Block); + +VOID +CmiMarkBlockDirty(PREGISTRY_HIVE RegistryHive, + BLOCK_OFFSET BlockOffset); NTSTATUS CmiAddFree(PREGISTRY_HIVE RegistryHive, diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index bb11ab4cb32..253e11b03c6 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -112,7 +112,6 @@ NtCreateKey(OUT PHANDLE KeyHandle, NULL, CmiKeyType, (PVOID*)&KeyObject); - if (!NT_SUCCESS(Status)) { return(Status); @@ -142,7 +141,6 @@ NtCreateKey(OUT PHANDLE KeyHandle, TitleIndex, Class, CreateOptions); - if (!NT_SUCCESS(Status)) { ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); @@ -200,15 +198,14 @@ NtDeleteKey(IN HANDLE KeyHandle) /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_WRITE, - CmiKeyType, - UserMode, - (PVOID *) &KeyObject, - NULL); - + KEY_WRITE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); if (!NT_SUCCESS(Status)) { - return Status; + return(Status); } /* Acquire hive lock */ @@ -219,21 +216,26 @@ NtDeleteKey(IN HANDLE KeyHandle) /* Set the marked for delete bit in the key object */ KeyObject->Flags |= KO_MARKED_FOR_DELETE; + /* Release hive lock */ + ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); + + DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); + /* Dereference the object */ ObDereferenceObject(KeyObject); if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive) ObDereferenceObject(KeyObject); - /* Close the handle */ - ObDeleteHandle(PsGetCurrentProcess(), KeyHandle); - /* FIXME: I think that ObDeleteHandle should dereference the object */ - ObDereferenceObject(KeyObject); - /* Release hive lock */ - ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); + DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject)); - 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; PKEY_OBJECT KeyObject; PREGISTRY_HIVE RegistryHive; +#if 0 WCHAR LogName[MAX_PATH]; UNICODE_STRING TmpFileName; HANDLE FileHandle; @@ -686,29 +689,42 @@ NtFlushKey(IN HANDLE KeyHandle) LARGE_INTEGER fileOffset; DWORD * pEntDword; ULONG i; +#endif DPRINT("KeyHandle %x\n", KeyHandle); /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, - KEY_QUERY_VALUE, - CmiKeyType, - UserMode, - (PVOID *) &KeyObject, - NULL); - + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); if (!NT_SUCCESS(Status)) { - return Status; + return(Status); } - /* Acquire hive lock */ - ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE); - VERIFY_KEY_OBJECT(KeyObject); 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 */ wcscpy(LogName,RegistryHive->Filename.Buffer); wcscat(LogName,L".log"); @@ -891,8 +907,12 @@ END FIXME*/ } ZwClose(FileHandle); - ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); +#endif + + ExReleaseResourceLite(&RegistryHive->HiveResource); + ObDereferenceObject(KeyObject); + return STATUS_SUCCESS; } @@ -1424,6 +1444,7 @@ NtSetValueKey(IN HANDLE KeyHandle, { /* If new data size is <= current then overwrite current data */ DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); + RtlZeroMemory(DataCell->Data, ValueCell->DataSize); RtlCopyMemory(DataCell->Data, Data, DataSize); ValueCell->DataSize = DataSize; ValueCell->DataType = Type; diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index b3d5fbf28e8..a3f58982b27 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -24,10 +24,12 @@ #include "cm.h" #endif - +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) BOOLEAN CmiDoVerify = FALSE; +/* FUNCTIONS ****************************************************************/ + VOID CmiCreateDefaultHiveHeader(PHIVE_HEADER Header) { @@ -366,7 +368,7 @@ CmiPopulateHive(HANDLE FileHandle) PHBIN BinCell; PCHAR tBuf; ULONG i; - + tBuf = (PCHAR) ExAllocatePool(NonPagedPool, REG_BLOCK_SIZE); if (tBuf == NULL) return STATUS_INSUFFICIENT_RESOURCES; @@ -390,14 +392,14 @@ CmiPopulateHive(HANDLE FileHandle) FileOffset.u.LowPart = (2 + i) * REG_BLOCK_SIZE; Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - tBuf, - REG_BLOCK_SIZE, - &FileOffset, - NULL); + NULL, + NULL, + NULL, + &IoStatusBlock, + tBuf, + REG_BLOCK_SIZE, + &FileOffset, + NULL); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); if (!NT_SUCCESS(Status)) { @@ -421,48 +423,48 @@ CmiCreateNewRegFile(HANDLE FileHandle) PKEY_CELL RootKeyCell; NTSTATUS Status; PHBIN BinCell; - PCHAR tBuf; - - tBuf = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); - if (tBuf == NULL) + PCHAR Buffer; + + Buffer = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); + if (Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; - - HiveHeader = (PHIVE_HEADER) tBuf; - BinCell = (PHBIN) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE); - RootKeyCell = (PKEY_CELL) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET); - FreeCell = (PCELL_HEADER) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); + + HiveHeader = (PHIVE_HEADER)Buffer; + BinCell = (PHBIN)((ULONG_PTR)Buffer + REG_BLOCK_SIZE); + RootKeyCell = (PKEY_CELL)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET); + FreeCell = (PCELL_HEADER)((ULONG_PTR)Buffer + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); CmiCreateDefaultHiveHeader(HiveHeader); CmiCreateDefaultBinCell(BinCell); CmiCreateDefaultRootKeyCell(RootKeyCell); - // First block + /* First block */ BinCell->BlockOffset = 0; - // Offset to root key block + /* Offset to root key block */ 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)); Status = ZwWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - tBuf, - 2 * REG_BLOCK_SIZE, - 0, - NULL); + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + 2 * REG_BLOCK_SIZE, + 0, + NULL); - ExFreePool(tBuf); + ExFreePool(Buffer); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); #if 1 if (NT_SUCCESS(Status)) { - CmiPopulateHive(FileHandle); + CmiPopulateHive(FileHandle); } #endif @@ -472,8 +474,8 @@ CmiCreateNewRegFile(HANDLE FileHandle) NTSTATUS CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, - PWSTR Filename, - BOOLEAN CreateNew) + PWSTR Filename, + BOOLEAN CreateNew) { OBJECT_ATTRIBUTES ObjectAttributes; FILE_STANDARD_INFORMATION fsi; @@ -487,16 +489,18 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, NTSTATUS Status; PHBIN tmpBin; 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 */ Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename); if (!NT_SUCCESS(Status)) - { - DPRINT("CmiInitPermanentRegistryHive() - Failed 1.\n"); - return Status; - } + { + DPRINT1("CmiInitPermanentRegistryHive() - Failed 1.\n"); + return Status; + } InitializeObjectAttributes(&ObjectAttributes, &RegistryHive->Filename, @@ -504,7 +508,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, NULL, NULL); - if (CreateNew) + if (CreateNew == TRUE) CreateDisposition = FILE_OPEN_IF; else CreateDisposition = FILE_OPEN; @@ -532,18 +536,18 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, Status = CmiCreateNewRegFile(FileHandle); if (!NT_SUCCESS(Status)) { + DPRINT1("CmiCreateNewRegFile() failed (Status %lx)\n", Status); RtlFreeUnicodeString(&RegistryHive->Filename); - DPRINT1("CmiCreateNewRegFile() - Failed with status %x.\n", Status); return(Status); } } Status = ObReferenceObjectByHandle(FileHandle, - FILE_ALL_ACCESS, - IoFileObjectType, - UserMode, - (PVOID*) &RegistryHive->FileObject, - NULL); + FILE_ALL_ACCESS, + IoFileObjectType, + UserMode, + (PVOID*)&RegistryHive->FileObject, + NULL); assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); @@ -551,10 +555,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, { NtClose(FileHandle); RtlFreeUnicodeString(&RegistryHive->Filename); - DPRINT("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status); + DPRINT1("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status); return Status; } + /* Read hive header */ FileOffset.u.HighPart = 0; FileOffset.u.LowPart = 0; 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), &FileOffset, 0); - assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); - if (!NT_SUCCESS(Status)) { ObDereferenceObject(RegistryHive->FileObject); @@ -744,7 +747,21 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, 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); } @@ -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 CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell) @@ -1139,33 +1263,33 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, } else { - NewKeyCell->Id = REG_KEY_CELL_ID; - NewKeyCell->Type = REG_KEY_CELL_TYPE; - ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime); - NewKeyCell->ParentKeyOffset = -1; - NewKeyCell->NumberOfSubKeys = 0; - NewKeyCell->HashTableOffset = -1; - NewKeyCell->NumberOfValues = 0; - NewKeyCell->ValuesOffset = -1; - NewKeyCell->SecurityKeyOffset = -1; - NewKeyCell->NameSize = NameSize; - wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize); - NewKeyCell->ClassNameOffset = -1; + NewKeyCell->Id = REG_KEY_CELL_ID; + NewKeyCell->Type = REG_KEY_CELL_TYPE; + ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime); + NewKeyCell->ParentKeyOffset = -1; + NewKeyCell->NumberOfSubKeys = 0; + NewKeyCell->HashTableOffset = -1; + NewKeyCell->NumberOfValues = 0; + NewKeyCell->ValuesOffset = -1; + NewKeyCell->SecurityKeyOffset = -1; + NewKeyCell->NameSize = NameSize; + wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize); + NewKeyCell->ClassNameOffset = -1; VERIFY_KEY_CELL(NewKeyCell); - if (Class) - { - PDATA_CELL pClass; + if (Class) + { + PDATA_CELL pClass; - NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR); - Status = CmiAllocateBlock(RegistryHive, - (PVOID) &pClass, - NewKeyCell->ClassSize, - &NewKeyCell->ClassNameOffset); - wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length); - ((PWSTR) (pClass->Data))[Class->Length] = 0; - } + NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR); + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &pClass, + NewKeyCell->ClassSize, + &NewKeyCell->ClassNameOffset); + wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length); + ((PWSTR) (pClass->Data))[Class->Length] = 0; + } } if (!NT_SUCCESS(Status)) @@ -1178,17 +1302,16 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, /* Don't modify hash table if key is volatile and parent is not */ if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive))) - { - return Status; - } + { + return Status; + } if (KeyCell->HashTableOffset == (ULONG_PTR) -1) { Status = CmiAllocateHashTableBlock(RegistryHive, - &HashBlock, - &KeyCell->HashTableOffset, - REG_INIT_HASH_TABLE_SIZE); - + &HashBlock, + &KeyCell->HashTableOffset, + REG_INIT_HASH_TABLE_SIZE); if (!NT_SUCCESS(Status)) { return Status; @@ -1199,19 +1322,18 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) { - BLOCK_OFFSET HTOffset; + BLOCK_OFFSET HTOffset; - /* Reallocate the hash table block */ - Status = CmiAllocateHashTableBlock(RegistryHive, - &NewHashBlock, - &HTOffset, - HashBlock->HashTableSize + - REG_EXTEND_HASH_TABLE_SIZE); - - if (!NT_SUCCESS(Status)) - { - return Status; - } + /* Reallocate the hash table block */ + Status = CmiAllocateHashTableBlock(RegistryHive, + &NewHashBlock, + &HTOffset, + HashBlock->HashTableSize + + REG_EXTEND_HASH_TABLE_SIZE); + if (!NT_SUCCESS(Status)) + { + return Status; + } RtlZeroMemory(&NewHashBlock->Table[0], sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); @@ -1470,9 +1592,9 @@ CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, NewHashSize = sizeof(HASH_TABLE_CELL) + (HashTableSize - 1) * sizeof(HASH_RECORD); Status = CmiAllocateBlock(RegistryHive, - (PVOID*) &NewHashBlock, - NewHashSize, - HBOffset); + (PVOID*) &NewHashBlock, + NewHashSize, + HBOffset); if ((NewHashBlock == NULL) || (!NT_SUCCESS(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 CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, PVALUE_CELL *ValueCell, @@ -1677,6 +1820,17 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive, /* Initialize a free block in this heap : */ tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + 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; if (NewBlockOffset) @@ -1742,7 +1896,10 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); if (Temp) - ZwQuerySystemTime((PTIME) &pBin->DateModified); + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]); + } if ((i + 1) < RegistryHive->FreeListSize) { @@ -1777,6 +1934,7 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); + CmiMarkBlockDirty(RegistryHive, *pBlockOffset + BlockSize); } else if (NewBlock->CellSize < BlockSize) { @@ -1815,6 +1973,10 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, if (pFree->CellSize < 0) pFree->CellSize = -pFree->CellSize; + /* Clear block (except the block size) */ + RtlZeroMemory(((PVOID)pFree) + sizeof(ULONG), + pFree->CellSize - sizeof(ULONG)); + CmiAddFree(RegistryHive, Block, Offset); CmiReleaseBlock(RegistryHive, Block); @@ -1822,6 +1984,8 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) ZwQuerySystemTime((PTIME) &pBin->DateModified); + CmiMarkBlockDirty(RegistryHive, Offset); + /* FIXME: Set first dword to block_offset of another free block ? */ /* FIXME: Concatenate with previous and next block if free */ } @@ -1872,74 +2036,76 @@ DPRINT("\n"); if (RegistryHive->FreeListMax) { DPRINT("\n"); - RtlMoveMemory(tmpList, RegistryHive->FreeList, - sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); + RtlMoveMemory(tmpList, + RegistryHive->FreeList, + sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); DPRINT("\n"); - RtlMoveMemory(tmpListOffset, RegistryHive->FreeListOffset, - sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); + RtlMoveMemory(tmpListOffset, + RegistryHive->FreeListOffset, + sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); DPRINT("\n"); - ExFreePool(RegistryHive->FreeList); + ExFreePool(RegistryHive->FreeList); DPRINT("\n"); - ExFreePool(RegistryHive->FreeListOffset); + ExFreePool(RegistryHive->FreeListOffset); DPRINT("\n"); - } + } DPRINT("\n"); - RegistryHive->FreeList = tmpList; - RegistryHive->FreeListOffset = tmpListOffset; - RegistryHive->FreeListMax += 32; + RegistryHive->FreeList = tmpList; + RegistryHive->FreeListOffset = tmpListOffset; + RegistryHive->FreeListMax += 32; DPRINT("\n"); - } + } DPRINT("\n"); - /* Add new offset to free list, maintaining list in ascending order */ - if ((RegistryHive->FreeListSize == 0) - || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) - { + /* Add new offset to free list, maintaining list in ascending order */ + if ((RegistryHive->FreeListSize == 0) + || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) + { DPRINT("\n"); - /* Add to end of list */ - RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock; - RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset; - } - else if (RegistryHive->FreeListOffset[0] > FreeOffset) - { + /* Add to end of list */ + RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock; + RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset; + } + else if (RegistryHive->FreeListOffset[0] > FreeOffset) + { DPRINT("\n"); - /* Add to begin of list */ - RtlMoveMemory(&RegistryHive->FreeList[1], - &RegistryHive->FreeList[0], - sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize); - RtlMoveMemory(&RegistryHive->FreeListOffset[1], - &RegistryHive->FreeListOffset[0], - sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize); - RegistryHive->FreeList[0] = FreeBlock; - RegistryHive->FreeListOffset[0] = FreeOffset; - RegistryHive->FreeListSize++; - } + /* Add to begin of list */ + RtlMoveMemory(&RegistryHive->FreeList[1], + &RegistryHive->FreeList[0], + sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize); + RtlMoveMemory(&RegistryHive->FreeListOffset[1], + &RegistryHive->FreeListOffset[0], + sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize); + RegistryHive->FreeList[0] = FreeBlock; + RegistryHive->FreeListOffset[0] = FreeOffset; + RegistryHive->FreeListSize++; + } + else + { +DPRINT("\n"); + /* Search where to insert */ + minInd = 0; + maxInd = RegistryHive->FreeListSize - 1; + while ((maxInd - minInd) > 1) + { + medInd = (minInd + maxInd) / 2; + if (RegistryHive->FreeListOffset[medInd] > FreeOffset) + maxInd = medInd; else - { -DPRINT("\n"); - /* Search where to insert */ - minInd = 0; - maxInd = RegistryHive->FreeListSize - 1; - while ((maxInd - minInd) > 1) - { - medInd = (minInd + maxInd) / 2; - if (RegistryHive->FreeListOffset[medInd] > FreeOffset) - maxInd = medInd; - else - minInd = medInd; - } + minInd = medInd; + } - /* Insert before maxInd */ - RtlMoveMemory(&RegistryHive->FreeList[maxInd+1], - &RegistryHive->FreeList[maxInd], + /* Insert before maxInd */ + RtlMoveMemory(&RegistryHive->FreeList[maxInd+1], + &RegistryHive->FreeList[maxInd], sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd)); - RtlMoveMemory(&RegistryHive->FreeListOffset[maxInd + 1], + RtlMoveMemory(&RegistryHive->FreeListOffset[maxInd + 1], &RegistryHive->FreeListOffset[maxInd], sizeof(RegistryHive->FreeListOffset[0]) * (RegistryHive->FreeListSize-minInd)); - RegistryHive->FreeList[maxInd] = FreeBlock; - RegistryHive->FreeListOffset[maxInd] = FreeOffset; - RegistryHive->FreeListSize++; - } + RegistryHive->FreeList[maxInd] = FreeBlock; + RegistryHive->FreeListOffset[maxInd] = FreeOffset; + RegistryHive->FreeListSize++; + } DPRINT("\n"); return STATUS_SUCCESS; @@ -1948,8 +2114,8 @@ DPRINT("\n"); PVOID CmiGetBlock(PREGISTRY_HIVE RegistryHive, - BLOCK_OFFSET BlockOffset, - PHBIN * ppBin) + BLOCK_OFFSET BlockOffset, + PHBIN * ppBin) { if (ppBin) *ppBin = NULL; @@ -1973,25 +2139,9 @@ 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 CmiLockBlock(PREGISTRY_HIVE RegistryHive, - PVOID Block) + PVOID Block) { if (IsPermanentHive(RegistryHive)) { @@ -2002,7 +2152,7 @@ CmiLockBlock(PREGISTRY_HIVE RegistryHive, VOID CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, - PVOID Block) + PVOID Block) { if (IsPermanentHive(RegistryHive)) { @@ -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 CmiGetPackedNameLength(IN PUNICODE_STRING Name, OUT PBOOLEAN Packable) @@ -2043,12 +2213,10 @@ CmiComparePackedNames(IN PUNICODE_STRING Name, PWCHAR UNameBuffer; ULONG i; - if (NamePacked) + if (NamePacked == TRUE) { if (Name->Length != NameBufferSize * sizeof(WCHAR)) - { return(FALSE); - } for (i = 0; i < Name->Length / sizeof(WCHAR); i++) { diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index dafe2dd9b34..9d34381b656 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -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 * PROJECT: ReactOS kernel @@ -659,7 +659,11 @@ CmiConnectHive(PWSTR FileName, Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew); if (!NT_SUCCESS(Status)) - return(Status); + { + DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status); + KeBugCheck(0); + return(Status); + } RtlInitUnicodeString(&uKeyName, FullName); @@ -675,7 +679,12 @@ CmiConnectHive(PWSTR FileName, CmiKeyType, (PVOID*)&NewKey); if (!NT_SUCCESS(Status)) - return(Status); + { + DPRINT1("ObCreateObject() failed (Status %lx)\n", Status); + KeBugCheck(0); + CmiRemoveRegistryHive(RegistryHive); + return(Status); + } NewKey->RegistryHive = RegistryHive; 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, CreateNew); - if (!NT_SUCCESS(Status)) { + if (!NT_SUCCESS(Status)) + { +#if 0 #ifdef WIN32_REGDBG WCHAR AltFileName[MAX_PATH]; @@ -749,6 +760,7 @@ CmiInitializeHive(PWSTR FileName, CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); //DPRINT("Status %.08x\n", Status); } +#endif #endif } @@ -865,7 +877,6 @@ CmiInitHives(BOOLEAN SetUpBoot) DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); return(Status); } - //assert(NT_SUCCESS(Status)); /* Connect the SAM hive */ wcscpy(EndPtr, REG_SAM_FILE_NAME); @@ -881,7 +892,6 @@ CmiInitHives(BOOLEAN SetUpBoot) DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); return(Status); } - //assert(NT_SUCCESS(Status)); /* Connect the SECURITY hive */ wcscpy(EndPtr, REG_SEC_FILE_NAME); @@ -896,7 +906,6 @@ CmiInitHives(BOOLEAN SetUpBoot) DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); return(Status); } - //assert(NT_SUCCESS(Status)); /* Connect the DEFAULT hive */ wcscpy(EndPtr, REG_USER_FILE_NAME); @@ -912,7 +921,6 @@ CmiInitHives(BOOLEAN SetUpBoot) DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status); return(Status); } - //assert(NT_SUCCESS(Status)); /* FIXME : initialize standards symbolic links */ @@ -936,42 +944,41 @@ CmShutdownRegistry(VOID) { PREGISTRY_HIVE Hive; PLIST_ENTRY Entry; - KIRQL oldlvl; +// KIRQL oldlvl; DPRINT1("CmShutdownRegistry() called\n"); /* Stop automatic hive synchronization */ CmiHiveSyncEnabled = FALSE; - KeAcquireSpinLock(&CmiHiveListLock,&oldlvl); +// KeAcquireSpinLock(&CmiHiveListLock,&oldlvl); Entry = CmiHiveListHead.Flink; while (Entry != &CmiHiveListHead) - { - Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); - - if (Hive->Flags & HIVE_VOLATILE) { - DPRINT("Volatile hive\n"); + Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList); + + if (IsPermanentHive(Hive)) + { + /* Acquire hive resource exclusively */ + ExAcquireResourceExclusiveLite(&Hive->HiveResource, + TRUE); + + /* Flush non-volatile hive */ + CmiFlushRegistryHive(Hive); + + /* Dereference file */ + ObDereferenceObject(Hive->FileObject); + Hive->FileObject = NULL; + + /* Release hive resource */ + ExReleaseResourceLite(&Hive->HiveResource); + } + + Entry = Entry->Flink; } - else - { - DPRINT("Flush non-volatile hive '%wZ'\n", &Hive->Filename); +// KeReleaseSpinLock(&CmiHiveListLock,oldlvl); - /* Flush non-volatile hive */ - - /* Dereference file */ - ObDereferenceObject(Hive->FileObject); - Hive->FileObject = NULL; - } - - Entry = Entry->Flink; - } - KeReleaseSpinLock(&CmiHiveListLock,oldlvl); - - /* Note: - * Don't call UNIMPLEMENTED() here since this function is - * called by NtShutdownSystem(). - */ + DPRINT1("CmShutdownRegistry() called\n"); } @@ -981,9 +988,36 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc, PVOID SystemArgument1, PVOID SystemArgument2) { - DPRINT("CmiHiveSyncDpcRoutine() called\n"); + PREGISTRY_HIVE Hive; + PLIST_ENTRY Entry; + KIRQL oldlvl; + + DPRINT1("CmiHiveSyncDpcRoutine() called\n"); 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; + DPRINT("CmiSyncHives() called\n"); + if (CmiHiveSyncEnabled == FALSE || CmiHiveSyncPending == TRUE) return; diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index 120cf198c32..ec704c516b0 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -277,10 +277,36 @@ CmiObjectDelete(PVOID DeletedObject) if (KeyObject->Flags & KO_MARKED_FOR_DELETE) { + PHASH_TABLE_CELL HashBlock; + 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, KeyObject->KeyCell, KeyObject->BlockOffset); + if (IsPermanentHive(KeyObject->RegistryHive)) + CmiSyncHives(); } else {