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