1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Test for NtQueryValueKey
5  * COPYRIGHT:   Copyright 2020 Thomas Faber (thomas.faber@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include <winreg.h>
10 
START_TEST(NtQueryValueKey)11 START_TEST(NtQueryValueKey)
12 {
13     NTSTATUS Status;
14     HANDLE KeyHandle;
15     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
16     OBJECT_ATTRIBUTES ObjectAttributes;
17     UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemRoot");
18     PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 Info;
19     PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 InfoUnaligned;
20     ULONG InfoLength;
21     ULONG ResultLength;
22     const WCHAR *StringData;
23     ULONG StringLength;
24 
25     InitializeObjectAttributes(&ObjectAttributes,
26                                &KeyName,
27                                OBJ_CASE_INSENSITIVE,
28                                NULL,
29                                NULL);
30     Status = NtOpenKey(&KeyHandle,
31                        KEY_QUERY_VALUE,
32                        &ObjectAttributes);
33     if (!NT_SUCCESS(Status))
34     {
35         skip("Test key unavailable\n");
36         return;
37     }
38 
39     /* Specify zero-size buffer, get the length */
40     ResultLength = 0x55555555;
41     Status = NtQueryValueKey(KeyHandle,
42                              &ValueName,
43                              KeyValuePartialInformationAlign64,
44                              NULL,
45                              0,
46                              &ResultLength);
47     ok_hex(Status, STATUS_BUFFER_TOO_SMALL);
48     ok(ResultLength > FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data) && ResultLength < 0x10000,
49        "Invalid result length %lu\n", ResultLength);
50     if (ResultLength < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data))
51     {
52         skip("Result length %lu too small\n", ResultLength);
53         goto Exit;
54     }
55     InfoLength = ResultLength;
56     Info = RtlAllocateHeap(RtlGetProcessHeap(),
57                            0,
58                            InfoLength + 4);
59     if (Info == NULL)
60     {
61         skip("Could not alloc %lu bytes\n", InfoLength);
62         goto Exit;
63     }
64 
65     /* Successful call */
66     Status = NtQueryValueKey(KeyHandle,
67                              &ValueName,
68                              KeyValuePartialInformationAlign64,
69                              Info,
70                              InfoLength,
71                              &ResultLength);
72     ok_hex(Status, STATUS_SUCCESS);
73     ok_int(ResultLength, InfoLength);
74 
75     ok_int(Info->Type, REG_SZ);
76     StringLength = InfoLength - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, Data);
77     ok_int(Info->DataLength, StringLength);
78 
79     StringData = (PWCHAR)Info->Data;
80     ok(Info->DataLength >= 5 * sizeof(WCHAR), "DataLength %lu is too small for path\n", Info->DataLength);
81     if (Info->DataLength >= 5 * sizeof(WCHAR))
82     {
83         trace("SystemRoot: %.*ls\n", (int)(Info->DataLength / sizeof(WCHAR) - 1), StringData);
84         ok(StringData[0] >= 'A' && StringData[0] <= 'Z', "Data[0] = %x\n", StringData[0]);
85         ok(StringData[1] == ':', "Data[1] = %x\n", StringData[1]);
86         ok(StringData[2] == '\\', "Data[2] = %x\n", StringData[2]);
87         ok(iswalnum(StringData[3]), "Data[3] = %x\n", StringData[3]);
88         ok(StringData[Info->DataLength / sizeof(WCHAR) - 1] == UNICODE_NULL,
89            "Data[%lu] = %x\n", Info->DataLength / sizeof(WCHAR) - 1, StringData[Info->DataLength / sizeof(WCHAR) - 1]);
90     }
91 
92     /* If the buffer isn't 64 bit aligned, the data won't be, either */
93     InfoUnaligned = (PVOID)((PUCHAR)Info + 4);
94     Status = NtQueryValueKey(KeyHandle,
95                              &ValueName,
96                              KeyValuePartialInformationAlign64,
97                              InfoUnaligned,
98                              InfoLength,
99                              &ResultLength);
100     ok_hex(Status, STATUS_SUCCESS);
101     ok_int(ResultLength, InfoLength);
102     ok_int(InfoUnaligned->Type, REG_SZ);
103     StringData = (PWCHAR)InfoUnaligned->Data;
104     ok(InfoUnaligned->DataLength >= 2 * sizeof(WCHAR), "DataLength %lu is too small for path\n", InfoUnaligned->DataLength);
105     if (InfoUnaligned->DataLength >= 2 * sizeof(WCHAR))
106     {
107         ok(StringData[1] == ':', "Data[1] = %x\n", StringData[1]);
108     }
109 
110     RtlFreeHeap(RtlGetProcessHeap(), 0, Info);
111 
112 Exit:
113     Status = NtClose(KeyHandle);
114     ok_hex(Status, STATUS_SUCCESS);
115 }
116