ReactOS  0.4.14-dev-50-g13bb5e2
NpfsConnect.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS kernel-mode tests
3  * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4  * PURPOSE: Kernel-Mode Test Suite NPFS Connect test
5  * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 #include "npfs.h"
10 
11 #define MAX_INSTANCES 5
12 #define IN_QUOTA 4096
13 #define OUT_QUOTA 4096
14 
15 #define CheckServer(ServerHandle, State) \
16  NpCheckServerPipe(ServerHandle, \
17  BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
18  MAX_INSTANCES, 1, \
19  IN_QUOTA, 0, \
20  OUT_QUOTA, OUT_QUOTA, \
21  State)
22 
23 #define CheckClient(ClientHandle, State) \
24  NpCheckClientPipe(ClientHandle, \
25  BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
26  MAX_INSTANCES, 1, \
27  IN_QUOTA, 0, \
28  OUT_QUOTA, OUT_QUOTA, \
29  State)
30 
31 static
32 VOID
35 {
36  HANDLE ClientHandle;
37 
38  ClientHandle = NULL;
39  Context->Connect.Status = NpOpenPipe(&ClientHandle,
40  Context->Connect.PipePath,
42  Context->Connect.ClientHandle = ClientHandle;
43 }
44 
45 static
46 VOID
49 {
50  Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle);
51 }
52 
53 static
54 BOOLEAN
57  IN PCWSTR PipePath,
58  IN ULONG MilliSeconds)
59 {
60  Context->Work = ConnectPipe;
61  Context->Connect.PipePath = PipePath;
62  return TriggerWork(Context, MilliSeconds);
63 }
64 
65 static
66 BOOLEAN
69  IN HANDLE ServerHandle,
70  IN ULONG MilliSeconds)
71 {
72  Context->Work = ListenPipe;
73  Context->Listen.ServerHandle = ServerHandle;
74  return TriggerWork(Context, MilliSeconds);
75 }
76 
77 static
78 VOID
80  IN HANDLE ServerHandle,
81  IN PCWSTR PipePath)
82 {
84  THREAD_CONTEXT ConnectContext;
85  THREAD_CONTEXT ListenContext;
86  BOOLEAN Okay;
87  HANDLE ClientHandle;
88 
89  StartWorkerThread(&ConnectContext);
90  StartWorkerThread(&ListenContext);
91 
92  /* Server should start out listening */
94 
95  /* Connect a client */
96  ClientHandle = NULL;
97  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
98  ok_bool_true(Okay, "CheckConnectPipe returned");
99  ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
100  if (NT_SUCCESS(ConnectContext.Connect.Status))
101  {
102  ClientHandle = ConnectContext.Connect.ClientHandle;
103  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
104  }
105  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
106 
107  /* Connect another client */
108  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
109  ok_bool_true(Okay, "CheckConnectPipe returned");
110  ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
111  if (NT_SUCCESS(ConnectContext.Connect.Status))
112  ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
113  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
114  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
115 
116  /* Disconnecting the client should fail */
117  Status = NpDisconnectPipe(ClientHandle);
119  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
120  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
121 
122  /* Listening on the client should fail */
123  Status = NpListenPipe(ClientHandle);
125  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
126  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
127 
128  /* Close client */
129  if (ClientHandle)
130  ObCloseHandle(ClientHandle, KernelMode);
131  CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
132 
133  /* Connecting a client now should fail */
134  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
135  ok_bool_true(Okay, "CheckConnectPipe returned");
136  ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
137  if (NT_SUCCESS(ConnectContext.Connect.Status))
138  ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
139  CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
140 
141  /* Listening should fail */
142  Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
143  ok_bool_true(Okay, "CheckListenPipe returned");
144  if (!skip(Okay, "Listen succeeded unexpectedly\n"))
145  CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
146 
147  /* Disconnect server */
148  Status = NpDisconnectPipe(ServerHandle);
151 
152  /* Disconnecting again should fail */
153  Status = NpDisconnectPipe(ServerHandle);
156 
157  /* Connecting a client now should fail */
158  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
159  ok_bool_true(Okay, "CheckConnectPipe returned");
160  ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
161  if (NT_SUCCESS(ConnectContext.Connect.Status))
162  ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
164 
165  /**************************************************************************/
166  /* Now listen again */
167  Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
168  ok_bool_false(Okay, "CheckListenPipe returned");
169  //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
170 
171  /* Connect client */
172  ClientHandle = NULL;
173  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
174  ok_bool_true(Okay, "CheckConnectPipe returned");
175  ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
176  if (NT_SUCCESS(ConnectContext.Connect.Status))
177  {
178  ClientHandle = ConnectContext.Connect.ClientHandle;
179  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
180  }
181  Okay = WaitForWork(&ListenContext, 100);
182  ok_bool_true(Okay, "WaitForWork returned");
183  ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
184  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
185 
186  /* Listening again should fail */
187  Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
188  ok_bool_true(Okay, "CheckListenPipe returned");
189  ok_eq_hex(ListenContext.Listen.Status, STATUS_PIPE_CONNECTED);
190  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
191  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
192 
193  /* Disconnect server */
194  Status = NpDisconnectPipe(ServerHandle);
196  NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
198 
199  /* Close client */
200  if (ClientHandle)
201  ObCloseHandle(ClientHandle, KernelMode);
203 
204  /**************************************************************************/
205  /* Listen once more */
206  Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
207  ok_bool_false(Okay, "CheckListenPipe returned");
208  //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
209 
210  /* Connect client */
211  ClientHandle = NULL;
212  Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
213  ok_bool_true(Okay, "CheckConnectPipe returned");
214  ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
215  if (NT_SUCCESS(ConnectContext.Connect.Status))
216  {
217  ClientHandle = ConnectContext.Connect.ClientHandle;
218  CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
219  }
220  Okay = WaitForWork(&ListenContext, 100);
221  ok_bool_true(Okay, "WaitForWork returned");
222  ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
223  CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
224 
225  /* Close server */
226  Status = ObCloseHandle(ServerHandle, KernelMode);
228  CheckClient(ClientHandle, FILE_PIPE_CLOSING_STATE);
229 
230  /* Close client */
231  if (ClientHandle)
232  ObCloseHandle(ClientHandle, KernelMode);
233 
234  FinishWorkerThread(&ListenContext);
235  FinishWorkerThread(&ConnectContext);
236 }
237 
238 static KSTART_ROUTINE RunTest;
239 static
240 VOID
241 NTAPI
243  IN PVOID Context)
244 {
246  HANDLE ServerHandle;
247 
249 
250  ServerHandle = INVALID_HANDLE_VALUE;
251  Status = NpCreatePipe(&ServerHandle,
252  DEVICE_NAMED_PIPE L"\\KmtestNpfsConnectTestPipe",
255  IN_QUOTA,
256  OUT_QUOTA);
258  ok(ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE, "ServerHandle = %p\n", ServerHandle);
259  if (!skip(NT_SUCCESS(Status) && ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE, "No pipe\n"))
260  {
261  CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
262  TestConnect(ServerHandle, DEVICE_NAMED_PIPE L"\\KmtestNpfsConnectTestPipe");
263  }
264 }
265 
266 START_TEST(NpfsConnect)
267 {
269 
272 }
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)
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL)
struct _THREAD_CONTEXT::@1566::@1569 Listen
#define CheckClient(ClientHandle, State)
Definition: NpfsConnect.c:23
#define STATUS_PIPE_DISCONNECTED
Definition: ntstatus.h:398
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
BOOLEAN TriggerWork(IN PTHREAD_CONTEXT Context, IN ULONG MilliSeconds)
Definition: NpfsHelpers.c:710
VOID StartWorkerThread(OUT PTHREAD_CONTEXT Context)
Definition: NpfsHelpers.c:674
LONG NTSTATUS
Definition: precomp.h:26
#define DEVICE_NAMED_PIPE
Definition: npfs.h:11
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define FILE_PIPE_CONNECTED_STATE
Definition: winternl.h:792
VOID FinishWorkerThread(IN PTHREAD_CONTEXT Context)
Definition: NpfsHelpers.c:685
#define CheckServer(ServerHandle, State)
Definition: NpfsConnect.c:15
#define ok_bool_false(value, desc)
Definition: kmt_test.h:257
#define ok_bool_true(value, desc)
Definition: kmt_test.h:256
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
START_TEST(NpfsConnect)
Definition: NpfsConnect.c:266
static BOOLEAN CheckListenPipe(IN PTHREAD_CONTEXT Context, IN HANDLE ServerHandle, IN ULONG MilliSeconds)
Definition: NpfsConnect.c:67
#define FILE_PIPE_LISTENING_STATE
Definition: winternl.h:791
static VOID TestConnect(IN HANDLE ServerHandle, IN PCWSTR PipePath)
Definition: NpfsConnect.c:79
NTSTATUS NpOpenPipe(OUT PHANDLE ClientHandle, IN PCWSTR PipePath, IN ULONG NamedPipeConfiguration)
Definition: NpfsHelpers.c:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define DUPLEX
Definition: npfs.h:21
#define NpDisconnectPipe(ServerHandle)
Definition: npfs.h:74
#define IN_QUOTA
Definition: NpfsConnect.c:12
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
static VOID ListenPipe(IN OUT PTHREAD_CONTEXT Context)
Definition: NpfsConnect.c:47
#define STATUS_PIPE_CONNECTED
Definition: ntstatus.h:400
static const WCHAR L[]
Definition: oid.c:1250
#define BYTE_STREAM
Definition: npfs.h:13
static BOOLEAN CheckConnectPipe(IN PTHREAD_CONTEXT Context, IN PCWSTR PipePath, IN ULONG MilliSeconds)
Definition: NpfsConnect.c:55
VOID KmtFinishThread(IN PKTHREAD Thread OPTIONAL, IN PKEVENT Event OPTIONAL)
Status
Definition: gdiplustypes.h:24
BOOLEAN WaitForWork(IN PTHREAD_CONTEXT Context, IN ULONG MilliSeconds)
Definition: NpfsHelpers.c:692
#define FILE_PIPE_DISCONNECTED_STATE
Definition: winternl.h:790
#define NpQueryPipe(h, es)
Definition: npfs.h:147
static VOID ConnectPipe(IN OUT PTHREAD_CONTEXT Context)
Definition: NpfsConnect.c:33
static KSTART_ROUTINE RunTest
Definition: NpfsConnect.c:238
#define ok(value,...)
Definition: atltest.h:57
#define QUEUE
Definition: npfs.h:17
#define skip(...)
Definition: atltest.h:64
#define FILE_PIPE_CLOSING_STATE
Definition: winternl.h:793
#define OUT
Definition: typedefs.h:39
#define OUT_QUOTA
Definition: NpfsConnect.c:13
#define MAX_INSTANCES
Definition: NpfsConnect.c:11
unsigned int ULONG
Definition: retypes.h:1
#define FILE_PIPE_FULL_DUPLEX
Definition: iotypes.h:83
#define ok_eq_hex(value, expected)
struct _THREAD_CONTEXT::@1566::@1568 Connect
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define STATUS_ILLEGAL_FUNCTION
Definition: ntstatus.h:397
#define STATUS_PIPE_NOT_AVAILABLE
Definition: ntstatus.h:394
#define NpListenPipe(ServerHandle)
Definition: npfs.h:73