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 */
68 if (!winetest_interactive
)
70 skip("ROSTESTS-365: Skipping ntdll_apitest:NtSetValueKey because it hangs on Windows Server 2003 x64-Testbot. Set winetest_interactive to run it anyway.\n");
75 Status
= RtlOpenCurrentUser(READ_CONTROL
, &ParentKeyHandle
);
76 ok(Status
== STATUS_SUCCESS
, "RtlOpenCurrentUser returned %lx\n", Status
);
77 if (!NT_SUCCESS(Status
))
79 skip("No user key handle\n");
83 InitializeObjectAttributes(&ObjectAttributes
,
88 Status
= NtCreateKey(&KeyHandle
,
89 KEY_QUERY_VALUE
| KEY_SET_VALUE
| DELETE
,
95 ok(Status
== STATUS_SUCCESS
, "NtCreateKey returned %lx\n", Status
);
96 if (!NT_SUCCESS(Status
))
98 NtClose(ParentKeyHandle
);
99 skip("No key handle\n");
103 LargeBufferLength
= 0x20000;
104 LargeBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, LargeBufferLength
);
106 PartialInfoLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[LargeBufferLength
]);
107 PartialInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PartialInfoLength
);
109 if (LargeBuffer
== NULL
|| PartialInfo
== NULL
)
111 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer
);
112 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo
);
113 NtDeleteKey(KeyHandle
);
115 NtClose(ParentKeyHandle
);
116 skip("Could not allocate buffers\n");
120 for (i
= 0; i
< RTL_NUMBER_OF(Tests
); i
++)
125 /* Make sure it exists */
126 RtlInitUnicodeString(&ValueName
, L
"ExistingValue");
127 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, REG_SZ
, Default
, sizeof(Default
));
128 ok(Status
== STATUS_SUCCESS
, "[%lu] NtSetValueKey failed with %lx", i
, Status
);
131 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
132 if (Status
== Tests
[i
].StatusExisting2
)
133 ok(Status
== Tests
[i
].StatusExisting
|| Status
== Tests
[i
].StatusExisting2
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx or %lx\n",
134 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusExisting
, Tests
[i
].StatusExisting2
);
136 ok(Status
== Tests
[i
].StatusExisting
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx\n",
137 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusExisting
);
140 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
141 QueryStatus
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
142 ok(QueryStatus
== STATUS_SUCCESS
, "[%lu, %p, %lu] NtQueryValueKey failed with %lx\n",
143 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
144 if (NT_SUCCESS(QueryStatus
))
146 if (NT_SUCCESS(Status
))
148 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
149 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
150 ok(PartialInfo
->Type
== Tests
[i
].Type
, "[%lu, %p, %lu] Type = %lu\n",
151 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
152 ok(PartialInfo
->DataLength
== Tests
[i
].DataSize
, "[%lu, %p, %lu] DataLength = %lu\n",
153 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
154 ok(!memcmp(PartialInfo
->Data
, Tests
[i
].Data
, Tests
[i
].DataSize
), "[%lu, %p, %lu] Data does not match set value\n",
155 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
159 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
160 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
161 ok(PartialInfo
->Type
== REG_SZ
, "[%lu, %p, %lu] Type = %lu\n",
162 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
163 ok(PartialInfo
->DataLength
== sizeof(Default
), "[%lu, %p, %lu] DataLength = %lu\n",
164 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
165 ok(!memcmp(PartialInfo
->Data
, Default
, sizeof(Default
)), "[%lu, %p, %lu] Data does not match default\n",
166 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
173 /* Make sure it doesn't exist */
174 RtlInitUnicodeString(&ValueName
, L
"NewValue");
175 Status
= NtDeleteValueKey(KeyHandle
, &ValueName
);
176 ok(Status
== STATUS_SUCCESS
|| Status
== STATUS_OBJECT_NAME_NOT_FOUND
,
177 "[%lu] NtDeleteValueKey failed with %lx", i
, Status
);
180 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
181 if (Tests
[i
].StatusNew2
)
182 ok(Status
== Tests
[i
].StatusNew
|| Status
== Tests
[i
].StatusNew2
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx or %lx\n",
183 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusNew
, Tests
[i
].StatusNew2
);
185 ok(Status
== Tests
[i
].StatusNew
, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx\n",
186 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, Status
, Tests
[i
].StatusNew
);
189 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
190 QueryStatus
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
191 if (NT_SUCCESS(Status
))
193 ok(QueryStatus
== STATUS_SUCCESS
, "[%lu, %p, %lu] NtQueryValueKey failed with %lx\n",
194 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
195 if (NT_SUCCESS(QueryStatus
))
197 ok(PartialInfo
->TitleIndex
== 0, "[%lu, %p, %lu] TitleIndex = %lu\n",
198 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->TitleIndex
);
199 ok(PartialInfo
->Type
== Tests
[i
].Type
, "[%lu, %p, %lu] Type = %lu\n",
200 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->Type
);
201 ok(PartialInfo
->DataLength
== Tests
[i
].DataSize
, "[%lu, %p, %lu] DataLength = %lu\n",
202 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, PartialInfo
->DataLength
);
203 ok(!memcmp(PartialInfo
->Data
, Tests
[i
].Data
, Tests
[i
].DataSize
), "[%lu, %p, %lu] Data does not match set value\n",
204 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
);
209 ok(QueryStatus
== STATUS_OBJECT_NAME_NOT_FOUND
, "[%lu, %p, %lu] QueryStatus = %lx\n",
210 Tests
[i
].Type
, Tests
[i
].Data
, Tests
[i
].DataSize
, QueryStatus
);
214 /* String value larger than MAXUSHORT */
216 const ULONG DataLengths
[] = { 0x10000, 0x10002, 0x20000 };
218 RtlInitUnicodeString(&ValueName
, L
"ExistingValue");
219 for (i
= 0; i
< RTL_NUMBER_OF(DataLengths
); i
++)
221 DataLength
= DataLengths
[i
];
222 RtlFillMemoryUlong(LargeBuffer
, DataLength
, '\0B\0A');
223 LargeBuffer
[DataLength
/ sizeof(WCHAR
) - 2] = L
'C';
224 LargeBuffer
[DataLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
225 Status
= NtSetValueKey(KeyHandle
, &ValueName
, 0, REG_SZ
, LargeBuffer
, DataLength
);
226 ok(Status
== STATUS_SUCCESS
, "[0x%lx] NtSetValueKey failed with %lx", DataLength
, Status
);
228 RtlZeroMemory(PartialInfo
, PartialInfoLength
);
229 Status
= NtQueryValueKey(KeyHandle
, &ValueName
, KeyValuePartialInformation
, PartialInfo
, PartialInfoLength
, &ResultLength
);
230 ok(Status
== STATUS_SUCCESS
, "[0x%lx] NtQueryValueKey failed with %lx\n", DataLength
, Status
);
231 ok(PartialInfo
->TitleIndex
== 0, "[0x%lx] TitleIndex = %lu\n", DataLength
, PartialInfo
->TitleIndex
);
232 ok(PartialInfo
->Type
== REG_SZ
, "[0x%lx] Type = %lu\n", DataLength
, PartialInfo
->Type
);
233 ok(PartialInfo
->DataLength
== DataLength
, "[0x%lx] DataLength = %lu\n", DataLength
, PartialInfo
->DataLength
);
234 ok(!memcmp(PartialInfo
->Data
, LargeBuffer
, DataLength
), "[0x%lx] Data does not match set value\n", DataLength
);
238 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer
);
239 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo
);
240 Status
= NtDeleteKey(KeyHandle
);
241 ok(Status
== STATUS_SUCCESS
, "NtDeleteKey returned %lx\n", Status
);
242 Status
= NtClose(KeyHandle
);
243 ok(Status
== STATUS_SUCCESS
, "NtClose returned %lx\n", Status
);
244 Status
= NtClose(ParentKeyHandle
);
245 ok(Status
== STATUS_SUCCESS
, "NtClose returned %lx\n", Status
);