From d608e437c997f4399d5563455ae8c2162ca9ec52 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 30 Nov 2002 14:46:27 +0000 Subject: [PATCH] Implemented packing of value names svn path=/trunk/; revision=3811 --- reactos/ntoskrnl/cm/cm.h | 44 +++- reactos/ntoskrnl/cm/ntfunc.c | 329 +++++++++++++++++------------- reactos/ntoskrnl/cm/regfile.c | 358 +++++++++++++++++++++------------ reactos/ntoskrnl/cm/registry.c | 39 ++-- reactos/ntoskrnl/cm/regobj.c | 10 +- reactos/ntoskrnl/cm/rtlfunc.c | 5 + 6 files changed, 492 insertions(+), 293 deletions(-) diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index 3799acc8316..83645854ce6 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -42,9 +42,6 @@ #define REG_KEY_CELL_ID 0x6b6e #define REG_HASH_TABLE_BLOCK_ID 0x666c #define REG_VALUE_CELL_ID 0x6b76 -#define REG_LINK_KEY_CELL_TYPE 0x10 -#define REG_KEY_CELL_TYPE 0x20 -#define REG_ROOT_KEY_CELL_TYPE 0x2c #define REG_HIVE_ID 0x66676572 #define REGISTRY_FILE_MAGIC "REGEDIT4" @@ -191,6 +188,12 @@ typedef struct _KEY_CELL UCHAR Name[0]; } __attribute__((packed)) KEY_CELL, *PKEY_CELL; +/* KEY_CELL.Type constants */ +#define REG_LINK_KEY_CELL_TYPE 0x10 +#define REG_KEY_CELL_TYPE 0x20 +#define REG_ROOT_KEY_CELL_TYPE 0x2c + + // hash record : // HashValue=four letters of value's name typedef struct _HASH_RECORD @@ -226,6 +229,10 @@ typedef struct _VALUE_CELL UCHAR Name[0]; /* warning : not zero terminated */ } __attribute__((packed)) VALUE_CELL, *PVALUE_CELL; +/* VALUE_CELL.Flags constants */ +#define REG_VALUE_NAME_PACKED 0x0001 + + typedef struct _DATA_CELL { LONG CellSize; @@ -427,7 +434,7 @@ CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, NTSTATUS CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueName, + IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *ValueCell, OUT BLOCK_OFFSET *VBOffset); @@ -440,14 +447,14 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, NTSTATUS CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueNameBuf, - OUT PVALUE_CELL *pValueCell, - OUT BLOCK_OFFSET *pVBOffset); + IN PUNICODE_STRING ValueName, + OUT PVALUE_CELL *pValueCell, + OUT BLOCK_OFFSET *pVBOffset); NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueName); + IN PUNICODE_STRING ValueName); NTSTATUS CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, @@ -468,9 +475,9 @@ CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, NTSTATUS CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, - OUT PVALUE_CELL *ValueCell, - OUT BLOCK_OFFSET *VBOffset, - IN PCHAR ValueNameBuf); + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset, + IN PUNICODE_STRING ValueName); NTSTATUS CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, @@ -509,4 +516,19 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive, NTSTATUS CmiInitHives(BOOLEAN SetUpBoot); +ULONG +CmiGetPackedNameLength(IN PUNICODE_STRING Name, + OUT PBOOLEAN Packable); + +BOOLEAN +CmiComparePackedNames(IN PUNICODE_STRING Name, + IN PCHAR NameBuffer, + IN USHORT NameBufferSize, + IN BOOLEAN NamePacked); + +VOID +CmiCopyPackedName(PWCHAR NameBuffer, + PCHAR PackedNameBuffer, + ULONG PackedNameSize); + #endif /*__INCLUDE_CM_H*/ diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index dd9d8ea7832..71ede9d9b8d 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -515,8 +515,16 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, switch (KeyValueInformationClass) { case KeyValueBasicInformation: - *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + - (ValueCell->NameSize + 1) * sizeof(WCHAR); + if (ValueCell->Flags & REG_VALUE_NAME_PACKED) + { + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + (ValueCell->NameSize + 1) * sizeof(WCHAR); + } + else + { + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + ValueCell->NameSize + sizeof(WCHAR); + } if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -527,12 +535,24 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, KeyValueInformation; ValueBasicInformation->TitleIndex = 0; ValueBasicInformation->Type = ValueCell->DataType; - ValueBasicInformation->NameLength = - (ValueCell->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueBasicInformation->Name, - ValueCell->Name, - ValueCell->NameSize * 2); - ValueBasicInformation->Name[ValueCell->NameSize] = 0; + if (ValueCell->Flags & REG_VALUE_NAME_PACKED) + { + ValueBasicInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + CmiCopyPackedName(ValueBasicInformation->Name, + ValueCell->Name, + ValueCell->NameSize); + ValueBasicInformation->Name[ValueCell->NameSize] = 0; + } + else + { + ValueBasicInformation->NameLength = + ValueCell->NameSize + sizeof(WCHAR); + RtlCopyMemory(ValueBasicInformation->Name, + ValueCell->Name, + ValueCell->NameSize * sizeof(WCHAR)); + ValueBasicInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0; + } } break; @@ -569,8 +589,18 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, break; case KeyValueFullInformation: - *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + - ValueCell->NameSize * sizeof(WCHAR) + (ValueCell->DataSize & LONG_MAX); + if (ValueCell->Flags & REG_VALUE_NAME_PACKED) + { + *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + + (ValueCell->NameSize + 1) * sizeof(WCHAR) + + (ValueCell->DataSize & LONG_MAX); + } + else + { + *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + + ValueCell->NameSize + sizeof(WCHAR) + + (ValueCell->DataSize & LONG_MAX); + } if (Length < *ResultLength) { Status = STATUS_BUFFER_OVERFLOW; @@ -581,34 +611,56 @@ NtEnumerateValueKey(IN HANDLE KeyHandle, KeyValueInformation; ValueFullInformation->TitleIndex = 0; ValueFullInformation->Type = ValueCell->DataType; - ValueFullInformation->DataOffset = - (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation - + (ValueCell->NameSize + 1) * sizeof(WCHAR); - ValueFullInformation->DataOffset = - (ValueFullInformation->DataOffset + 3) & 0xfffffffc; - ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; - ValueFullInformation->NameLength = - (ValueCell->NameSize + 1) * sizeof(WCHAR); - mbstowcs(ValueFullInformation->Name, - ValueCell->Name, - ValueCell->NameSize * 2); - ValueFullInformation->Name[ValueCell->NameSize] = 0; - if (ValueCell->DataSize > 0) - { - DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); - RtlCopyMemory((PCHAR) ValueFullInformation - + ValueFullInformation->DataOffset, - DataCell->Data, - ValueCell->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryHive, DataCell); - } + if (ValueCell->Flags & REG_VALUE_NAME_PACKED) + { + ValueFullInformation->DataOffset = + (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation + + (ValueCell->NameSize + 1) * sizeof(WCHAR); + } else - { - RtlCopyMemory((PCHAR) ValueFullInformation - + ValueFullInformation->DataOffset, - &ValueCell->DataOffset, - ValueCell->DataSize & LONG_MAX); - } + { + ValueFullInformation->DataOffset = + (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation + + ValueCell->NameSize + sizeof(WCHAR); + } + ValueFullInformation->DataOffset = + (ValueFullInformation->DataOffset + 3) & 0xfffffffc; + ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; + if (ValueCell->Flags & REG_VALUE_NAME_PACKED) + { + ValueFullInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + + CmiCopyPackedName(ValueFullInformation->Name, + ValueCell->Name, + ValueCell->NameSize); + ValueFullInformation->Name[ValueCell->NameSize] = 0; + } + else + { + ValueFullInformation->NameLength = + ValueCell->NameSize + sizeof(WCHAR); + RtlCopyMemory(ValueFullInformation->Name, + ValueCell->Name, + ValueCell->NameSize); + ValueFullInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0; + } + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } } break; } @@ -859,7 +911,7 @@ NtOpenKey(OUT PHANDLE KeyHandle, NTSTATUS Status; PVOID Object; - DPRINT("KH %x DA %x OA %x OA->ON %x\n", + DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n", KeyHandle, DesiredAccess, ObjectAttributes, @@ -877,7 +929,7 @@ NtOpenKey(OUT PHANDLE KeyHandle, VERIFY_KEY_OBJECT((PKEY_OBJECT) Object); - DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer); + DPRINT("RemainingPath '%wZ'\n", &RemainingPath); if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0)) { @@ -1081,14 +1133,10 @@ NtQueryValueKey(IN HANDLE KeyHandle, PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; PKEY_VALUE_FULL_INFORMATION ValueFullInformation; - char ValueName2[MAX_PATH]; DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n", KeyHandle, ValueName->Buffer, Length); - wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); - ValueName2[ValueName->Length >> 1] = 0; - /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, KEY_QUERY_VALUE, @@ -1115,7 +1163,7 @@ NtQueryValueKey(IN HANDLE KeyHandle, /* Get Value block of interest */ Status = CmiScanKeyForValue(RegistryHive, KeyCell, - ValueName2, + ValueName, &ValueCell, NULL); if (!NT_SUCCESS(Status)) @@ -1159,39 +1207,39 @@ NtQueryValueKey(IN HANDLE KeyHandle, } else { - ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) + ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; ValuePartialInformation->TitleIndex = 0; ValuePartialInformation->Type = ValueCell->DataType; ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX; if (ValueCell->DataSize > 0) - { - DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); - RtlCopyMemory(ValuePartialInformation->Data, + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(ValuePartialInformation->Data, DataCell->Data, ValueCell->DataSize & LONG_MAX); - CmiReleaseBlock(RegistryHive, DataCell); - } + CmiReleaseBlock(RegistryHive, DataCell); + } else - { - RtlCopyMemory(ValuePartialInformation->Data, - &ValueCell->DataOffset, + { + RtlCopyMemory(ValuePartialInformation->Data, + &ValueCell->DataOffset, ValueCell->DataSize & LONG_MAX); - } + } } break; case KeyValueFullInformation: *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) - + (ValueCell->NameSize -1) * sizeof(WCHAR) - + (ValueCell->DataSize & LONG_MAX); + + (ValueCell->NameSize -1) * sizeof(WCHAR) + + (ValueCell->DataSize & LONG_MAX); if (Length < *ResultLength) { Status = STATUS_BUFFER_TOO_SMALL; } else { - ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) + ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation; ValueFullInformation->TitleIndex = 0; ValueFullInformation->Type = ValueCell->DataType; @@ -1251,17 +1299,13 @@ NtSetValueKey(IN HANDLE KeyHandle, PKEY_CELL KeyCell; PVALUE_CELL ValueCell; BLOCK_OFFSET VBOffset; - char ValueName2[MAX_PATH]; PDATA_CELL DataCell; PDATA_CELL NewDataCell; PHBIN pBin; ULONG DesiredAccess; - DPRINT("KeyHandle %x ValueName %S Type %d\n", - KeyHandle, ValueName? ValueName->Buffer : NULL, Type); - - wcstombs(ValueName2,ValueName->Buffer, ValueName->Length >> 1); - ValueName2[ValueName->Length>>1] = 0; + DPRINT("NtSetValueKey(KeyHandle %x ValueName %S Type %d)\n", + KeyHandle, ValueName? ValueName->Buffer : NULL, Type); DesiredAccess = KEY_SET_VALUE; if (Type == REG_LINK) @@ -1287,7 +1331,7 @@ NtSetValueKey(IN HANDLE KeyHandle, RegistryHive = KeyObject->RegistryHive; Status = CmiScanKeyForValue(RegistryHive, KeyCell, - ValueName2, + ValueName, &ValueCell, &VBOffset); if (!NT_SUCCESS(Status)) @@ -1301,9 +1345,10 @@ NtSetValueKey(IN HANDLE KeyHandle, if (ValueCell == NULL) { + DPRINT("Allocate new value cell\n"); Status = CmiAddValueToKey(RegistryHive, KeyCell, - ValueName2, + ValueName, &ValueCell, &VBOffset); } @@ -1316,71 +1361,93 @@ NtSetValueKey(IN HANDLE KeyHandle, ObDereferenceObject(KeyObject); return(Status); } - else + + DPRINT("DataSize %lu\n", DataSize); + DPRINT("ValueCell %p\n", ValueCell); + DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); + + if (DataSize <= 4) { - DPRINT("DataSize (%d)\n", DataSize); - /* If datasize <= 4 then write in valueblock directly */ - if (DataSize <= 4) + DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); + if ((ValueCell->DataSize >= 0) && + (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) { - DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); - if ((ValueCell->DataSize >= 0) && - (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) - { - CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); - } - - RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize); - ValueCell->DataSize = DataSize | 0x80000000; - ValueCell->DataType = Type; - RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize); + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); } + + RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize); + ValueCell->DataSize = DataSize | 0x80000000; + ValueCell->DataType = Type; + RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize); + } + else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff)) + { /* If new data size is <= current then overwrite current data */ - else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff)) - { - DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); - RtlCopyMemory(DataCell->Data, Data, DataSize); - ValueCell->DataSize = DataSize; - ValueCell->DataType = Type; - CmiReleaseBlock(RegistryHive, DataCell); - /* Update time of heap */ - if (IsPermanentHive(RegistryHive)) - { - ZwQuerySystemTime((PTIME) &pBin->DateModified); - } - } - else - { - BLOCK_OFFSET NewOffset; - - /* Destroy current data block and allocate a new one */ - if ((ValueCell->DataSize >= 0) && - (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) - { - CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); - } - Status = CmiAllocateBlock(RegistryHive, - (PVOID *)&NewDataCell, - DataSize, - &NewOffset); - RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize); - ValueCell->DataSize = DataSize; - ValueCell->DataType = Type; - CmiReleaseBlock(RegistryHive, NewDataCell); - ValueCell->DataOffset = NewOffset; - } - - if (strcmp(ValueName2, "SymbolicLinkValue") == 0) - { - KeyCell->Type = REG_LINK_KEY_CELL_TYPE; - } + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); + RtlCopyMemory(DataCell->Data, Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, DataCell); /* Update time of heap */ - if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) + if (IsPermanentHive(RegistryHive)) { ZwQuerySystemTime((PTIME) &pBin->DateModified); } } + else + { + /* + * New data size is larger than the current, destroy current + * data block and allocate a new one. + */ + BLOCK_OFFSET NewOffset; + + DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); + + if ((ValueCell->DataSize >= 0) && + (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) + { + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); + ValueCell->DataSize = 0; + ValueCell->DataType = 0; + ValueCell->DataOffset = 0xffffffff; + } + + Status = CmiAllocateBlock(RegistryHive, + (PVOID *)&NewDataCell, + DataSize, + &NewOffset); + if (!NT_SUCCESS(Status)) + { + DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status); + + ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); + ObDereferenceObject(KeyObject); + + return(Status); + } + + RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, NewDataCell); + ValueCell->DataOffset = NewOffset; + } + + /* Mark link key */ + if ((_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0) && + (Type == REG_LINK)) + { + KeyCell->Type = REG_LINK_KEY_CELL_TYPE; + } + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); ObDereferenceObject(KeyObject); @@ -1395,13 +1462,9 @@ NTSTATUS STDCALL NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName) { - CHAR ValueName2[MAX_PATH]; PKEY_OBJECT KeyObject; NTSTATUS Status; - wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); - ValueName2[ValueName->Length>>1] = 0; - /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, KEY_QUERY_VALUE, @@ -1421,7 +1484,7 @@ NtDeleteValueKey(IN HANDLE KeyHandle, Status = CmiDeleteValueFromKey(KeyObject->RegistryHive, KeyObject->KeyCell, - ValueName2); + ValueName); /* Release hive lock */ ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource); @@ -1452,12 +1515,12 @@ NtLoadKey2(IN PHANDLE KeyHandle, NTSTATUS STDCALL NtNotifyChangeKey( IN HANDLE KeyHandle, - IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, + IN BOOLEAN Asynchroneous, OUT PVOID ChangeBuffer, IN ULONG Length, IN BOOLEAN WatchSubtree) @@ -1475,7 +1538,6 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle, OUT PULONG ReturnLength) { PREGISTRY_HIVE RegistryHive; - UCHAR ValueName[MAX_PATH]; PVALUE_CELL ValueCell; PKEY_OBJECT KeyObject; PDATA_CELL DataCell; @@ -1511,17 +1573,12 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle, for (i = 0; i < NumberOfValues; i++) { - wcstombs(ValueName, - ValueList[i].ValueName->Buffer, - ValueList[i].ValueName->Length >> 1); - ValueName[ValueList[i].ValueName->Length >> 1] = 0; - - DPRINT("ValueName: '%s'\n", ValueName); + DPRINT("ValueName: '%wZ'\n", ValueList[i].ValueName); /* Get Value block of interest */ Status = CmiScanKeyForValue(RegistryHive, KeyCell, - ValueName, + ValueList[i].ValueName, &ValueCell, NULL); diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 4587dc26b76..b3d5fbf28e8 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -1204,7 +1204,7 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, /* Reallocate the hash table block */ Status = CmiAllocateHashTableBlock(RegistryHive, &NewHashBlock, - &HTOffset, + &HTOffset, HashBlock->HashTableSize + REG_EXTEND_HASH_TABLE_SIZE); @@ -1219,7 +1219,7 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, &HashBlock->Table[0], sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset); - KeyCell->HashTableOffset = HTOffset; + KeyCell->HashTableOffset = HTOffset; HashBlock = NewHashBlock; } } @@ -1237,13 +1237,12 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, NTSTATUS CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueName, + IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *ValueCell, OUT BLOCK_OFFSET *VBOffset) { PVALUE_LIST_CELL ValueListCell; PVALUE_CELL CurValueCell; - ULONG Length; ULONG i; ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); @@ -1261,17 +1260,17 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, for (i = 0; i < KeyCell->NumberOfValues; i++) { CurValueCell = CmiGetBlock(RegistryHive, - ValueListCell->Values[i], - NULL); - /* FIXME: perhaps we must not ignore case if NtCreateKey has not been */ - /* called with OBJ_CASE_INSENSITIVE flag ? */ - Length = strlen(ValueName); + ValueListCell->Values[i], + NULL); + if ((CurValueCell != NULL) && - (CurValueCell->NameSize == Length) && - (_strnicmp(CurValueCell->Name, ValueName, Length) == 0)) + CmiComparePackedNames(ValueName, + CurValueCell->Name, + CurValueCell->NameSize, + CurValueCell->Flags & REG_VALUE_NAME_PACKED)) { *ValueCell = CurValueCell; - if (VBOffset) + if (VBOffset) *VBOffset = ValueListCell->Values[i]; //DPRINT("Found value %s\n", ValueName); break; @@ -1280,7 +1279,7 @@ CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, } CmiReleaseBlock(RegistryHive, ValueListCell); - + return STATUS_SUCCESS; } @@ -1293,7 +1292,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, { PVALUE_LIST_CELL ValueListCell; PVALUE_CELL CurValueCell; - + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); *ValueCell = NULL; @@ -1321,7 +1320,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, CmiReleaseBlock(RegistryHive, CurValueCell); CmiReleaseBlock(RegistryHive, ValueListCell); - + return STATUS_SUCCESS; } @@ -1329,7 +1328,7 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, NTSTATUS CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueNameBuf, + IN PUNICODE_STRING ValueName, OUT PVALUE_CELL *pValueCell, OUT BLOCK_OFFSET *pVBOffset) { @@ -1343,7 +1342,7 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, Status = CmiAllocateValueCell(RegistryHive, &NewValueCell, &VBOffset, - ValueNameBuf); + ValueName); *pVBOffset = VBOffset; if (!NT_SUCCESS(Status)) @@ -1407,7 +1406,7 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, NTSTATUS CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, IN PKEY_CELL KeyCell, - IN PCHAR ValueName) + IN PUNICODE_STRING ValueName) { PVALUE_LIST_CELL ValueListCell; PVALUE_CELL CurValueCell; @@ -1425,9 +1424,12 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, for (i = 0; i < KeyCell->NumberOfValues; i++) { CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL); + if ((CurValueCell != NULL) && - (CurValueCell->NameSize == strlen(ValueName)) && - (memcmp(CurValueCell->Name, ValueName, strlen(ValueName)) == 0)) + CmiComparePackedNames(ValueName, + CurValueCell->Name, + CurValueCell->NameSize, + CurValueCell->Flags & REG_VALUE_NAME_PACKED)) { if ((KeyCell->NumberOfValues - 1) < i) { @@ -1539,20 +1541,25 @@ NTSTATUS CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, PVALUE_CELL *ValueCell, BLOCK_OFFSET *VBOffset, - IN PCHAR ValueNameBuf) + IN PUNICODE_STRING ValueName) { PVALUE_CELL NewValueCell; - ULONG NewValueSize; NTSTATUS Status; + BOOLEAN Packable; + ULONG NameSize; + ULONG i; Status = STATUS_SUCCESS; - NewValueSize = sizeof(VALUE_CELL) + strlen(ValueNameBuf); - Status = CmiAllocateBlock(RegistryHive, - (PVOID*) &NewValueCell, - NewValueSize, - VBOffset); + NameSize = CmiGetPackedNameLength(ValueName, + &Packable); + DPRINT("ValueName->Length %lu NameSize %lu\n", ValueName->Length, NameSize); + + Status = CmiAllocateBlock(RegistryHive, + (PVOID*) &NewValueCell, + sizeof(VALUE_CELL) + NameSize, + VBOffset); if ((NewValueCell == NULL) || (!NT_SUCCESS(Status))) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -1560,8 +1567,22 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, else { NewValueCell->Id = REG_VALUE_CELL_ID; - NewValueCell->NameSize = strlen(ValueNameBuf); - memcpy(NewValueCell->Name, ValueNameBuf, strlen(ValueNameBuf)); + NewValueCell->NameSize = NameSize; + if (Packable) + { + /* Pack the value name */ + for (i = 0; i < NameSize; i++) + NewValueCell->Name[i] = (CHAR)ValueName->Buffer[i]; + NewValueCell->Flags |= REG_VALUE_NAME_PACKED; + } + else + { + /* Copy the value name */ + RtlCopyMemory(NewValueCell->Name, + ValueName->Buffer, + NameSize); + NewValueCell->Flags = 0; + } NewValueCell->DataType = 0; NewValueCell->DataSize = 0; NewValueCell->DataOffset = 0xffffffff; @@ -1669,9 +1690,9 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive, NTSTATUS CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, - PVOID *Block, - LONG BlockSize, - BLOCK_OFFSET * pBlockOffset) + PVOID *Block, + LONG BlockSize, + BLOCK_OFFSET * pBlockOffset) { PCELL_HEADER NewBlock; NTSTATUS Status; @@ -1687,86 +1708,88 @@ CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, { NewBlock = ExAllocatePool(NonPagedPool, BlockSize); - if (NewBlock == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - RtlZeroMemory(NewBlock, BlockSize); - NewBlock->CellSize = BlockSize; - CmiLockBlock(RegistryHive, NewBlock); - *Block = NewBlock; - if (pBlockOffset) - *pBlockOffset = (BLOCK_OFFSET) NewBlock; - } + if (NewBlock == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + RtlZeroMemory(NewBlock, BlockSize); + NewBlock->CellSize = BlockSize; + CmiLockBlock(RegistryHive, NewBlock); + *Block = NewBlock; + if (pBlockOffset) + *pBlockOffset = (BLOCK_OFFSET) NewBlock; + } } else { - ULONG i; + ULONG i; - /* first search in free blocks */ - NewBlock = NULL; - for (i = 0; i < RegistryHive->FreeListSize; i++) - { - if (RegistryHive->FreeList[i]->CellSize >= BlockSize) - { - PVOID Temp; - NewBlock = RegistryHive->FreeList[i]; + /* first search in free blocks */ + NewBlock = NULL; + for (i = 0; i < RegistryHive->FreeListSize; i++) + { + if (RegistryHive->FreeList[i]->CellSize >= BlockSize) + { + PVOID Temp; - if (pBlockOffset) - *pBlockOffset = RegistryHive->FreeListOffset[i]; + NewBlock = RegistryHive->FreeList[i]; + if (pBlockOffset) + *pBlockOffset = RegistryHive->FreeListOffset[i]; - /* Update time of heap */ - Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); + /* Update time of heap */ + Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); - if (Temp) - ZwQuerySystemTime((PTIME) &pBin->DateModified); + if (Temp) + ZwQuerySystemTime((PTIME) &pBin->DateModified); - if ((i + 1) < RegistryHive->FreeListSize) - { - RtlMoveMemory(&RegistryHive->FreeList[i], - &RegistryHive->FreeList[i + 1], - sizeof(RegistryHive->FreeList[0]) - * (RegistryHive->FreeListSize - i - 1)); - RtlMoveMemory(&RegistryHive->FreeListOffset[i], - &RegistryHive->FreeListOffset[i + 1], - sizeof(RegistryHive->FreeListOffset[0]) - * (RegistryHive->FreeListSize - i - 1)); - } - RegistryHive->FreeListSize--; - break; - } - } + if ((i + 1) < RegistryHive->FreeListSize) + { + RtlMoveMemory(&RegistryHive->FreeList[i], + &RegistryHive->FreeList[i + 1], + sizeof(RegistryHive->FreeList[0]) + * (RegistryHive->FreeListSize - i - 1)); + RtlMoveMemory(&RegistryHive->FreeListOffset[i], + &RegistryHive->FreeListOffset[i + 1], + sizeof(RegistryHive->FreeListOffset[0]) + * (RegistryHive->FreeListSize - i - 1)); + } + RegistryHive->FreeListSize--; + break; + } + } - /* Need to extend hive file : */ - if (NewBlock == NULL) - { - /* Add a new block */ - Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset); - } + /* Need to extend hive file : */ + if (NewBlock == NULL) + { + /* Add a new block */ + Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset); + } - if (NT_SUCCESS(Status)) - { - *Block = NewBlock; + if (NT_SUCCESS(Status)) + { + *Block = NewBlock; - /* Split the block in two parts */ - if (NewBlock->CellSize > BlockSize) - { - NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); - NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; - CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); - } - else if (NewBlock->CellSize < BlockSize) - { - return STATUS_UNSUCCESSFUL; - } - RtlZeroMemory(*Block, BlockSize); - ((PCELL_HEADER) (*Block))->CellSize = -BlockSize; - CmiLockBlock(RegistryHive, *Block); - } - } - return Status; + /* Split the block in two parts */ + if (NewBlock->CellSize > BlockSize) + { + NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); + NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; + CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); + } + else if (NewBlock->CellSize < BlockSize) + { + return(STATUS_UNSUCCESSFUL); + } + + RtlZeroMemory(*Block, BlockSize); + ((PCELL_HEADER) (*Block))->CellSize = -BlockSize; + CmiLockBlock(RegistryHive, *Block); + } + } + + return(Status); } @@ -1781,27 +1804,27 @@ CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, Status = STATUS_SUCCESS; if (IsVolatileHive(RegistryHive)) - { - CmiReleaseBlock(RegistryHive, Block); - ExFreePool(Block); - } + { + CmiReleaseBlock(RegistryHive, Block); + ExFreePool(Block); + } else - { - PCELL_HEADER pFree = Block; + { + PCELL_HEADER pFree = Block; - if (pFree->CellSize < 0) - pFree->CellSize = -pFree->CellSize; + if (pFree->CellSize < 0) + pFree->CellSize = -pFree->CellSize; - CmiAddFree(RegistryHive, Block, Offset); - CmiReleaseBlock(RegistryHive, Block); + CmiAddFree(RegistryHive, Block, Offset); + CmiReleaseBlock(RegistryHive, Block); - /* Update time of heap */ - if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) - ZwQuerySystemTime((PTIME) &pBin->DateModified); + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) + ZwQuerySystemTime((PTIME) &pBin->DateModified); - /* FIXME: Set first dword to block_offset of another free block ? */ - /* FIXME: Concatenate with previous and next block if free */ - } + /* FIXME: Set first dword to block_offset of another free block ? */ + /* FIXME: Concatenate with previous and next block if free */ + } return Status; } @@ -1825,29 +1848,29 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive, FreeBlock, FreeOffset); DPRINT("\n"); if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) - { + { DPRINT("\n"); - tmpList = ExAllocatePool(PagedPool, + tmpList = ExAllocatePool(PagedPool, sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); DPRINT("\n"); - if (tmpList == NULL) - return STATUS_INSUFFICIENT_RESOURCES; + if (tmpList == NULL) + return STATUS_INSUFFICIENT_RESOURCES; DPRINT("\n"); - tmpListOffset = ExAllocatePool(PagedPool, + tmpListOffset = ExAllocatePool(PagedPool, sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32)); DPRINT("\n"); - if (tmpListOffset == NULL) - { - ExFreePool(tmpList); - return STATUS_INSUFFICIENT_RESOURCES; - } + if (tmpListOffset == NULL) + { + ExFreePool(tmpList); + return STATUS_INSUFFICIENT_RESOURCES; + } DPRINT("\n"); - if (RegistryHive->FreeListMax) - { + if (RegistryHive->FreeListMax) + { DPRINT("\n"); RtlMoveMemory(tmpList, RegistryHive->FreeList, sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); @@ -1986,3 +2009,80 @@ CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, /* FIXME: Implement */ } } + + +ULONG +CmiGetPackedNameLength(IN PUNICODE_STRING Name, + OUT PBOOLEAN Packable) +{ + ULONG i; + + if (Packable != NULL) + *Packable = TRUE; + + for (i = 0; i < Name->Length; i++) + { + if (Name->Buffer[i] > 0xFF) + { + if (Packable != NULL) + *Packable = FALSE; + return(Name->Length); + } + } + + return(Name->Length / sizeof(WCHAR)); +} + + +BOOLEAN +CmiComparePackedNames(IN PUNICODE_STRING Name, + IN PCHAR NameBuffer, + IN USHORT NameBufferSize, + IN BOOLEAN NamePacked) +{ + PWCHAR UNameBuffer; + ULONG i; + + if (NamePacked) + { + if (Name->Length != NameBufferSize * sizeof(WCHAR)) + { + return(FALSE); + } + + for (i = 0; i < Name->Length / sizeof(WCHAR); i++) + { + if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar((WCHAR)NameBuffer[i])) + return(FALSE); + } + } + else + { + if (Name->Length != NameBufferSize) + return(FALSE); + + UNameBuffer = (PWCHAR)NameBuffer; + + for (i = 0; i < Name->Length / sizeof(WCHAR); i++) + { + if (RtlUpcaseUnicodeChar(Name->Buffer[i]) != RtlUpcaseUnicodeChar(UNameBuffer[i])) + return(FALSE); + } + } + + return(TRUE); +} + + +VOID +CmiCopyPackedName(PWCHAR NameBuffer, + PCHAR PackedNameBuffer, + ULONG PackedNameSize) +{ + ULONG i; + + for (i = 0; i < PackedNameSize; i++) + NameBuffer[i] = (WCHAR)PackedNameBuffer[i]; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index 2d002d1ef4e..dbc039946c7 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -1,4 +1,4 @@ -/* $Id: registry.c,v 1.78 2002/11/26 15:31:41 ekohl Exp $ +/* $Id: registry.c,v 1.79 2002/11/30 14:46:27 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -20,6 +20,7 @@ #include #include #include +#include #define NDEBUG #include @@ -204,7 +205,7 @@ CmiCheckByName(BOOLEAN Verbose, wcscpy(KeyPathBuffer, L"\\Registry\\"); wcscat(KeyPathBuffer, KeyName); - RtlInitUnicodeString(&KeyPath, KeyPathBuffer); + RtlInitUnicodeString(&KeyPath, KeyPathBuffer); InitializeObjectAttributes(&ObjectAttributes, &KeyPath, @@ -219,11 +220,11 @@ CmiCheckByName(BOOLEAN Verbose, if (CHECKED) { if (!NT_SUCCESS(Status)) - { + { DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status); DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status); assert(NT_SUCCESS(Status)); - } + } } CmiCheckKey(Verbose, Key); @@ -484,6 +485,7 @@ CmInit2(PCHAR CommandLine) { PCHAR p1, p2; ULONG PiceStart; + NTSTATUS Status; /* FIXME: Store system start options */ @@ -515,12 +517,17 @@ CmInit2(PCHAR CommandLine) p1 = p2; } #ifndef WIN32_REGDBG - RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, - L"\\Pice", - L"Start", - REG_DWORD, - &PiceStart, - sizeof(ULONG)); + Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, + L"\\Pice", + L"Start", + REG_DWORD, + &PiceStart, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + + KeBugCheck(CONFIG_INITIALIZATION_FAILED); + } #endif } @@ -602,12 +609,12 @@ CmiCreateCurrentControlSetLink(VOID) RtlInitUnicodeStringFromLiteral(&LinkValue, L"SymbolicLinkValue"); - Status=NtSetValueKey(KeyHandle, - &LinkValue, - 0, - REG_LINK, - (PVOID)TargetNameBuffer, - TargetNameLength); + Status = NtSetValueKey(KeyHandle, + &LinkValue, + 0, + REG_LINK, + (PVOID)TargetNameBuffer, + TargetNameLength); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index cb20844bda0..5a73f312ae3 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -168,6 +168,8 @@ CmiObjectParse(PVOID ParsedObject, if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) && !((Attributes & OBJ_OPENLINK) && (end == NULL))) { + DPRINT("Found link\n"); + RtlInitUnicodeString(&LinkPath, NULL); Status = CmiGetLinkTarget(FoundObject->RegistryHive, FoundObject->KeyCell, @@ -436,18 +438,22 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, PKEY_CELL KeyCell, PUNICODE_STRING TargetPath) { + UNICODE_STRING LinkName = UNICODE_STRING_INITIALIZER(L"SymbolicLinkValue"); PVALUE_CELL ValueCell; PDATA_CELL DataCell; NTSTATUS Status; + DPRINT("CmiGetLinkTarget() called\n"); + /* Get Value block of interest */ Status = CmiScanKeyForValue(RegistryHive, KeyCell, - "SymbolicLinkValue", + &LinkName, &ValueCell, NULL); if (!NT_SUCCESS(Status)) { + DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status); return(Status); } @@ -485,6 +491,8 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0; } + DPRINT("TargetPath '%wZ'\n", TargetPath); + return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/cm/rtlfunc.c b/reactos/ntoskrnl/cm/rtlfunc.c index 9678f62542f..7e36694ab81 100644 --- a/reactos/ntoskrnl/cm/rtlfunc.c +++ b/reactos/ntoskrnl/cm/rtlfunc.c @@ -6,6 +6,8 @@ * UPDATE HISTORY: */ +/* INCLUDES *****************************************************************/ + #ifdef WIN32_REGDBG #include "cm_win32.h" #else @@ -23,6 +25,9 @@ #include "cm.h" #endif + +/* FUNCTIONS ****************************************************************/ + NTSTATUS STDCALL RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)