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