ReactOS 0.4.15-dev-7958-gcd0bb1a
NtSetValueKey.c
Go to the documentation of this file.
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 NtSetValueKey
5 * COPYRIGHT: Copyright 2016-2019 Thomas Faber (thomas.faber@reactos.org)
6 */
7
8#include "precomp.h"
9
10#include <winreg.h>
11
13{
15 HANDLE ParentKeyHandle;
17 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SOFTWARE\\ntdll-apitest-NtSetValueKey");
20 WCHAR Default[] = L"Default";
21 WCHAR Hello[] = L"Hello";
22 WCHAR Empty[] = L"";
23 NTSTATUS QueryStatus;
25 ULONG PartialInfoLength;
28 PWCHAR LargeBuffer;
29 ULONG LargeBufferLength;
30 const struct
31 {
32 ULONG Type;
33 PVOID Data;
35 NTSTATUS StatusExisting;
36 NTSTATUS StatusNew;
37 NTSTATUS StatusExisting2;
38 NTSTATUS StatusNew2;
39 } Tests[] =
40 {
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 */
52 { REG_SZ, NULL, 6, STATUS_INVALID_PARAMETER, STATUS_ACCESS_VIOLATION, /* CM_KEY_VALUE_SMALL+2, null data */
54 { REG_SZ, NULL, 0x7fff0000, STATUS_INVALID_PARAMETER, STATUS_INSUFFICIENT_RESOURCES, /* MI_USER_PROBE_ADDRESS, null data */
56 { REG_SZ, NULL, 0x7fff0001, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, /* MI_USER_PROBE_ADDRESS+1, null data */
58 { REG_SZ, NULL, 0x7fffffff, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, /* <2GB, null data */
60 { REG_SZ, NULL, 0x80000000, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, /* 2GB, null data */
64 };
65 ULONG i;
66
67#if defined(_M_AMD64)
69 {
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");
71 return;
72 }
73#endif
74
75 Status = RtlOpenCurrentUser(READ_CONTROL, &ParentKeyHandle);
76 ok(Status == STATUS_SUCCESS, "RtlOpenCurrentUser returned %lx\n", Status);
77 if (!NT_SUCCESS(Status))
78 {
79 skip("No user key handle\n");
80 return;
81 }
82
84 &KeyName,
86 ParentKeyHandle,
87 NULL);
91 0,
92 NULL,
94 NULL);
95 ok(Status == STATUS_SUCCESS, "NtCreateKey returned %lx\n", Status);
96 if (!NT_SUCCESS(Status))
97 {
98 NtClose(ParentKeyHandle);
99 skip("No key handle\n");
100 return;
101 }
102
103 LargeBufferLength = 0x20000;
104 LargeBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, LargeBufferLength);
105
106 PartialInfoLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[LargeBufferLength]);
107 PartialInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, PartialInfoLength);
108
109 if (LargeBuffer == NULL || PartialInfo == NULL)
110 {
111 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer);
112 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo);
115 NtClose(ParentKeyHandle);
116 skip("Could not allocate buffers\n");
117 return;
118 }
119
120 for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
121 {
122 /*
123 * Existing value
124 */
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);
129
130 /* Set it */
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);
135 else
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);
138
139 /* Check it */
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))
145 {
146 if (NT_SUCCESS(Status))
147 {
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);
156 }
157 else
158 {
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);
167 }
168 }
169
170 /*
171 * New value
172 */
173 /* Make sure it doesn't exist */
174 RtlInitUnicodeString(&ValueName, L"NewValue");
177 "[%lu] NtDeleteValueKey failed with %lx", i, Status);
178
179 /* Set it */
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);
184 else
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);
187
188 /* Check it */
189 RtlZeroMemory(PartialInfo, PartialInfoLength);
190 QueryStatus = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, PartialInfo, PartialInfoLength, &ResultLength);
191 if (NT_SUCCESS(Status))
192 {
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))
196 {
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);
205 }
206 }
207 else
208 {
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);
211 }
212 }
213
214 /* String value larger than MAXUSHORT */
215 {
216 const ULONG DataLengths[] = { 0x10000, 0x10002, 0x20000 };
217
218 RtlInitUnicodeString(&ValueName, L"ExistingValue");
219 for (i = 0; i < RTL_NUMBER_OF(DataLengths); i++)
220 {
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;
226 ok(Status == STATUS_SUCCESS, "[0x%lx] NtSetValueKey failed with %lx", DataLength, Status);
227
228 RtlZeroMemory(PartialInfo, PartialInfoLength);
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);
235 }
236 }
237
238 RtlFreeHeap(GetProcessHeap(), 0, LargeBuffer);
239 RtlFreeHeap(GetProcessHeap(), 0, PartialInfo);
241 ok(Status == STATUS_SUCCESS, "NtDeleteKey returned %lx\n", Status);
243 ok(Status == STATUS_SUCCESS, "NtClose returned %lx\n", Status);
244 Status = NtClose(ParentKeyHandle);
245 ok(Status == STATUS_SUCCESS, "NtClose returned %lx\n", Status);
246}
struct test_data Tests[]
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GetProcessHeap()
Definition: compat.h:736
@ Empty
Definition: npfs.h:125
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define REG_SZ
Definition: layer.c:22
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
#define REG_BINARY
Definition: nt_native.h:1496
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:1014
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DELETE
Definition: nt_native.h:57
#define READ_CONTROL
Definition: nt_native.h:58
#define REG_NONE
Definition: nt_native.h:1492
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define KEY_SET_VALUE
Definition: nt_native.h:1017
NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle)
Definition: ntapi.c:408
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define UNICODE_NULL
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define L(x)
Definition: ntvdm.h:50
int winetest_interactive
#define STATUS_SUCCESS
Definition: shellext.h:65
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
__wchar_t WCHAR
Definition: xmlstorage.h:180