reactos/modules/rostests/kmtests/npfs/NpfsReadWrite.c

598 lines
26 KiB
C

/*
* 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@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);
}