Author: tfaber Date: Sat Apr 25 15:05:36 2015 New Revision: 67414
URL: http://svn.reactos.org/svn/reactos?rev=67414&view=rev Log: [NTDLL_APITEST] - Add a test for NtQueryKey(KeyFullInformation) CORE-6976
Modified: trunk/rostests/apitests/ntdll/NtQueryKey.c
Modified: trunk/rostests/apitests/ntdll/NtQueryKey.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/NtQueryKey.... ============================================================================== --- trunk/rostests/apitests/ntdll/NtQueryKey.c [iso-8859-1] (original) +++ trunk/rostests/apitests/ntdll/NtQueryKey.c [iso-8859-1] Sat Apr 25 15:05:36 2015 @@ -3,6 +3,7 @@ * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Tests for the NtQueryKey API * PROGRAMMER: Jérôme Gardou jerome.gardou@reactos.org + * Thomas Faber thomas.faber@reactos.org */
#include <apitest.h> @@ -12,6 +13,181 @@ #include <ndk/cmfuncs.h> #include <ndk/cmtypes.h> #include <ndk/obfuncs.h> + +static +void +Test_KeyFullInformation(void) +{ + UNICODE_STRING HKLM_Name = RTL_CONSTANT_STRING(L"\Registry\Machine"); + UNICODE_STRING Software_Name = RTL_CONSTANT_STRING(L"Software"); + UNICODE_STRING Test_Name = RTL_CONSTANT_STRING(L"NtQueryKey_apitest"); + UNICODE_STRING MyClass = RTL_CONSTANT_STRING(L"MyClass"); + HANDLE HKLM_Key, HKLM_Software_Key, Test_Key; + ULONG FullInformationLength; + PKEY_FULL_INFORMATION FullInformation; + ULONG InfoLength; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + FullInformationLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[100]); + FullInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInformationLength); + if (!FullInformation) + { + skip("Out of memory\n"); + return; + } + + InitializeObjectAttributes(&ObjectAttributes, + &HKLM_Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&HKLM_Key, KEY_READ, &ObjectAttributes); + ok_ntstatus(Status, STATUS_SUCCESS); + + InfoLength = 0x55555555; + Status = NtQueryKey(HKLM_Key, KeyFullInformation, NULL, 0, &InfoLength); + ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(HKLM_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex); + ok(FullInformation->ClassOffset == 0xffffffff, "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == 0, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->SubKeys >= 5 && FullInformation->SubKeys < 20, "SubKeys = %lu\n", FullInformation->SubKeys); + ok(FullInformation->MaxNameLen >= 8 * sizeof(WCHAR) && FullInformation->MaxNameLen < 100 * sizeof(WCHAR), "MaxNameLen = %lu\n", FullInformation->MaxNameLen); + ok(FullInformation->MaxClassLen != 0x55555555 && FullInformation->MaxClassLen % sizeof(WCHAR) == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen); + ok(FullInformation->Values != 0x55555555, "Values = %lu\n", FullInformation->Values); + ok(FullInformation->MaxValueNameLen != 0x55555555 && FullInformation->MaxValueNameLen % sizeof(WCHAR) == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen); + ok(FullInformation->MaxValueDataLen != 0x55555555, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen); + ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(HKLM_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) - 1, &InfoLength); + ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart == 0x5555555555555555, "LastWriteTime changed: %I64d\n", FullInformation->LastWriteTime.QuadPart); + + InitializeObjectAttributes(&ObjectAttributes, + &Software_Name, + OBJ_CASE_INSENSITIVE, + HKLM_Key, + NULL); + Status = NtOpenKey(&HKLM_Software_Key, KEY_READ, &ObjectAttributes); + ok_ntstatus(Status, STATUS_SUCCESS); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(HKLM_Software_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex); + ok(FullInformation->ClassOffset == 0xffffffff, "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == 0, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->SubKeys >= 5 && FullInformation->SubKeys < 1000, "SubKeys = %lu\n", FullInformation->SubKeys); + ok(FullInformation->MaxNameLen >= 8 * sizeof(WCHAR), "MaxNameLen = %lu\n", FullInformation->MaxNameLen); + ok(FullInformation->MaxClassLen != 0x55555555 && FullInformation->MaxClassLen % sizeof(WCHAR) == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen); + ok(FullInformation->Values != 0x55555555, "Values = %lu\n", FullInformation->Values); + ok(FullInformation->MaxValueNameLen != 0x55555555 && FullInformation->MaxValueNameLen % sizeof(WCHAR) == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen); + ok(FullInformation->MaxValueDataLen != 0x55555555, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen); + ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]); + + InitializeObjectAttributes(&ObjectAttributes, + &Test_Name, + OBJ_CASE_INSENSITIVE, + HKLM_Software_Key, + NULL); + Status = NtCreateKey(&Test_Key, KEY_ALL_ACCESS, &ObjectAttributes, 0, &MyClass, REG_OPTION_VOLATILE, NULL); + ok_ntstatus(Status, STATUS_SUCCESS); + + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, NULL, 0, &InfoLength); + ok(Status == STATUS_BUFFER_TOO_SMALL, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class), &InfoLength); + ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->TitleIndex == 0, "TitleIndex = %lu\n", FullInformation->TitleIndex); + ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->SubKeys == 0, "SubKeys = %lu\n", FullInformation->SubKeys); + ok(FullInformation->MaxNameLen == 0, "MaxNameLen = %lu\n", FullInformation->MaxNameLen); + ok(FullInformation->MaxClassLen == 0, "MaxClassLen = %lu\n", FullInformation->MaxClassLen); + ok(FullInformation->Values == 0, "Values = %lu\n", FullInformation->Values); + ok(FullInformation->MaxValueNameLen == 0, "MaxValueNameLen = %lu\n", FullInformation->MaxValueNameLen); + ok(FullInformation->MaxValueDataLen == 0, "MaxValueDataLen = %lu\n", FullInformation->MaxValueDataLen); + ok(FullInformation->Class[0] == 0x5555, "Class[0] = %u\n", FullInformation->Class[0]); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class[1]), &InfoLength); + ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]); + ok(FullInformation->Class[1] == 0x5555, "Class[1] = %u\n", FullInformation->Class[1]); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length - 1, &InfoLength); + ok(Status == STATUS_BUFFER_OVERFLOW, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]); + ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]); + ok(FullInformation->Class[6] == (L's' | 0x5500), "Class[6] = %u\n", FullInformation->Class[6]); + ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, &InfoLength); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]); + ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]); + ok(FullInformation->Class[6] == L's', "Class[6] = %u\n", FullInformation->Class[6]); + ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]); + + RtlFillMemory(FullInformation, FullInformationLength, 0x55); + InfoLength = 0x55555555; + Status = NtQueryKey(Test_Key, KeyFullInformation, FullInformation, FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length + sizeof(UNICODE_NULL), &InfoLength); + ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status); + ok(InfoLength == FIELD_OFFSET(KEY_FULL_INFORMATION, Class) + MyClass.Length, "InfoLength = %lu\n", InfoLength); + ok(FullInformation->LastWriteTime.QuadPart != 0x5555555555555555, "LastWriteTime unchanged\n"); + ok(FullInformation->ClassOffset == FIELD_OFFSET(KEY_FULL_INFORMATION, Class), "ClassOffset = %lu\n", FullInformation->ClassOffset); + ok(FullInformation->ClassLength == MyClass.Length, "ClassLength = %lu\n", FullInformation->ClassLength); + ok(FullInformation->Class[0] == L'M', "Class[0] = %u\n", FullInformation->Class[0]); + ok(FullInformation->Class[1] == L'y', "Class[1] = %u\n", FullInformation->Class[1]); + ok(FullInformation->Class[6] == L's', "Class[6] = %u\n", FullInformation->Class[6]); + ok(FullInformation->Class[7] == 0x5555, "Class[7] = %u\n", FullInformation->Class[7]); + + RtlFreeHeap(RtlGetProcessHeap(), 0, FullInformation); + + Status = NtDeleteKey(Test_Key); + ok_ntstatus(Status, STATUS_SUCCESS); + + NtClose(Test_Key); + NtClose(HKLM_Software_Key); + NtClose(HKLM_Key); +}
static void @@ -44,7 +220,11 @@
/* Get it for real */ NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength); - ok(NameInformation != NULL, "\n"); + if (!NameInformation) + { + skip("Out of memory\n"); + return; + }
Status = NtQueryKey(HKLM_Key, KeyNameInformation, NameInformation, InfoLength, &InfoLength); ok_ntstatus(Status, STATUS_SUCCESS); @@ -97,5 +277,6 @@
START_TEST(NtQueryKey) { + Test_KeyFullInformation(); Test_KeyNameInformation(); }