Author: tfaber
Date: Wed Apr 9 18:00:33 2014
New Revision: 62695
URL:
http://svn.reactos.org/svn/reactos?rev=62695&view=rev
Log:
[KMTESTS:NPFS]
- Add some (pretty incomplete) tests for NPFS Create, Connect and Read/Write operations
CORE-7451
Added:
trunk/rostests/kmtests/npfs/ (with props)
trunk/rostests/kmtests/npfs/NpfsConnect.c (with props)
trunk/rostests/kmtests/npfs/NpfsCreate.c (with props)
trunk/rostests/kmtests/npfs/NpfsHelpers.c (with props)
trunk/rostests/kmtests/npfs/NpfsReadWrite.c (with props)
trunk/rostests/kmtests/npfs/npfs.h (with props)
Modified:
trunk/rostests/kmtests/CMakeLists.txt
trunk/rostests/kmtests/kmtest_drv/testlist.c
Modified: trunk/rostests/kmtests/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/CMakeLists.txt?re…
==============================================================================
--- trunk/rostests/kmtests/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/rostests/kmtests/CMakeLists.txt [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -28,6 +28,10 @@
example/Example.c
example/KernelType.c
+ npfs/NpfsConnect.c
+ npfs/NpfsCreate.c
+ npfs/NpfsHelpers.c
+ npfs/NpfsReadWrite.c
ntos_ex/ExCallback.c
ntos_ex/ExDoubleList.c
ntos_ex/ExFastMutex.c
Modified: trunk/rostests/kmtests/kmtest_drv/testlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/kmtest_drv/testli…
==============================================================================
--- trunk/rostests/kmtests/kmtest_drv/testlist.c [iso-8859-1] (original)
+++ trunk/rostests/kmtests/kmtest_drv/testlist.c [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -38,6 +38,9 @@
KMT_TESTFUNC Test_KeTimer;
KMT_TESTFUNC Test_KernelType;
KMT_TESTFUNC Test_MmSection;
+KMT_TESTFUNC Test_NpfsConnect;
+KMT_TESTFUNC Test_NpfsCreate;
+KMT_TESTFUNC Test_NpfsReadWrite;
KMT_TESTFUNC Test_ObReference;
KMT_TESTFUNC Test_ObType;
KMT_TESTFUNC Test_ObTypeClean;
@@ -89,6 +92,9 @@
{ "KeTimer", Test_KeTimer },
{ "-KernelType", Test_KernelType },
{ "MmSection", Test_MmSection },
+ { "NpfsConnect", Test_NpfsConnect },
+ { "NpfsCreate", Test_NpfsCreate },
+ { "NpfsReadWrite", Test_NpfsReadWrite },
{ "ObReference", Test_ObReference },
{ "ObType", Test_ObType },
{ "-ObTypeClean", Test_ObTypeClean },
Propchange: trunk/rostests/kmtests/npfs/
------------------------------------------------------------------------------
--- bugtraq:logregex (added)
+++ bugtraq:logregex Wed Apr 9 18:00:33 2014
@@ -0,0 +1,2 @@
+([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))?
+(\d+)
Propchange: trunk/rostests/kmtests/npfs/
------------------------------------------------------------------------------
bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/rostests/kmtests/npfs/
------------------------------------------------------------------------------
bugtraq:url =
http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: trunk/rostests/kmtests/npfs/
------------------------------------------------------------------------------
tsvn:logminsize = 10
Added: trunk/rostests/kmtests/npfs/NpfsConnect.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/npfs/NpfsConnect.…
==============================================================================
--- trunk/rostests/kmtests/npfs/NpfsConnect.c (added)
+++ trunk/rostests/kmtests/npfs/NpfsConnect.c [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -0,0 +1,272 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite NPFS Connect test
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ */
+
+#include <kmt_test.h>
+#include "npfs.h"
+
+#define MAX_INSTANCES 5
+#define IN_QUOTA 4096
+#define OUT_QUOTA 4096
+
+#define CheckServer(ServerHandle, State) \
+ NpCheckServerPipe(ServerHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, 0, \
+ OUT_QUOTA, OUT_QUOTA, \
+ State)
+
+#define CheckClient(ClientHandle, State) \
+ NpCheckClientPipe(ClientHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, 0, \
+ OUT_QUOTA, OUT_QUOTA, \
+ State)
+
+static
+VOID
+ConnectPipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ HANDLE ClientHandle;
+
+ ClientHandle = NULL;
+ Context->Connect.Status = NpOpenPipe(&ClientHandle,
+ Context->Connect.PipePath,
+ FILE_PIPE_FULL_DUPLEX);
+ Context->Connect.ClientHandle = ClientHandle;
+}
+
+static
+VOID
+ListenPipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle);
+}
+
+static
+BOOLEAN
+CheckConnectPipe(
+ IN PTHREAD_CONTEXT Context,
+ IN PCWSTR PipePath,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = ConnectPipe;
+ Context->Connect.PipePath = PipePath;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static
+BOOLEAN
+CheckListenPipe(
+ IN PTHREAD_CONTEXT Context,
+ IN HANDLE ServerHandle,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = ListenPipe;
+ Context->Listen.ServerHandle = ServerHandle;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static
+VOID
+TestConnect(
+ IN HANDLE ServerHandle,
+ IN PCWSTR PipePath)
+{
+ NTSTATUS Status;
+ THREAD_CONTEXT ConnectContext;
+ THREAD_CONTEXT ListenContext;
+ BOOLEAN Okay;
+ HANDLE ClientHandle;
+
+ StartWorkerThread(&ConnectContext);
+ StartWorkerThread(&ListenContext);
+
+ /* Server should start out listening */
+ CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
+
+ /* Connect a client */
+ ClientHandle = NULL;
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ {
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ }
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Connect another client */
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Disconnecting the client should fail */
+ Status = NpDisconnectPipe(ClientHandle);
+ ok_eq_hex(Status, STATUS_ILLEGAL_FUNCTION);
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Listening on the client should fail */
+ Status = NpListenPipe(ClientHandle);
+ ok_eq_hex(Status, STATUS_ILLEGAL_FUNCTION);
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Close client */
+ if (ClientHandle)
+ ObCloseHandle(ClientHandle, KernelMode);
+ CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
+
+ /* Connecting a client now should fail */
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
+ CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
+
+ /* Listening should fail */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_true(Okay, "CheckListenPipe returned");
+ if (!skip(Okay, "Listen succeeded unexpectedly\n"))
+ CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
+
+ /* Disconnect server */
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+
+ /* Disconnecting again should fail */
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_PIPE_DISCONNECTED);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+
+ /* Connecting a client now should fail */
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+
+ /**************************************************************************/
+ /* Now listen again */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_false(Okay, "CheckListenPipe returned");
+ //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
+
+ /* Connect client */
+ ClientHandle = NULL;
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ {
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ }
+ Okay = WaitForWork(&ListenContext, 100);
+ ok_bool_true(Okay, "WaitForWork returned");
+ ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Listening again should fail */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_true(Okay, "CheckListenPipe returned");
+ ok_eq_hex(ListenContext.Listen.Status, STATUS_PIPE_CONNECTED);
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Disconnect server */
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+
+ /* Close client */
+ if (ClientHandle)
+ ObCloseHandle(ClientHandle, KernelMode);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+
+ /**************************************************************************/
+ /* Listen once more */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_false(Okay, "CheckListenPipe returned");
+ //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
+
+ /* Connect client */
+ ClientHandle = NULL;
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ if (NT_SUCCESS(ConnectContext.Connect.Status))
+ {
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ }
+ Okay = WaitForWork(&ListenContext, 100);
+ ok_bool_true(Okay, "WaitForWork returned");
+ ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /* Close server */
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ CheckClient(ClientHandle, FILE_PIPE_CLOSING_STATE);
+
+ /* Close client */
+ if (ClientHandle)
+ ObCloseHandle(ClientHandle, KernelMode);
+
+ FinishWorkerThread(&ListenContext);
+ FinishWorkerThread(&ConnectContext);
+}
+
+static KSTART_ROUTINE RunTest;
+static
+VOID
+NTAPI
+RunTest(
+ IN PVOID Context)
+{
+ NTSTATUS Status;
+ HANDLE ServerHandle;
+
+ UNREFERENCED_PARAMETER(Context);
+
+ ServerHandle = INVALID_HANDLE_VALUE;
+ Status = NpCreatePipe(&ServerHandle,
+ DEVICE_NAMED_PIPE L"\\KmtestNpfsConnectTestPipe",
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MAX_INSTANCES,
+ IN_QUOTA,
+ OUT_QUOTA);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ok(ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE,
"ServerHandle = %p\n", ServerHandle);
+ if (!skip(NT_SUCCESS(Status) && ServerHandle != NULL && ServerHandle
!= INVALID_HANDLE_VALUE, "No pipe\n"))
+ {
+ CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
+ TestConnect(ServerHandle, DEVICE_NAMED_PIPE
L"\\KmtestNpfsConnectTestPipe");
+ }
+}
+
+START_TEST(NpfsConnect)
+{
+ PKTHREAD Thread;
+
+ Thread = KmtStartThread(RunTest, NULL);
+ KmtFinishThread(Thread, NULL);
+}
Propchange: trunk/rostests/kmtests/npfs/NpfsConnect.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/kmtests/npfs/NpfsCreate.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/npfs/NpfsCreate.c…
==============================================================================
--- trunk/rostests/kmtests/npfs/NpfsCreate.c (added)
+++ trunk/rostests/kmtests/npfs/NpfsCreate.c [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -0,0 +1,118 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite NPFS Create test
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ */
+
+#include <kmt_test.h>
+#include "npfs.h"
+
+static
+VOID
+TestCreateNamedPipe(VOID)
+{
+ NTSTATUS Status;
+ HANDLE ServerHandle;
+ ULONG MaxInstances;
+ ULONG InQuota, OutQuota;
+ ULONG Quotas[] = { 0, 1, 2, 1024, PAGE_SIZE - 1, PAGE_SIZE, PAGE_SIZE + 1, 2 *
PAGE_SIZE, 8 * PAGE_SIZE, 64 * PAGE_SIZE, 64 * PAGE_SIZE + 1, 128 * PAGE_SIZE };
+ ULONG i;
+ LARGE_INTEGER Timeout;
+
+ /* Invalid pipe name */
+ MaxInstances = 1;
+ InQuota = 4096;
+ OutQuota = 4096;
+ ServerHandle = INVALID_HANDLE_VALUE;
+ Status = NpCreatePipe(&ServerHandle,
+ DEVICE_NAMED_PIPE L"",
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MaxInstances,
+ InQuota,
+ OutQuota);
+ ok_eq_hex(Status, STATUS_OBJECT_NAME_INVALID);
+ ok_eq_pointer(ServerHandle, INVALID_HANDLE_VALUE);
+ if (ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE)
+ ObCloseHandle(ServerHandle, KernelMode);
+
+ ServerHandle = INVALID_HANDLE_VALUE;
+ Status = NpCreatePipe(&ServerHandle,
+ DEVICE_NAMED_PIPE L"\\",
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MaxInstances,
+ InQuota,
+ OutQuota);
+ ok_eq_hex(Status, STATUS_OBJECT_NAME_INVALID);
+ ok_eq_pointer(ServerHandle, INVALID_HANDLE_VALUE);
+ if (ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE)
+ ObCloseHandle(ServerHandle, KernelMode);
+
+ ServerHandle = INVALID_HANDLE_VALUE;
+ Status = NpCreatePipe(&ServerHandle,
+ DEVICE_NAMED_PIPE L"\\\\",
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MaxInstances,
+ InQuota,
+ OutQuota);
+ ok_eq_hex(Status, STATUS_OBJECT_NAME_INVALID);
+ ok_eq_pointer(ServerHandle, INVALID_HANDLE_VALUE);
+ if (ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE)
+ ObCloseHandle(ServerHandle, KernelMode);
+
+ /* Test in-quota */
+ MaxInstances = 1;
+ OutQuota = 4096;
+ for (i = 0; i < RTL_NUMBER_OF(Quotas); i++)
+ {
+ InQuota = Quotas[i];
+ ServerHandle = INVALID_HANDLE_VALUE;
+ Status = NpCreatePipe(&ServerHandle,
+ DEVICE_NAMED_PIPE L"\\KmtestNpfsCreateTestPipe",
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MaxInstances,
+ InQuota,
+ OutQuota);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ok(ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE,
"ServerHandle = %p\n", ServerHandle);
+ if (!skip(NT_SUCCESS(Status) && ServerHandle != NULL &&
ServerHandle != INVALID_HANDLE_VALUE, "No pipe\n"))
+ {
+ NpCheckServerPipe(ServerHandle,
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MaxInstances, 1,
+ InQuota, 0,
+ OutQuota, OutQuota,
+ FILE_PIPE_LISTENING_STATE);
+ ObCloseHandle(ServerHandle, KernelMode);
+ Timeout.QuadPart = -100 * 1000 * 10;
+ Status = KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ }
+ }
+}
+
+static
+VOID
+TestCreate(VOID)
+{
+}
+
+static KSTART_ROUTINE RunTest;
+static
+VOID
+NTAPI
+RunTest(
+ IN PVOID Context)
+{
+ UNREFERENCED_PARAMETER(Context);
+ TestCreateNamedPipe();
+ TestCreate();
+}
+
+START_TEST(NpfsCreate)
+{
+ PKTHREAD Thread;
+
+ Thread = KmtStartThread(RunTest, NULL);
+ KmtFinishThread(Thread, NULL);
+}
Propchange: trunk/rostests/kmtests/npfs/NpfsCreate.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/kmtests/npfs/NpfsHelpers.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/npfs/NpfsHelpers.…
==============================================================================
--- trunk/rostests/kmtests/npfs/NpfsHelpers.c (added)
+++ trunk/rostests/kmtests/npfs/NpfsHelpers.c [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -0,0 +1,774 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite Helper functions for NPFS tests
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ */
+
+#include <kmt_test.h>
+#include "npfs.h"
+
+NTSTATUS
+NpCreatePipeEx(
+ OUT PHANDLE ServerHandle,
+ IN PCWSTR PipePath,
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ IN ULONG NamedPipeType,
+ IN ULONG ShareAccess,
+ IN ULONG MaximumInstances,
+ IN ULONG InboundQuota,
+ IN ULONG OutboundQuota,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions,
+ IN PLARGE_INTEGER DefaultTimeout OPTIONAL)
+{
+ UNICODE_STRING ObjectName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NAMED_PIPE_CREATE_PARAMETERS Params;
+ IO_STATUS_BLOCK IoStatusBlock;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&ObjectName, PipePath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ObjectName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ Params.NamedPipeType = NamedPipeType;
+ Params.ReadMode = ReadMode;
+ Params.CompletionMode = CompletionMode;
+ Params.MaximumInstances = MaximumInstances;
+ Params.InboundQuota = InboundQuota;
+ Params.OutboundQuota = OutboundQuota;
+ if (DefaultTimeout)
+ {
+ Params.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart;
+ Params.TimeoutSpecified = TRUE;
+ }
+ else
+ {
+ Params.DefaultTimeout.QuadPart = 0;
+ Params.TimeoutSpecified = FALSE;
+ }
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = IoCreateFile(ServerHandle,
+ DesiredAccess,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, /* AllocationSize */
+ 0, /* FileAttributes */
+ ShareAccess,
+ Disposition,
+ CreateOptions,
+ NULL, /* EaBuffer */
+ 0, /* EaLength */
+ CreateFileTypeNamedPipe,
+ &Params,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ ok_eq_ulongptr(IoStatusBlock.Information, FILE_CREATED);
+ }
+ else
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ }
+ return Status;
+}
+
+NTSTATUS
+NpCreatePipe(
+ OUT PHANDLE ServerHandle,
+ PCWSTR PipePath,
+ ULONG ReadMode,
+ ULONG CompletionMode,
+ ULONG NamedPipeType,
+ ULONG NamedPipeConfiguration,
+ ULONG MaximumInstances,
+ ULONG InboundQuota,
+ ULONG OutboundQuota)
+{
+ ULONG ShareAccess;
+ LARGE_INTEGER DefaultTimeout;
+
+ if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
+ ShareAccess = FILE_SHARE_WRITE;
+ else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
+ ShareAccess = FILE_SHARE_READ;
+ else if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
+ ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ DefaultTimeout.QuadPart = -50 * 1000 * 10;
+
+ return NpCreatePipeEx(ServerHandle,
+ PipePath,
+ ReadMode,
+ CompletionMode,
+ NamedPipeType,
+ ShareAccess,
+ MaximumInstances,
+ InboundQuota,
+ OutboundQuota,
+ SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
+ FILE_OPEN_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ &DefaultTimeout);
+}
+
+NTSTATUS
+NpOpenPipeEx(
+ OUT PHANDLE ClientHandle,
+ IN PCWSTR PipePath,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG ShareAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions)
+{
+ UNICODE_STRING ObjectName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ RtlInitUnicodeString(&ObjectName, PipePath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ObjectName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = IoCreateFile(ClientHandle,
+ DesiredAccess,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, /* AllocationSize */
+ 0, /* FileAttributes */
+ ShareAccess,
+ Disposition,
+ CreateOptions,
+ NULL, /* EaBuffer */
+ 0, /* EaLength */
+ CreateFileTypeNone,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ ok(Status != STATUS_PENDING, "IoCreateFile returned pending\n");
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED);
+ }
+ else
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ }
+ return Status;
+}
+
+NTSTATUS
+NpOpenPipe(
+ OUT PHANDLE ClientHandle,
+ IN PCWSTR PipePath,
+ IN ULONG NamedPipeConfiguration)
+{
+ ULONG ShareAccess;
+
+ if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
+ ShareAccess = FILE_SHARE_WRITE;
+ else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
+ ShareAccess = FILE_SHARE_READ;
+ else if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
+ ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ return NpOpenPipeEx(ClientHandle,
+ PipePath,
+ SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
+ ShareAccess,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+}
+
+NTSTATUS
+NpControlPipe(
+ IN HANDLE ServerHandle,
+ IN ULONG FsControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferLength)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = ZwFsControlFile(ServerHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FsControlCode,
+ InputBuffer,
+ InputBufferLength,
+ NULL,
+ 0);
+ if (Status == STATUS_PENDING)
+ {
+ Status = ZwWaitForSingleObject(ServerHandle,
+ FALSE,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Status = IoStatusBlock.Status;
+ }
+ if (NT_SUCCESS(Status))
+ {
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0);
+ }
+ else
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ }
+ return Status;
+}
+
+NTSTATUS
+NpWaitPipe(
+ IN PCWSTR PipeName,
+ IN PLARGE_INTEGER Timeout)
+{
+ NTSTATUS Status;
+ HANDLE RootHandle;
+ UNICODE_STRING RootDirectoryName = RTL_CONSTANT_STRING(DEVICE_NAMED_PIPE);
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PFILE_PIPE_WAIT_FOR_BUFFER WaitForBuffer;
+ ULONG NameLength;
+ ULONG BufferSize;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &RootDirectoryName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = IoCreateFile(&RootHandle,
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0,
+ CreateFileTypeNone,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ return Status;
+ }
+ ok(Status != STATUS_PENDING, "IoCreateFile returned pending\n");
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED);
+
+ NameLength = wcslen(PipeName) * sizeof(WCHAR);
+ BufferSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER,
+ Name[NameLength / sizeof(WCHAR)]);
+ WaitForBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, 'WPmK');
+ if (WaitForBuffer == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ if (Timeout)
+ {
+ WaitForBuffer->Timeout.QuadPart = Timeout->QuadPart;
+ WaitForBuffer->TimeoutSpecified = TRUE;
+ }
+ else
+ {
+ WaitForBuffer->Timeout.QuadPart = 0;
+ WaitForBuffer->TimeoutSpecified = FALSE;
+ }
+ WaitForBuffer->NameLength = NameLength;
+ RtlCopyMemory(WaitForBuffer->Name, PipeName, NameLength);
+ Status = NpControlPipe(RootHandle,
+ FSCTL_PIPE_WAIT,
+ WaitForBuffer,
+ BufferSize);
+ ExFreePoolWithTag(WaitForBuffer, 'WPmK');
+ return Status;
+}
+
+NTSTATUS
+NpReadPipe(
+ IN HANDLE PipeHandle,
+ OUT PVOID Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG_PTR BytesRead)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ BOOLEAN PendingReturned = FALSE;
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = ZwReadFile(PipeHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ BufferSize,
+ NULL,
+ NULL);
+ if (Status == STATUS_PENDING)
+ {
+ Status = ZwWaitForSingleObject(PipeHandle,
+ FALSE,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Status = IoStatusBlock.Status;
+ PendingReturned = TRUE;
+ }
+ if (NT_SUCCESS(Status))
+ {
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ *BytesRead = IoStatusBlock.Information;
+ }
+ else
+ {
+ if (PendingReturned)
+ {
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0);
+ }
+ else
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ }
+ *BytesRead = 0;
+ }
+ return Status;
+}
+
+NTSTATUS
+NpWritePipe(
+ IN HANDLE PipeHandle,
+ IN const VOID *Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG_PTR BytesWritten)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ Status = ZwWriteFile(PipeHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ (PVOID)Buffer,
+ BufferSize,
+ NULL,
+ NULL);
+ if (Status == STATUS_PENDING)
+ {
+ Status = ZwWaitForSingleObject(PipeHandle,
+ FALSE,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Status = IoStatusBlock.Status;
+ }
+ if (NT_SUCCESS(Status))
+ {
+ ok_eq_hex(IoStatusBlock.Status, Status);
+ *BytesWritten = IoStatusBlock.Information;
+ }
+ else
+ {
+ ok_eq_hex(IoStatusBlock.Status, 0x55555555UL);
+ ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL);
+ *BytesWritten = 0;
+ }
+ return Status;
+}
+
+static
+BOOLEAN
+CheckBuffer(
+ PVOID Buffer,
+ SIZE_T Size,
+ UCHAR Value)
+{
+ PUCHAR Array = Buffer;
+ SIZE_T i;
+
+ for (i = 0; i < Size; i++)
+ if (Array[i] != Value)
+ {
+ trace("Expected %x, found %x at offset %lu\n", Value, Array[i],
(ULONG)i);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#define ok_eq_print_(value, expected, spec, FileAndLine) \
+ KmtOk((value) == (expected), FileAndLine,
#value " = " spec ", expected " spec "\n", value, expected)
+#define ok_eq_ulong_(value, expected) ok_eq_print_(value, expected,
"%lu", FileAndLine)
+#define ok_eq_ulonglong_(value, expected) ok_eq_print_(value, expected,
"%I64u", FileAndLine)
+#ifndef _WIN64
+#define ok_eq_ulongptr_(value, expected) ok_eq_print_(value, (ULONG_PTR)(expected),
"%lu", FileAndLine)
+#elif defined _WIN64
+#define ok_eq_ulongptr_(value, expected) ok_eq_print_(value, (ULONG_PTR)(expected),
"%I64u", FileAndLine)
+#endif
+#define ok_eq_hex_(value, expected) ok_eq_print_(value, expected,
"0x%08lx", FileAndLine)
+
+VOID
+NpCheckServerPipe_(
+ IN HANDLE ServerHandle,
+ /* PipeInformation */
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ /* PipeLocalInformation */
+ IN ULONG NamedPipeType,
+ IN ULONG NamedPipeConfiguration,
+ IN ULONG MaximumInstances,
+ IN ULONG CurrentInstances,
+ IN ULONG InboundQuota,
+ IN ULONG ReadDataAvailable,
+ IN ULONG OutboundQuota,
+ IN ULONG WriteQuotaAvailable,
+ IN ULONG NamedPipeState,
+ /* PipeRemoteInformation */
+ /* */
+ IN PCSTR FileAndLine)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_PIPE_INFORMATION PipeInfo;
+ FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo;
+ FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo;
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55);
+ Status = ZwQueryInformationFile(ServerHandle,
+ &IoStatusBlock,
+ &PipeInfo,
+ sizeof(PipeInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeInfo));
+ ok_eq_ulong_(PipeInfo.ReadMode, ReadMode);
+ ok_eq_ulong_(PipeInfo.CompletionMode, CompletionMode);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55);
+ Status = ZwQueryInformationFile(ServerHandle,
+ &IoStatusBlock,
+ &PipeLocalInfo,
+ sizeof(PipeLocalInfo),
+ FilePipeLocalInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeLocalInfo));
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeType, NamedPipeType);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeConfiguration, NamedPipeConfiguration);
+ ok_eq_ulong_(PipeLocalInfo.MaximumInstances, MaximumInstances);
+ ok_eq_ulong_(PipeLocalInfo.CurrentInstances, CurrentInstances);
+ ok_eq_ulong_(PipeLocalInfo.InboundQuota, InboundQuota);
+ ok_eq_ulong_(PipeLocalInfo.ReadDataAvailable, ReadDataAvailable);
+ ok_eq_ulong_(PipeLocalInfo.OutboundQuota, OutboundQuota);
+ ok_eq_ulong_(PipeLocalInfo.WriteQuotaAvailable, WriteQuotaAvailable);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeState, NamedPipeState);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeEnd, (ULONG)FILE_PIPE_SERVER_END);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55);
+ Status = ZwQueryInformationFile(ServerHandle,
+ &IoStatusBlock,
+ &PipeRemoteInfo,
+ sizeof(PipeRemoteInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information,
RTL_SIZEOF_THROUGH_FIELD(FILE_PIPE_REMOTE_INFORMATION, CollectDataTime));
+ ok_eq_ulonglong_(PipeRemoteInfo.CollectDataTime.QuadPart, 0ULL);
+ ok_eq_ulong_(PipeRemoteInfo.MaximumCollectionCount, 0x55555555UL);
+}
+
+VOID
+NpCheckClientPipe_(
+ IN HANDLE ClientHandle,
+ /* PipeInformation */
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ /* PipeLocalInformation */
+ IN ULONG NamedPipeType,
+ IN ULONG NamedPipeConfiguration,
+ IN ULONG MaximumInstances,
+ IN ULONG CurrentInstances,
+ IN ULONG InboundQuota,
+ IN ULONG ReadDataAvailable,
+ IN ULONG OutboundQuota,
+ IN ULONG WriteQuotaAvailable,
+ IN ULONG NamedPipeState,
+ /* PipeRemoteInformation */
+ /* */
+ IN PCSTR FileAndLine)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_PIPE_INFORMATION PipeInfo;
+ FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo;
+ FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo;
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55);
+ Status = ZwQueryInformationFile(ClientHandle,
+ &IoStatusBlock,
+ &PipeInfo,
+ sizeof(PipeInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeInfo));
+ ok_eq_ulong_(PipeInfo.ReadMode, ReadMode);
+ ok_eq_ulong_(PipeInfo.CompletionMode, CompletionMode);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55);
+ Status = ZwQueryInformationFile(ClientHandle,
+ &IoStatusBlock,
+ &PipeLocalInfo,
+ sizeof(PipeLocalInfo),
+ FilePipeLocalInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeLocalInfo));
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeType, NamedPipeType);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeConfiguration, NamedPipeConfiguration);
+ ok_eq_ulong_(PipeLocalInfo.MaximumInstances, MaximumInstances);
+ ok_eq_ulong_(PipeLocalInfo.CurrentInstances, CurrentInstances);
+ ok_eq_ulong_(PipeLocalInfo.InboundQuota, InboundQuota);
+ ok_eq_ulong_(PipeLocalInfo.ReadDataAvailable, ReadDataAvailable);
+ ok_eq_ulong_(PipeLocalInfo.OutboundQuota, OutboundQuota);
+ ok_eq_ulong_(PipeLocalInfo.WriteQuotaAvailable, WriteQuotaAvailable);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeState, NamedPipeState);
+ ok_eq_ulong_(PipeLocalInfo.NamedPipeEnd, (ULONG)FILE_PIPE_CLIENT_END);
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55);
+ Status = ZwQueryInformationFile(ClientHandle,
+ &IoStatusBlock,
+ &PipeRemoteInfo,
+ sizeof(PipeRemoteInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, STATUS_SUCCESS);
+ ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS);
+ ok_eq_ulongptr_(IoStatusBlock.Information,
RTL_SIZEOF_THROUGH_FIELD(FILE_PIPE_REMOTE_INFORMATION, CollectDataTime));
+ ok_eq_ulonglong_(PipeRemoteInfo.CollectDataTime.QuadPart, 0ULL);
+ ok_eq_ulong_(PipeRemoteInfo.MaximumCollectionCount, 0x55555555UL);
+}
+
+VOID
+NpQueryPipe_(
+ IN HANDLE PipeHandle,
+ IN NTSTATUS ExpectedStatus,
+ IN PCSTR FileAndLine)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_PIPE_INFORMATION PipeInfo;
+ FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo;
+ FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo;
+
+ ASSERT(!NT_SUCCESS(ExpectedStatus));
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55);
+ Status = ZwQueryInformationFile(PipeHandle,
+ &IoStatusBlock,
+ &PipeInfo,
+ sizeof(PipeInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, ExpectedStatus);
+ ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55),
"CheckBuffer returned");
+ ok_bool_true(CheckBuffer(&PipeInfo, sizeof(PipeInfo), 0x55), "CheckBuffer
returned");
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55);
+ Status = ZwQueryInformationFile(PipeHandle,
+ &IoStatusBlock,
+ &PipeLocalInfo,
+ sizeof(PipeLocalInfo),
+ FilePipeLocalInformation);
+ ok_eq_hex_(Status, ExpectedStatus);
+ ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55),
"CheckBuffer returned");
+ ok_bool_true(CheckBuffer(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55),
"CheckBuffer returned");
+
+ RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55);
+ RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55);
+ Status = ZwQueryInformationFile(PipeHandle,
+ &IoStatusBlock,
+ &PipeRemoteInfo,
+ sizeof(PipeRemoteInfo),
+ FilePipeInformation);
+ ok_eq_hex_(Status, ExpectedStatus);
+ ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55),
"CheckBuffer returned");
+ ok_bool_true(CheckBuffer(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55),
"CheckBuffer returned");
+}
+
+static KSTART_ROUTINE PipeWorkerThread;
+static
+VOID
+NTAPI
+PipeWorkerThread(
+ IN PVOID ThreadContext)
+{
+ PTHREAD_CONTEXT Context = ThreadContext;
+ PVOID WaitEvents[2] = { &Context->ThreadDoneEvent,
+ &Context->StartWorkEvent };
+ NTSTATUS Status;
+
+ while (TRUE)
+ {
+ Status = KeWaitForMultipleObjects(RTL_NUMBER_OF(WaitEvents),
+ WaitEvents,
+ WaitAny,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL,
+ NULL);
+ if (Status == STATUS_WAIT_0)
+ break;
+ ASSERT(Status == STATUS_WAIT_1);
+
+ Context->Work(Context);
+
+ KeSetEvent(&Context->WorkCompleteEvent, IO_NO_INCREMENT, TRUE);
+ }
+}
+
+VOID
+StartWorkerThread(
+ OUT PTHREAD_CONTEXT Context)
+{
+ KeInitializeEvent(&Context->ThreadDoneEvent, NotificationEvent, FALSE);
+ KeInitializeEvent(&Context->StartWorkEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&Context->WorkCompleteEvent, NotificationEvent, TRUE);
+
+ Context->Thread = KmtStartThread(PipeWorkerThread, Context);
+}
+
+VOID
+FinishWorkerThread(
+ IN PTHREAD_CONTEXT Context)
+{
+ KmtFinishThread(Context->Thread, &Context->ThreadDoneEvent);
+}
+
+BOOLEAN
+WaitForWork(
+ IN PTHREAD_CONTEXT Context,
+ IN ULONG MilliSeconds)
+{
+ LARGE_INTEGER Timeout;
+ NTSTATUS Status;
+
+ Timeout.QuadPart = -10 * 1000 * (LONGLONG)MilliSeconds;
+ Status = KeWaitForSingleObject(&Context->WorkCompleteEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ &Timeout);
+ ok(Status == STATUS_SUCCESS || Status == STATUS_TIMEOUT, "Wait status
%lx\n", Status);
+ return Status != STATUS_TIMEOUT;
+}
+
+BOOLEAN
+TriggerWork(
+ IN PTHREAD_CONTEXT Context,
+ IN ULONG MilliSeconds)
+{
+ NTSTATUS Status;
+
+ Status = KeWaitForSingleObject(&Context->WorkCompleteEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ KeResetEvent(&Context->WorkCompleteEvent);
+ KeSetEvent(&Context->StartWorkEvent, IO_NO_INCREMENT, TRUE);
+ return WaitForWork(Context, MilliSeconds);
+}
+
+PKTHREAD
+KmtStartThread(
+ IN PKSTART_ROUTINE StartRoutine,
+ IN PVOID StartContext OPTIONAL)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE ThreadHandle;
+ PVOID ThreadObject = NULL;
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ ThreadHandle = INVALID_HANDLE_VALUE;
+ Status = PsCreateSystemThread(&ThreadHandle,
+ SYNCHRONIZE,
+ &ObjectAttributes,
+ NULL,
+ NULL,
+ StartRoutine,
+ StartContext);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ if (!skip(NT_SUCCESS(Status) && ThreadHandle != NULL && ThreadHandle
!= INVALID_HANDLE_VALUE, "No thread\n"))
+ {
+ Status = ObReferenceObjectByHandle(ThreadHandle,
+ SYNCHRONIZE,
+ PsThreadType,
+ KernelMode,
+ &ThreadObject,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ObCloseHandle(ThreadHandle, KernelMode);
+ }
+ return ThreadObject;
+}
+
+VOID
+KmtFinishThread(
+ IN PKTHREAD Thread OPTIONAL,
+ IN PKEVENT Event OPTIONAL)
+{
+ NTSTATUS Status;
+
+ if (skip(Thread != NULL, "No thread\n"))
+ return;
+
+ if (Event)
+ KeSetEvent(Event, IO_NO_INCREMENT, TRUE);
+ Status = KeWaitForSingleObject(Thread,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ ObDereferenceObject(Thread);
+}
Propchange: trunk/rostests/kmtests/npfs/NpfsHelpers.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/kmtests/npfs/NpfsReadWrite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/npfs/NpfsReadWrit…
==============================================================================
--- trunk/rostests/kmtests/npfs/NpfsReadWrite.c (added)
+++ trunk/rostests/kmtests/npfs/NpfsReadWrite.c [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -0,0 +1,598 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite NPFS Read/Write test
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ */
+
+#include <kmt_test.h>
+#include "npfs.h"
+
+typedef struct _READ_WRITE_TEST_CONTEXT
+{
+ PCWSTR PipePath;
+ BOOLEAN ServerSynchronous;
+ BOOLEAN ClientSynchronous;
+} READ_WRITE_TEST_CONTEXT, *PREAD_WRITE_TEST_CONTEXT;
+
+#define MAX_INSTANCES 5
+#define IN_QUOTA 4096
+#define OUT_QUOTA 4096
+
+#define MakeServer(ServerHandle, PipePath, ServerSynchronous) \
+ NpCreatePipeEx(ServerHandle, \
+ PipePath, \
+ BYTE_STREAM, \
+ QUEUE, \
+ BYTE_STREAM, \
+ FILE_SHARE_READ | FILE_SHARE_WRITE, \
+ MAX_INSTANCES, \
+ IN_QUOTA, \
+ OUT_QUOTA, \
+ SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, \
+ FILE_OPEN_IF, \
+ (ServerSynchronous) ? FILE_SYNCHRONOUS_IO_NONALERT \
+ : 0, \
+ &DefaultTimeout)
+
+#define CheckServer(ServerHandle, State) \
+ NpCheckServerPipe(ServerHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, 0, \
+ OUT_QUOTA, OUT_QUOTA, \
+ State)
+
+#define CheckClient(ClientHandle, State) \
+ NpCheckClientPipe(ClientHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, 0, \
+ OUT_QUOTA, OUT_QUOTA, \
+ State)
+
+#define CheckServerQuota(ServerHandle, InQ, OutQ) \
+ NpCheckServerPipe(ServerHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, InQ, \
+ OUT_QUOTA, OUT_QUOTA - (OutQ), \
+ FILE_PIPE_CONNECTED_STATE)
+
+#define CheckClientQuota(ClientHandle, InQ, OutQ) \
+ NpCheckClientPipe(ClientHandle, \
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
+ MAX_INSTANCES, 1, \
+ IN_QUOTA, InQ, \
+ OUT_QUOTA, OUT_QUOTA - (OutQ), \
+ FILE_PIPE_CONNECTED_STATE)
+
+#define CheckPipeContext(Context, ExpectedStatus, ExpectedBytes) do \
+{ \
+ ok_bool_true(Okay, "CheckPipeContext");
\
+ ok_eq_hex((Context)->ReadWrite.Status, ExpectedStatus); \
+ ok_eq_ulongptr((Context)->ReadWrite.BytesTransferred, ExpectedBytes); \
+} while (0)
+
+static
+VOID
+ConnectPipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ HANDLE ClientHandle;
+
+ ClientHandle = NULL;
+ Context->Connect.Status = NpOpenPipeEx(&ClientHandle,
+ Context->Connect.PipePath,
+ SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ Context->Connect.ClientSynchronous ?
FILE_SYNCHRONOUS_IO_NONALERT
+ : 0);
+ Context->Connect.ClientHandle = ClientHandle;
+}
+
+static
+VOID
+ListenPipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle);
+}
+
+static
+VOID
+ReadPipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ Context->ReadWrite.Status = NpReadPipe(Context->ReadWrite.PipeHandle,
+ Context->ReadWrite.Buffer,
+ Context->ReadWrite.BufferSize,
+
(PULONG_PTR)&Context->ReadWrite.BytesTransferred);
+}
+
+static
+VOID
+WritePipe(
+ IN OUT PTHREAD_CONTEXT Context)
+{
+ Context->ReadWrite.Status = NpWritePipe(Context->ReadWrite.PipeHandle,
+ Context->ReadWrite.Buffer,
+ Context->ReadWrite.BufferSize,
+
(PULONG_PTR)&Context->ReadWrite.BytesTransferred);
+}
+
+static
+BOOLEAN
+CheckConnectPipe(
+ IN PTHREAD_CONTEXT Context,
+ IN PCWSTR PipePath,
+ IN BOOLEAN ClientSynchronous,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = ConnectPipe;
+ Context->Connect.PipePath = PipePath;
+ Context->Connect.ClientSynchronous = ClientSynchronous;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static
+BOOLEAN
+CheckListenPipe(
+ IN PTHREAD_CONTEXT Context,
+ IN HANDLE ServerHandle,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = ListenPipe;
+ Context->Listen.ServerHandle = ServerHandle;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static
+BOOLEAN
+CheckReadPipe(
+ IN PTHREAD_CONTEXT Context,
+ IN HANDLE PipeHandle,
+ OUT PVOID Buffer,
+ IN ULONG BufferSize,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = ReadPipe;
+ Context->ReadWrite.PipeHandle = PipeHandle;
+ Context->ReadWrite.Buffer = Buffer;
+ Context->ReadWrite.BufferSize = BufferSize;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static
+BOOLEAN
+CheckWritePipe(
+ IN PTHREAD_CONTEXT Context,
+ IN HANDLE PipeHandle,
+ IN const VOID *Buffer,
+ IN ULONG BufferSize,
+ IN ULONG MilliSeconds)
+{
+ Context->Work = WritePipe;
+ Context->ReadWrite.PipeHandle = PipeHandle;
+ Context->ReadWrite.Buffer = (PVOID)Buffer;
+ Context->ReadWrite.BufferSize = BufferSize;
+ return TriggerWork(Context, MilliSeconds);
+}
+
+static KSTART_ROUTINE TestReadWrite;
+static
+VOID
+NTAPI
+TestReadWrite(
+ IN PVOID Context)
+{
+ PREAD_WRITE_TEST_CONTEXT TestContext = Context;
+ PCWSTR PipePath = TestContext->PipePath;
+ BOOLEAN ServerSynchronous = TestContext->ServerSynchronous;
+ BOOLEAN ClientSynchronous = TestContext->ClientSynchronous;
+ NTSTATUS Status;
+ HANDLE ServerHandle;
+ LARGE_INTEGER DefaultTimeout;
+ THREAD_CONTEXT ConnectContext;
+ THREAD_CONTEXT ListenContext;
+ THREAD_CONTEXT ClientReadContext;
+ THREAD_CONTEXT ClientWriteContext;
+ THREAD_CONTEXT ServerReadContext;
+ THREAD_CONTEXT ServerWriteContext;
+ BOOLEAN Okay;
+ HANDLE ClientHandle;
+ UCHAR ReadBuffer[128];
+ UCHAR WriteBuffer[128];
+
+ StartWorkerThread(&ConnectContext);
+ StartWorkerThread(&ListenContext);
+ StartWorkerThread(&ClientReadContext);
+ StartWorkerThread(&ClientWriteContext);
+ StartWorkerThread(&ServerReadContext);
+ StartWorkerThread(&ServerWriteContext);
+
+ DefaultTimeout.QuadPart = -50 * 1000 * 10;
+
+ /* Server should start out listening */
+ Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
+
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, NULL, 0, 100);
+ ok_bool_true(Okay, "CheckWritePipe returned");
+ ok_eq_ulongptr(ServerWriteContext.ReadWrite.BytesTransferred, 0);
+ ok_eq_hex(ServerWriteContext.ReadWrite.Status, STATUS_PIPE_LISTENING);
+
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, NULL, 0, 100);
+ ok_bool_true(Okay, "CheckReadPipe returned");
+ ok_eq_ulongptr(ServerReadContext.ReadWrite.BytesTransferred, 0);
+ ok_eq_hex(ServerReadContext.ReadWrite.Status, STATUS_PIPE_LISTENING);
+
+ /* Connect a client */
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Server to client, write first, 1 byte */
+ WriteBuffer[0] = 'A';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
+ CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'A');
+ CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
+
+ /** Server to client, read first, 1 byte */
+ WriteBuffer[0] = 'B';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ CheckServerQuota(ServerHandle, 0, 1);
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
+ Okay = WaitForWork(&ClientReadContext, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'B');
+ CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
+
+ /** Client to server, write first, 1 byte */
+ WriteBuffer[0] = 'C';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
+ CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'C');
+ CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
+
+ /** Client to server, read first, 1 byte */
+ WriteBuffer[0] = 'D';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ CheckClientQuota(ClientHandle, 0, 1);
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
+ Okay = WaitForWork(&ServerReadContext, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'D');
+ CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
+
+ /** Server to client, write 0 bytes */
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, (PVOID)1, 0, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 0);
+ CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
+
+ /** Client to Server, write 0 bytes */
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, (PVOID)1, 0, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 0);
+ CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
+
+ /** Server to client, read 0 bytes blocks, write 0 bytes does not unblock, write 1
byte unblocks */
+ WriteBuffer[0] = 'E';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, (PVOID)1, 0, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ CheckServerQuota(ServerHandle, 0, 0);
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, (PVOID)1, 0, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 0);
+ Okay = WaitForWork(&ClientReadContext, 100);
+ ok_bool_false(Okay, "WaitForWork returned");
+ CheckServerQuota(ServerHandle, 0, 0);
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
+ Okay = WaitForWork(&ClientReadContext, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+ CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'E');
+ CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
+
+ /** Client to server, read 0 bytes blocks, write 0 bytes does not unblock, write 1
byte unblocks */
+ WriteBuffer[0] = 'F';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, (PVOID)1, 0, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ CheckClientQuota(ClientHandle, 0, 0);
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, (PVOID)1, 0, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 0);
+ Okay = WaitForWork(&ServerReadContext, 100);
+ ok_bool_false(Okay, "WaitForWork returned");
+ CheckClientQuota(ClientHandle, 0, 0);
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
+ Okay = WaitForWork(&ServerReadContext, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+ CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'F');
+ CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
+
+ /** Disconnect server with pending read on client */
+ WriteBuffer[0] = 'G';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ CheckServerQuota(ServerHandle, 0, 1);
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = WaitForWork(&ClientReadContext, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+
+ /* Read from server when disconnected */
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
+
+ /* Write to server when disconnected */
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_PIPE_DISCONNECTED, 0);
+
+ /* Read from client when disconnected */
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
+
+ /* Write to client when disconnected */
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_PIPE_DISCONNECTED, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_false(Okay, "CheckListenPipe returned");
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ Okay = WaitForWork(&ListenContext, 100);
+ ok_bool_true(Okay, "WaitForWork returned");
+ ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Close server with pending read on client */
+ WriteBuffer[0] = 'H';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = WaitForWork(&ClientReadContext, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+
+ /* Read from client when closed */
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
+
+ /* Write to client when closed */
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_PIPE_CLOSING, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Close client with pending read on server */
+ WriteBuffer[0] = 'I';
+ ReadBuffer[0] = 'X';
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ ok_bool_false(Okay, "CheckReadPipe returned");
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = WaitForWork(&ServerReadContext, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+
+ /* Read from server when closed */
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
+
+ /* Write to server when closed */
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_PIPE_CLOSING, 0);
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Write to server and disconnect, then read from client */
+ WriteBuffer[0] = 'J';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
+ CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
+ ok_bool_false(Okay, "CheckListenPipe returned");
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ Okay = WaitForWork(&ListenContext, 100);
+ ok_bool_true(Okay, "WaitForWork returned");
+ ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Write to server and close, then read from client */
+ WriteBuffer[0] = 'K';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
+ CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ NpCheckClientPipe(ClientHandle,
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MAX_INSTANCES, 1,
+ IN_QUOTA, 1,
+ OUT_QUOTA, OUT_QUOTA,
+ FILE_PIPE_CLOSING_STATE);
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'K');
+ Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+
+ /** Write to client and close, then read from server */
+ WriteBuffer[0] = 'L';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
+ CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ NpCheckServerPipe(ServerHandle,
+ BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
+ MAX_INSTANCES, 1,
+ IN_QUOTA, 1,
+ OUT_QUOTA, OUT_QUOTA,
+ FILE_PIPE_CLOSING_STATE);
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
+ ok_eq_uint(ReadBuffer[0], 'L');
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ /* Restore the connection */
+ Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
+ ok_bool_true(Okay, "CheckConnectPipe returned");
+ ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
+ ClientHandle = ConnectContext.Connect.ClientHandle;
+ CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
+ CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
+
+ /** Write to client and disconnect server, then read from server */
+ WriteBuffer[0] = 'M';
+ ReadBuffer[0] = 'X';
+ Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
+ CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
+ CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
+ Status = NpDisconnectPipe(ServerHandle);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
+ CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
+ ok_eq_uint(ReadBuffer[0], 'X');
+ Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
+ CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
+ Status = ObCloseHandle(ClientHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ Status = ObCloseHandle(ServerHandle, KernelMode);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+
+ FinishWorkerThread(&ServerWriteContext);
+ FinishWorkerThread(&ServerReadContext);
+ FinishWorkerThread(&ClientWriteContext);
+ FinishWorkerThread(&ClientReadContext);
+ FinishWorkerThread(&ListenContext);
+ FinishWorkerThread(&ConnectContext);
+}
+
+START_TEST(NpfsReadWrite)
+{
+ PKTHREAD Thread;
+ READ_WRITE_TEST_CONTEXT TestContext;
+
+ TestContext.PipePath = DEVICE_NAMED_PIPE L"\\KmtestNpfsReadWriteTestPipe";
+
+ TestContext.ServerSynchronous = TRUE;
+ TestContext.ClientSynchronous = TRUE;
+ Thread = KmtStartThread(TestReadWrite, &TestContext);
+ KmtFinishThread(Thread, NULL);
+
+ TestContext.ServerSynchronous = FALSE;
+ TestContext.ClientSynchronous = TRUE;
+ Thread = KmtStartThread(TestReadWrite, &TestContext);
+ KmtFinishThread(Thread, NULL);
+
+ TestContext.ServerSynchronous = TRUE;
+ TestContext.ClientSynchronous = FALSE;
+ Thread = KmtStartThread(TestReadWrite, &TestContext);
+ KmtFinishThread(Thread, NULL);
+
+ TestContext.ServerSynchronous = FALSE;
+ TestContext.ClientSynchronous = FALSE;
+ Thread = KmtStartThread(TestReadWrite, &TestContext);
+ KmtFinishThread(Thread, NULL);
+}
Propchange: trunk/rostests/kmtests/npfs/NpfsReadWrite.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/kmtests/npfs/npfs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/npfs/npfs.h?rev=6…
==============================================================================
--- trunk/rostests/kmtests/npfs/npfs.h (added)
+++ trunk/rostests/kmtests/npfs/npfs.h [iso-8859-1] Wed Apr 9 18:00:33 2014
@@ -0,0 +1,225 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite NPFS helper declarations
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ */
+
+#ifndef _KMTEST_NPFS_H_
+#define _KMTEST_NPFS_H_
+
+#define DEVICE_NAMED_PIPE L"\\Device\\NamedPipe"
+
+#define BYTE_STREAM FILE_PIPE_BYTE_STREAM_MODE
+C_ASSERT(FILE_PIPE_BYTE_STREAM_MODE == FILE_PIPE_BYTE_STREAM_TYPE);
+#define MESSAGE FILE_PIPE_MESSAGE_MODE
+C_ASSERT(FILE_PIPE_MESSAGE_MODE == FILE_PIPE_MESSAGE_TYPE);
+#define QUEUE FILE_PIPE_QUEUE_OPERATION
+#define COMPLETE FILE_PIPE_COMPLETE_OPERATION
+#define INBOUND FILE_PIPE_INBOUND
+#define OUTBOUND FILE_PIPE_OUTBOUND
+#define DUPLEX FILE_PIPE_FULL_DUPLEX
+
+NTSTATUS
+NpCreatePipeEx(
+ OUT PHANDLE ServerHandle,
+ IN PCWSTR PipePath,
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ IN ULONG NamedPipeType,
+ IN ULONG ShareAccess,
+ IN ULONG MaximumInstances,
+ IN ULONG InboundQuota,
+ IN ULONG OutboundQuota,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions,
+ IN PLARGE_INTEGER DefaultTimeout OPTIONAL);
+
+NTSTATUS
+NpCreatePipe(
+ OUT PHANDLE ServerHandle,
+ IN PCWSTR PipePath,
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ IN ULONG NamedPipeType,
+ IN ULONG NamedPipeConfiguration,
+ IN ULONG MaximumInstances,
+ IN ULONG InboundQuota,
+ IN ULONG OutboundQuota);
+
+NTSTATUS
+NpOpenPipeEx(
+ OUT PHANDLE ClientHandle,
+ IN PCWSTR PipePath,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG ShareAccess,
+ IN ULONG Disposition,
+ IN ULONG CreateOptions);
+
+NTSTATUS
+NpOpenPipe(
+ OUT PHANDLE ClientHandle,
+ IN PCWSTR PipePath,
+ IN ULONG NamedPipeConfiguration);
+
+NTSTATUS
+NpControlPipe(
+ IN HANDLE PipeHandle,
+ IN ULONG FsControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferLength);
+
+#define NpListenPipe(ServerHandle) NpControlPipe(ServerHandle, FSCTL_PIPE_LISTEN,
NULL, 0)
+#define NpDisconnectPipe(ServerHandle) NpControlPipe(ServerHandle,
FSCTL_PIPE_DISCONNECT, NULL, 0)
+
+NTSTATUS
+NpWaitPipe(
+ IN PCWSTR PipeName,
+ IN PLARGE_INTEGER Timeout);
+
+NTSTATUS
+NpReadPipe(
+ IN HANDLE PipeHandle,
+ OUT PVOID Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG_PTR BytesRead);
+
+NTSTATUS
+NpWritePipe(
+ IN HANDLE PipeHandle,
+ IN const VOID *Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG_PTR BytesWritten);
+
+#define NpCheckServerPipe(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps) \
+ NpCheckServerPipe__(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, __FILE__,
__LINE__)
+
+#define NpCheckServerPipe__(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, file,
line) \
+ NpCheckServerPipe_(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, file
":" KMT_STRINGIZE(line))
+
+VOID
+NpCheckServerPipe_(
+ IN HANDLE ServerHandle,
+ /* PipeInformation */
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ /* PipeLocalInformation */
+ IN ULONG NamedPipeType,
+ IN ULONG NamedPipeConfiguration,
+ IN ULONG MaximumInstances,
+ IN ULONG CurrentInstances,
+ IN ULONG InboundQuota,
+ IN ULONG ReadDataAvailable,
+ IN ULONG OutboundQuota,
+ IN ULONG WriteQuotaAvailable,
+ IN ULONG NamedPipeState,
+ /* PipeRemoteInformation */
+ /* */
+ IN PCSTR FileAndLine);
+
+#define NpCheckClientPipe(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps) \
+ NpCheckClientPipe__(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, __FILE__,
__LINE__)
+
+#define NpCheckClientPipe__(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, file,
line) \
+ NpCheckClientPipe_(h, rm, cm, npt, npc, mi, ci, iq, rsa, oq, wqa, nps, file
":" KMT_STRINGIZE(line))
+
+VOID
+NpCheckClientPipe_(
+ IN HANDLE ClientHandle,
+ /* PipeInformation */
+ IN ULONG ReadMode,
+ IN ULONG CompletionMode,
+ /* PipeLocalInformation */
+ IN ULONG NamedPipeType,
+ IN ULONG NamedPipeConfiguration,
+ IN ULONG MaximumInstances,
+ IN ULONG CurrentInstances,
+ IN ULONG InboundQuota,
+ IN ULONG ReadDataAvailable,
+ IN ULONG OutboundQuota,
+ IN ULONG WriteQuotaAvailable,
+ IN ULONG NamedPipeState,
+ /* PipeRemoteInformation */
+ /* */
+ IN PCSTR FileAndLine);
+
+#define NpQueryPipe(h, es) \
+ NpQueryPipe__(h, es, __FILE__, __LINE__)
+
+#define NpQueryPipe__(h, es, file, line) \
+ NpQueryPipe_(h, es, file ":" KMT_STRINGIZE(line))
+
+VOID
+NpQueryPipe_(
+ IN HANDLE Handle,
+ IN NTSTATUS ExpectedStatus,
+ IN PCSTR FileAndLine);
+
+
+struct _THREAD_CONTEXT;
+typedef VOID (WORK_FUNCTION)(IN OUT struct _THREAD_CONTEXT *);
+typedef WORK_FUNCTION *PWORK_FUNCTION;
+
+typedef struct _THREAD_CONTEXT
+{
+ volatile PWORK_FUNCTION Work;
+ volatile union
+ {
+ struct
+ {
+ PCWSTR PipePath;
+ BOOLEAN ClientSynchronous;
+ HANDLE ClientHandle;
+ NTSTATUS Status;
+ } Connect;
+ struct
+ {
+ HANDLE ServerHandle;
+ NTSTATUS Status;
+ } Listen;
+ struct
+ {
+ HANDLE PipeHandle;
+ PVOID Buffer;
+ ULONG BufferSize;
+ ULONG_PTR BytesTransferred;
+ NTSTATUS Status;
+ } ReadWrite;
+ };
+ KEVENT ThreadDoneEvent;
+ KEVENT StartWorkEvent;
+ KEVENT WorkCompleteEvent;
+ PKTHREAD Thread;
+} THREAD_CONTEXT, *PTHREAD_CONTEXT;
+
+VOID
+StartWorkerThread(
+ OUT PTHREAD_CONTEXT Context);
+
+VOID
+FinishWorkerThread(
+ IN PTHREAD_CONTEXT Context);
+
+BOOLEAN
+WaitForWork(
+ IN PTHREAD_CONTEXT Context,
+ IN ULONG MilliSeconds);
+
+BOOLEAN
+TriggerWork(
+ IN PTHREAD_CONTEXT Context,
+ IN ULONG MilliSeconds);
+
+
+PKTHREAD
+KmtStartThread(
+ IN PKSTART_ROUTINE StartRoutine,
+ IN PVOID StartContext OPTIONAL);
+
+VOID
+KmtFinishThread(
+ IN PKTHREAD Thread OPTIONAL,
+ IN PKEVENT Event OPTIONAL);
+
+#endif /* !defined _KMTEST_NPFS_H_ */
Propchange: trunk/rostests/kmtests/npfs/npfs.h
------------------------------------------------------------------------------
svn:eol-style = native