mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 23:28:58 +00:00
283 lines
12 KiB
C
283 lines
12 KiB
C
![]() |
/*
|
||
|
* PROJECT: ReactOS kernel-mode tests
|
||
|
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
|
||
|
* PURPOSE: Kernel-Mode Test for Zw*SymbolicLinkObject
|
||
|
* PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
|
||
|
*/
|
||
|
|
||
|
#include <kmt_test.h>
|
||
|
|
||
|
#define NDEBUG
|
||
|
#include <debug.h>
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
TestQueryLink(
|
||
|
_In_ HANDLE LinkHandle,
|
||
|
_In_ PCUNICODE_STRING ExpectedTarget)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
WCHAR QueriedTargetBuffer[32];
|
||
|
UNICODE_STRING QueriedTarget;
|
||
|
ULONG ResultLength;
|
||
|
PULONG pResultLength;
|
||
|
ULONG i;
|
||
|
|
||
|
for (i = 0; i < 2; i++)
|
||
|
{
|
||
|
if (i == 0)
|
||
|
{
|
||
|
pResultLength = &ResultLength;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pResultLength = NULL;
|
||
|
}
|
||
|
|
||
|
/* Query with NULL Buffer just gives us the length */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget, NULL, 0);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
|
||
|
ok_eq_uint(QueriedTarget.Length, 0);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, 0);
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, NULL);
|
||
|
if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
|
||
|
/* Query with Length-1 buffer */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget,
|
||
|
QueriedTargetBuffer,
|
||
|
ExpectedTarget->Length - 1);
|
||
|
RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
|
||
|
ok_eq_uint(QueriedTarget.Length, 0);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length - 1);
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
|
||
|
ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
|
||
|
if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
|
||
|
/* Query with Length buffer */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget,
|
||
|
QueriedTargetBuffer,
|
||
|
ExpectedTarget->Length);
|
||
|
RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length);
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
|
||
|
if (pResultLength &&
|
||
|
QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength)
|
||
|
{
|
||
|
ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
|
||
|
ok_eq_uint(QueriedTarget.Length, 0);
|
||
|
ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
|
||
|
if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
|
||
|
ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
|
||
|
}
|
||
|
|
||
|
/* Query with Length+1 buffer */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget,
|
||
|
QueriedTargetBuffer,
|
||
|
ExpectedTarget->Length + 1);
|
||
|
RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + 1);
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
|
||
|
if (pResultLength &&
|
||
|
QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength)
|
||
|
{
|
||
|
ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL);
|
||
|
ok_eq_uint(QueriedTarget.Length, 0);
|
||
|
ok_eq_uint(QueriedTarget.Buffer[0], 0x5555);
|
||
|
if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
|
||
|
ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
|
||
|
}
|
||
|
|
||
|
/* Query with Length+2 buffer */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget,
|
||
|
QueriedTargetBuffer,
|
||
|
ExpectedTarget->Length + sizeof(WCHAR));
|
||
|
RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + sizeof(WCHAR));
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
|
||
|
ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
|
||
|
if (pResultLength)
|
||
|
{
|
||
|
if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL))
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0);
|
||
|
ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
|
||
|
}
|
||
|
|
||
|
/* Query with full-sized buffer */
|
||
|
RtlInitEmptyUnicodeString(&QueriedTarget,
|
||
|
QueriedTargetBuffer,
|
||
|
sizeof(QueriedTargetBuffer));
|
||
|
RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55);
|
||
|
if (pResultLength) ResultLength = 0x55555555;
|
||
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
||
|
&QueriedTarget,
|
||
|
pResultLength);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length);
|
||
|
ok_eq_uint(QueriedTarget.MaximumLength, sizeof(QueriedTargetBuffer));
|
||
|
ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer);
|
||
|
ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget);
|
||
|
if (pResultLength)
|
||
|
{
|
||
|
if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL))
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0);
|
||
|
ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
START_TEST(ObSymbolicLink)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
HANDLE LinkHandle;
|
||
|
HANDLE LinkHandle2;
|
||
|
UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\Device\\ObSymbolicLinkKmtestNamedPipe");
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
UNICODE_STRING DefaultLinkTarget = RTL_CONSTANT_STRING(L"\\Device\\NamedPipe");
|
||
|
UNICODE_STRING LinkTarget = DefaultLinkTarget;
|
||
|
|
||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||
|
&LinkName,
|
||
|
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes);
|
||
|
ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
|
||
|
ok_eq_pointer(LinkHandle, NULL);
|
||
|
if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
|
||
|
|
||
|
/* Create it */
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
Status = ZwCreateSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes,
|
||
|
&LinkTarget);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
|
||
|
if (skip(NT_SUCCESS(Status), "Failed to create link\n"))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Now we should be able to open it */
|
||
|
LinkHandle2 = KmtInvalidPointer;
|
||
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle2,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2);
|
||
|
if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n"))
|
||
|
{
|
||
|
TestQueryLink(LinkHandle2, &LinkTarget);
|
||
|
ObCloseHandle(LinkHandle2, KernelMode);
|
||
|
}
|
||
|
|
||
|
/* Close it */
|
||
|
ObCloseHandle(LinkHandle, KernelMode);
|
||
|
|
||
|
/* Open fails again */
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes);
|
||
|
ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
|
||
|
ok_eq_pointer(LinkHandle, NULL);
|
||
|
if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
|
||
|
|
||
|
/* Create with broken LinkTarget */
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
LinkTarget.Buffer = NULL;
|
||
|
Status = ZwCreateSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes,
|
||
|
&LinkTarget);
|
||
|
ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
|
||
|
ok(LinkHandle == KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
|
||
|
if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
|
||
|
|
||
|
/* Since it failed, open should also fail */
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes);
|
||
|
ok_eq_hex(Status, STATUS_OBJECT_NAME_NOT_FOUND);
|
||
|
ok_eq_pointer(LinkHandle, NULL);
|
||
|
if (NT_SUCCESS(Status)) ObCloseHandle(LinkHandle, KernelMode);
|
||
|
|
||
|
/* Create with valid, but not null-terminated LinkTarget */
|
||
|
LinkTarget = DefaultLinkTarget;
|
||
|
LinkTarget.MaximumLength = LinkTarget.Length;
|
||
|
LinkHandle = KmtInvalidPointer;
|
||
|
Status = ZwCreateSymbolicLinkObject(&LinkHandle,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes,
|
||
|
&LinkTarget);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok(LinkHandle != NULL && LinkHandle != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle);
|
||
|
if (skip(NT_SUCCESS(Status), "Failed to create link\n"))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Now we should be able to open it */
|
||
|
LinkHandle2 = KmtInvalidPointer;
|
||
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle2,
|
||
|
SYMBOLIC_LINK_QUERY,
|
||
|
&ObjectAttributes);
|
||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||
|
ok(LinkHandle2 != NULL && LinkHandle2 != KmtInvalidPointer, "LinkHandle = %p\n", LinkHandle2);
|
||
|
if (!skip(NT_SUCCESS(Status), "Failed to open symlink\n"))
|
||
|
{
|
||
|
TestQueryLink(LinkHandle2, &LinkTarget);
|
||
|
ObCloseHandle(LinkHandle2, KernelMode);
|
||
|
}
|
||
|
|
||
|
/* Close it */
|
||
|
ObCloseHandle(LinkHandle, KernelMode);
|
||
|
}
|