ReactOS  0.4.14-dev-317-g96040ec
ObSymbolicLink.c
Go to the documentation of this file.
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
16  _In_ HANDLE LinkHandle,
17  _In_ PCUNICODE_STRING ExpectedTarget)
18 {
20  WCHAR QueriedTargetBuffer[32];
21  UNICODE_STRING QueriedTarget;
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);
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);
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  {
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  {
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  {
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  {
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);
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);
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 {
174  HANDLE LinkHandle;
175  HANDLE LinkHandle2;
176  UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\Device\\ObSymbolicLinkKmtestNamedPipe");
178  UNICODE_STRING DefaultLinkTarget = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe");
179  UNICODE_STRING LinkTarget = DefaultLinkTarget;
180 
182  &LinkName,
184  NULL,
185  NULL);
186  LinkHandle = KmtInvalidPointer;
187  Status = ZwOpenSymbolicLinkObject(&LinkHandle,
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,
199  &LinkTarget);
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,
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,
229  ok_eq_pointer(LinkHandle, NULL);
230  if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
231 
232  /* Create with broken LinkTarget */
233  LinkHandle = KmtInvalidPointer;
235  Status = ZwCreateSymbolicLinkObject(&LinkHandle,
238  &LinkTarget);
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,
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;
255  LinkHandle = KmtInvalidPointer;
256  Status = ZwCreateSymbolicLinkObject(&LinkHandle,
259  &LinkTarget);
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,
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 }
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define ok_eq_ulong(value, expected)
#define KmtInvalidPointer
Definition: kmt_test.h:275
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define ok_eq_pointer(value, expected)
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292
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 UNICODE_NULL
smooth NULL
Definition: ftsmooth.c:416
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSYSAPI NTSTATUS NTAPI ZwCreateSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ PUNICODE_STRING Name)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
static const WCHAR L[]
Definition: oid.c:1250
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
#define ok(value,...)
Definition: atltest.h:57
unsigned int * PULONG
Definition: retypes.h:1
#define skip(...)
Definition: atltest.h:64
unsigned int ULONG
Definition: retypes.h:1
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define ok_eq_hex(value, expected)
#define ok_eq_uint(value, expected)
Definition: kmt_test.h:239
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14