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 NtSetValueKey
5 * COPYRIGHT: Copyright 2016-2019 Thomas Faber (thomas.faber@reactos.org)
12 START_TEST(NtSetValueKey
)
15 HANDLE ParentKeyHandle
;
17 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"SOFTWARE\\ntdll-apitest-NtSetValueKey");
18 OBJECT_ATTRIBUTES ObjectAttributes
;
19 UNICODE_STRING ValueName
;
20 WCHAR Default
[] = L
"Default";
21 WCHAR Hello
[] = L
"Hello";
24 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
25 ULONG PartialInfoLength
;
29 ULONG LargeBufferLength
;
35 NTSTATUS StatusExisting
;
37 NTSTATUS StatusExisting2
;
41 { REG_NONE
, NULL
, 0, STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Empty REG_NONE value */
42 { REG_SZ
, Hello
, sizeof(Hello
), STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Regular string */
43 { REG_SZ
, Empty
, sizeof(Empty
), STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Empty string */
44 { REG_SZ
, NULL
, 0, STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Zero length */
45 { REG_SZ
, Hello
, 0, STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Zero length, non-null data */
46 { REG_SZ
, (PVOID
)(LONG_PTR
)-4, 0, STATUS_SUCCESS
, STATUS_SUCCESS
}, /* Zero length, kernel data */
47 { REG_SZ
, NULL
, 1, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
}, /* Non-zero length (odd), null data */
48 { REG_SZ
, NULL
, 2, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
}, /* Non-zero length (even), null data */
49 { REG_SZ
, NULL
, 4, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
}, /* CM_KEY_VALUE_SMALL, null data */
50 { REG_SZ
, NULL
, 5, STATUS_INVALID_PARAMETER
, STATUS_ACCESS_VIOLATION
, /* CM_KEY_VALUE_SMALL+1, null data */
51 STATUS_ACCESS_VIOLATION
, STATUS_INSUFFICIENT_RESOURCES
}, /* win7 */
52 { REG_SZ
, NULL
, 6, STATUS_INVALID_PARAMETER
, STATUS_ACCESS_VIOLATION
, /* CM_KEY_VALUE_SMALL+2, null data */
53 STATUS_ACCESS_VIOLATION
, STATUS_INSUFFICIENT_RESOURCES
}, /* win7 */
54 { REG_SZ
, NULL
, 0x7fff0000, STATUS_INVALID_PARAMETER
, STATUS_INSUFFICIENT_RESOURCES
, /* MI_USER_PROBE_ADDRESS, null data */
55 STATUS_INSUFFICIENT_RESOURCES
, STATUS_INSUFFICIENT_RESOURCES
}, /* win7 */
56 { REG_SZ
, NULL
, 0x7fff0001, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
, /* MI_USER_PROBE_ADDRESS+1, null data */
57 STATUS_INSUFFICIENT_RESOURCES
, STATUS_INSUFFICIENT_RESOURCES
}, /* win7 */
58 { REG_SZ
, NULL
, 0x7fffffff, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
, /* <2GB, null data */
59 STATUS_INVALID_PARAMETER
, STATUS_INVALID_PARAMETER
}, /* win7 */
60 { REG_SZ
, NULL
, 0x80000000, STATUS_ACCESS_VIOLATION
, STATUS_ACCESS_VIOLATION
, /* 2GB, null data */
61 STATUS_INVALID_PARAMETER
, STATUS_INVALID_PARAMETER
}, /* win7 */
62 { REG_BINARY
, NULL
, 5, STATUS_INVALID_PARAMETER
, STATUS_ACCESS_VIOLATION
, /* ROSTESTS-200 */
63 STATUS_ACCESS_VIOLATION
, STATUS_INSUFFICIENT_RESOURCES
}, /* win7 */
67 Status
= RtlOpenCurrentUser(READ_CONTROL
, &ParentKeyHandle
);
68 ok(Status
== STATUS_SUCCESS
, "RtlOpenCurrentUser returned %lx\n", Status
);
69 if (!NT_SUCCESS(Status
))
71 skip("No user key handle\n");
75 InitializeObjectAttributes(&ObjectAttributes
,
80 Status
= NtCreateKey(&KeyHandle
,
81 KEY_QUERY_VALUE
| KEY_SET_VALUE
| DELETE
,
87 ok(Status
== STATUS_SUCCESS
, "NtCreateKey returned %lx\n", Status
);
88 if (!NT_SUCCESS(Status
))
90 NtClose(ParentKeyHandle
);
91 skip("No key handle\n");
95 LargeBufferLength
= 0x20000;
96 LargeBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, LargeBufferLength
);
98 PartialInfoLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[LargeBufferLength
]);
99 PartialInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PartialInfoLength
);
101 if (LargeBuffer
== NULL
|| PartialInfo
== NULL
)
103 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer
);
104 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo
);
105 NtDeleteKey(KeyHandle
);
107 NtClose(ParentKeyHandle
);
108 skip("Could not allocate buffers\n");
112 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
117 /* Make sure it exists */
118 RtlInitUnicodeString(&ValueName
, L
"ExistingValue");
119 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, REG_SZ
, Default
, sizeof(Default
));
120 ok(Status
== STATUS_SUCCESS
, "[%lu] NtSetValueKey failed with %lx", i
, Status
);
123 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
124 if (Status
== Tests
[i
].StatusExisting2
)
125 ok(Status
== Tests
[i
].StatusExisting
|| Status
== Tests
[i
].StatusExisting2
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx or %lx\n",
126 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusExisting
, Tests
[i
].StatusExisting2
);
128 ok(Status
== Tests
[i
].StatusExisting
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx\n",
129 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusExisting
);
132 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
133 QueryStatus
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
134 ok(QueryStatus
== STATUS_SUCCESS
, "[%lu, %p, %lu] NtQueryValueKey failed with %lx\n",
135 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
136 if (NT_SUCCESS(QueryStatus
))
138 if (NT_SUCCESS(Status
))
140 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
141 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
142 ok(PartialInfo
->Type
== Tests
[i
].Type
, "[%lu, %p, %lu] Type = %lu\n",
143 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
144 ok(PartialInfo
->DataLength
== Tests
[i
].DataSize
, "[%lu, %p, %lu] DataLength = %lu\n",
145 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
146 ok(!memcmp(PartialInfo
->Data
, Tests
[i
].Data
, Tests
[i
].DataSize
), "[%lu, %p, %lu] Data does not match set value\n",
147 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
151 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
152 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
153 ok(PartialInfo
->Type
== REG_SZ
, "[%lu, %p, %lu] Type = %lu\n",
154 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
155 ok(PartialInfo
->DataLength
== sizeof(Default
), "[%lu, %p, %lu] DataLength = %lu\n",
156 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
157 ok(!memcmp(PartialInfo
->Data
, Default
, sizeof(Default
)), "[%lu, %p, %lu] Data does not match default\n",
158 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
165 /* Make sure it doesn't exist */
166 RtlInitUnicodeString(&ValueName
, L
"NewValue");
167 Status
= NtDeleteValueKey(KeyHandle
, &ValueName
);
168 ok(Status
== STATUS_SUCCESS
|| Status
== STATUS_OBJECT_NAME_NOT_FOUND
,
169 "[%lu] NtDeleteValueKey failed with %lx", i
, Status
);
172 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
173 if (Tests
[i
].StatusNew2
)
174 ok(Status
== Tests
[i
].StatusNew
|| Status
== Tests
[i
].StatusNew2
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx or %lx\n",
175 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusNew
, Tests
[i
].StatusNew2
);
177 ok(Status
== Tests
[i
].StatusNew
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx\n",
178 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusNew
);
181 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
182 QueryStatus
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
183 if (NT_SUCCESS(Status
))
185 ok(QueryStatus
== STATUS_SUCCESS
, "[%lu, %p, %lu] NtQueryValueKey failed with %lx\n",
186 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
187 if (NT_SUCCESS(QueryStatus
))
189 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
190 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
191 ok(PartialInfo
->Type
== Tests
[i
].Type
, "[%lu, %p, %lu] Type = %lu\n",
192 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
193 ok(PartialInfo
->DataLength
== Tests
[i
].DataSize
, "[%lu, %p, %lu] DataLength = %lu\n",
194 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
195 ok(!memcmp(PartialInfo
->Data
, Tests
[i
].Data
, Tests
[i
].DataSize
), "[%lu, %p, %lu] Data does not match set value\n",
196 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
201 ok(QueryStatus
== STATUS_OBJECT_NAME_NOT_FOUND
, "[%lu, %p, %lu] QueryStatus = %lx\n",
202 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
206 /* String value larger than MAXUSHORT */
208 const ULONG DataLengths
[] = { 0x10000, 0x10002, 0x20000 };
210 RtlInitUnicodeString(&ValueName
, L
"ExistingValue");
211 for (i
= 0; i
< RTL_NUMBER_OF(DataLengths
); i
++)
213 DataLength
= DataLengths
[i
];
214 RtlFillMemoryUlong(LargeBuffer
, DataLength
, '\0B\0A');
215 LargeBuffer
[DataLength
/ sizeof(WCHAR
) - 2] = L
'C';
216 LargeBuffer
[DataLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
217 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, REG_SZ
, LargeBuffer
, DataLength
);
218 ok(Status
== STATUS_SUCCESS
, "[0x%lx] NtSetValueKey failed with %lx", DataLength
, Status
);
220 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
221 Status
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
222 ok(Status
== STATUS_SUCCESS
, "[0x%lx] NtQueryValueKey failed with %lx\n", DataLength
, Status
);
223 ok(PartialInfo
->TitleIndex
== 0, "[0x%lx] TitleIndex = %lu\n", DataLength
, PartialInfo
->TitleIndex
);
224 ok(PartialInfo
->Type
== REG_SZ
, "[0x%lx] Type = %lu\n", DataLength
, PartialInfo
->Type
);
225 ok(PartialInfo
->DataLength
== DataLength
, "[0x%lx] DataLength = %lu\n", DataLength
, PartialInfo
->DataLength
);
226 ok(!memcmp(PartialInfo
->Data
, LargeBuffer
, DataLength
), "[0x%lx] Data does not match set value\n", DataLength
);
230 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer
);
231 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo
);
232 Status
= NtDeleteKey(KeyHandle
);
233 ok(Status
== STATUS_SUCCESS
, "NtDeleteKey returned %lx\n", Status
);
234 Status
= NtClose(KeyHandle
);
235 ok(Status
== STATUS_SUCCESS
, "NtClose returned %lx\n", Status
);
236 Status
= NtClose(ParentKeyHandle
);
237 ok(Status
== STATUS_SUCCESS
, "NtClose returned %lx\n", Status
);