[USP10_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / kmtests / ntos_ob / ObSymbolicLink.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test for Zw*SymbolicLinkObject
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define NDEBUG
11 #include <debug.h>
12
13 static
14 VOID
15 TestQueryLink(
16 _In_ HANDLE LinkHandle,
17 _In_ PCUNICODE_STRING ExpectedTarget)
18 {
19 NTSTATUS Status;
20 WCHAR QueriedTargetBuffer[32];
21 UNICODE_STRING QueriedTarget;
22 ULONG ResultLength;
23 PULONG pResultLength;
24 ULONG i;
25
26 for (i = 0; i < 2; i++)
27 {
28 if (i == 0)
29 {
30 pResultLength = &ResultLength;
31 }
32 else
33 {
34 pResultLength = NULL;
35 }
36
37 /* Query with NULL Buffer just gives us the length */
38 RtlInitEmptyUnicodeString(&QueriedTarget, NULL, 0);
39 if (pResultLength) ResultLength = 0x55555555;
40 Status = ZwQuerySymbolicLinkObject(LinkHandle,
41 &QueriedTarget,
42 pResultLength);
43 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
44 ok_eq_uint(QueriedTarget.Length, 0);
45 ok_eq_uint(QueriedTarget.MaximumLength, 0);
46 ok_eq_pointer(QueriedTarget.Buffer, NULL);
47 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
48
49 /* Query with Length-1 buffer */
50 RtlInitEmptyUnicodeString(&QueriedTarget,
51 QueriedTargetBuffer,
52 ExpectedTarget->Length - 1);
53 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
54 if (pResultLength) ResultLength = 0x55555555;
55 Status = ZwQuerySymbolicLinkObject(LinkHandle,
56 &QueriedTarget,
57 pResultLength);
58 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
59 ok_eq_uint(QueriedTarget.Length, 0);
60 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length - 1);
61 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
62 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
63 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
64
65 /* Query with Length buffer */
66 RtlInitEmptyUnicodeString(&QueriedTarget,
67 QueriedTargetBuffer,
68 ExpectedTarget->Length);
69 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
70 if (pResultLength) ResultLength = 0x55555555;
71 Status = ZwQuerySymbolicLinkObject(LinkHandle,
72 &QueriedTarget,
73 pResultLength);
74 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length);
75 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
76 if (pResultLength &&
77 QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength)
78 {
79 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
80 ok_eq_uint(QueriedTarget.Length, 0);
81 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
82 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
83 }
84 else
85 {
86 ok_eq_hex(Status, STATUS_SUCCESS);
87 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
88 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
89 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
90 }
91
92 /* Query with Length+1 buffer */
93 RtlInitEmptyUnicodeString(&QueriedTarget,
94 QueriedTargetBuffer,
95 ExpectedTarget->Length + 1);
96 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
97 if (pResultLength) ResultLength = 0x55555555;
98 Status = ZwQuerySymbolicLinkObject(LinkHandle,
99 &QueriedTarget,
100 pResultLength);
101 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + 1);
102 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
103 if (pResultLength &&
104 QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength)
105 {
106 ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
107 ok_eq_uint(QueriedTarget.Length, 0);
108 ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
109 if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
110 }
111 else
112 {
113 ok_eq_hex(Status, STATUS_SUCCESS);
114 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
115 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
116 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
117 }
118
119 /* Query with Length+2 buffer */
120 RtlInitEmptyUnicodeString(&QueriedTarget,
121 QueriedTargetBuffer,
122 ExpectedTarget->Length + sizeof(WCHAR));
123 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
124 if (pResultLength) ResultLength = 0x55555555;
125 Status = ZwQuerySymbolicLinkObject(LinkHandle,
126 &QueriedTarget,
127 pResultLength);
128 ok_eq_hex(Status, STATUS_SUCCESS);
129 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
130 ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + sizeof(WCHAR));
131 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
132 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
133 if (pResultLength)
134 {
135 if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL))
136 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0);
137 ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
138 }
139 else
140 {
141 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
142 }
143
144 /* Query with full-sized buffer */
145 RtlInitEmptyUnicodeString(&QueriedTarget,
146 QueriedTargetBuffer,
147 sizeof(QueriedTargetBuffer));
148 RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
149 if (pResultLength) ResultLength = 0x55555555;
150 Status = ZwQuerySymbolicLinkObject(LinkHandle,
151 &QueriedTarget,
152 pResultLength);
153 ok_eq_hex(Status, STATUS_SUCCESS);
154 ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
155 ok_eq_uint(QueriedTarget.MaximumLength, sizeof(QueriedTargetBuffer));
156 ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
157 ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
158 if (pResultLength)
159 {
160 if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL))
161 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0);
162 ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
163 }
164 else
165 {
166 ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
167 }
168 }
169 }
170
171 START_TEST(ObSymbolicLink)
172 {
173 NTSTATUS Status;
174 HANDLE LinkHandle;
175 HANDLE LinkHandle2;
176 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\Device\\ObSymbolicLinkKmtestNamedPipe");
177 OBJECT_ATTRIBUTES ObjectAttributes;
178 UNICODE_STRING DefaultLinkTarget = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe");
179 UNICODE_STRING LinkTarget = DefaultLinkTarget;
180
181 InitializeObjectAttributes(&ObjectAttributes,
182 &LinkName,
183 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
184 NULL,
185 NULL);
186 LinkHandle = KmtInvalidPointer;
187 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
188 SYMBOLIC_LINK_QUERY,
189 &ObjectAttributes);
190 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
191 ok_eq_pointer(LinkHandle, NULL);
192 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
193
194 /* Create it */
195 LinkHandle = KmtInvalidPointer;
196 Status = ZwCreateSymbolicLinkObject(&LinkHandle,
197 SYMBOLIC_LINK_QUERY,
198 &ObjectAttributes,
199 &LinkTarget);
200 ok_eq_hex(Status, STATUS_SUCCESS);
201 ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
202 if (skip(NT_SUCCESS(Status), "Failed to create link\n"))
203 {
204 return;
205 }
206
207 /* Now we should be able to open it */
208 LinkHandle2 = KmtInvalidPointer;
209 Status = ZwOpenSymbolicLinkObject(&LinkHandle2,
210 SYMBOLIC_LINK_QUERY,
211 &ObjectAttributes);
212 ok_eq_hex(Status, STATUS_SUCCESS);
213 ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2);
214 if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n"))
215 {
216 TestQueryLink(LinkHandle2, &LinkTarget);
217 ObCloseHandle(LinkHandle2, KernelMode);
218 }
219
220 /* Close it */
221 ObCloseHandle(LinkHandle, KernelMode);
222
223 /* Open fails again */
224 LinkHandle = KmtInvalidPointer;
225 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
226 SYMBOLIC_LINK_QUERY,
227 &ObjectAttributes);
228 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
229 ok_eq_pointer(LinkHandle, NULL);
230 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
231
232 /* Create with broken LinkTarget */
233 LinkHandle = KmtInvalidPointer;
234 LinkTarget.Buffer = NULL;
235 Status = ZwCreateSymbolicLinkObject(&LinkHandle,
236 SYMBOLIC_LINK_QUERY,
237 &ObjectAttributes,
238 &LinkTarget);
239 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
240 ok(LinkHandle == KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
241 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
242
243 /* Since it failed, open should also fail */
244 LinkHandle = KmtInvalidPointer;
245 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
246 SYMBOLIC_LINK_QUERY,
247 &ObjectAttributes);
248 ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
249 ok_eq_pointer(LinkHandle, NULL);
250 if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
251
252 /* Create with valid, but not null-terminated LinkTarget */
253 LinkTarget = DefaultLinkTarget;
254 LinkTarget.MaximumLength = LinkTarget.Length;
255 LinkHandle = KmtInvalidPointer;
256 Status = ZwCreateSymbolicLinkObject(&LinkHandle,
257 SYMBOLIC_LINK_QUERY,
258 &ObjectAttributes,
259 &LinkTarget);
260 ok_eq_hex(Status, STATUS_SUCCESS);
261 ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
262 if (skip(NT_SUCCESS(Status), "Failed to create link\n"))
263 {
264 return;
265 }
266
267 /* Now we should be able to open it */
268 LinkHandle2 = KmtInvalidPointer;
269 Status = ZwOpenSymbolicLinkObject(&LinkHandle2,
270 SYMBOLIC_LINK_QUERY,
271 &ObjectAttributes);
272 ok_eq_hex(Status, STATUS_SUCCESS);
273 ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2);
274 if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n"))
275 {
276 TestQueryLink(LinkHandle2, &LinkTarget);
277 ObCloseHandle(LinkHandle2, KernelMode);
278 }
279
280 /* Close it */
281 ObCloseHandle(LinkHandle, KernelMode);
282 }