/* * PROJECT: ReactOS API Tests * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: Test for NtQueryValueKey * COPYRIGHT: Copyright 2020 Thomas Faber (thomas.faber@reactos.org) */ #include "precomp.h" #include START_TEST(NtQueryValueKey) { NTSTATUS Status; HANDLE KeyHandle; UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"); OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemRoot"); PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 Info; PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 InfoUnaligned; ULONG InfoLength; ULONG ResultLength; const WCHAR *StringData; ULONG StringLength; InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { skip("Test key unavailable\n"); return; } /* Specify zero-size buffer, get the length */ ResultLength = 0x55555555; Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformationAlign64, NULL, 0, &ResultLength); ok_hex(Status, STATUS_BUFFER_TOO_SMALL); ok(ResultLength > FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data) && ResultLength < 0x10000, "Invalid result length %lu\n", ResultLength); if (ResultLength < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data)) { skip("Result length %lu too small\n", ResultLength); goto Exit; } InfoLength = ResultLength; Info = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength + 4); if (Info == NULL) { skip("Could not alloc %lu bytes\n", InfoLength); goto Exit; } /* Successful call */ Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformationAlign64, Info, InfoLength, &ResultLength); ok_hex(Status, STATUS_SUCCESS); ok_int(ResultLength, InfoLength); ok_int(Info->Type, REG_SZ); StringLength = InfoLength - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data); ok_int(Info->DataLength, StringLength); StringData = (PWCHAR)Info->Data; ok(Info->DataLength >= 5 * sizeof(WCHAR), "DataLength %lu is too small for path\n", Info->DataLength); if (Info->DataLength >= 5 * sizeof(WCHAR)) { trace("SystemRoot: %.*ls\n", (int)(Info->DataLength / sizeof(WCHAR) - 1), StringData); ok(StringData[0] >= 'A' && StringData[0] <= 'Z', "Data[0] = %x\n", StringData[0]); ok(StringData[1] == ':', "Data[1] = %x\n", StringData[1]); ok(StringData[2] == '\\', "Data[2] = %x\n", StringData[2]); ok(iswalnum(StringData[3]), "Data[3] = %x\n", StringData[3]); ok(StringData[Info->DataLength / sizeof(WCHAR) - 1] == UNICODE_NULL, "Data[%lu] = %x\n", Info->DataLength / sizeof(WCHAR) - 1, StringData[Info->DataLength / sizeof(WCHAR) - 1]); } /* If the buffer isn't 64 bit aligned, the data won't be, either */ InfoUnaligned = (PVOID)((PUCHAR)Info + 4); Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformationAlign64, InfoUnaligned, InfoLength, &ResultLength); ok_hex(Status, STATUS_SUCCESS); ok_int(ResultLength, InfoLength); ok_int(InfoUnaligned->Type, REG_SZ); StringData = (PWCHAR)InfoUnaligned->Data; ok(InfoUnaligned->DataLength >= 2 * sizeof(WCHAR), "DataLength %lu is too small for path\n", InfoUnaligned->DataLength); if (InfoUnaligned->DataLength >= 2 * sizeof(WCHAR)) { ok(StringData[1] == ':', "Data[1] = %x\n", StringData[1]); } RtlFreeHeap(RtlGetProcessHeap(), 0, Info); Exit: Status = NtClose(KeyHandle); ok_hex(Status, STATUS_SUCCESS); }