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 Read/Write test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9 #include "npfs.h"
10
11 typedef struct _READ_WRITE_TEST_CONTEXT
12 {
13 PCWSTR PipePath;
14 BOOLEAN ServerSynchronous;
15 BOOLEAN ClientSynchronous;
16 } READ_WRITE_TEST_CONTEXT, *PREAD_WRITE_TEST_CONTEXT;
17
18 #define MAX_INSTANCES 5
19 #define IN_QUOTA 4096
20 #define OUT_QUOTA 4096
21
22 #define MakeServer(ServerHandle, PipePath, ServerSynchronous) \
23 NpCreatePipeEx(ServerHandle, \
24 PipePath, \
25 BYTE_STREAM, \
26 QUEUE, \
27 BYTE_STREAM, \
28 FILE_SHARE_READ | FILE_SHARE_WRITE, \
29 MAX_INSTANCES, \
30 IN_QUOTA, \
31 OUT_QUOTA, \
32 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, \
33 FILE_OPEN_IF, \
34 (ServerSynchronous) ? FILE_SYNCHRONOUS_IO_NONALERT \
35 : 0, \
36 &DefaultTimeout)
37
38 #define CheckServer(ServerHandle, State) \
39 NpCheckServerPipe(ServerHandle, \
40 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
41 MAX_INSTANCES, 1, \
42 IN_QUOTA, 0, \
43 OUT_QUOTA, OUT_QUOTA, \
44 State)
45
46 #define CheckClient(ClientHandle, State) \
47 NpCheckClientPipe(ClientHandle, \
48 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
49 MAX_INSTANCES, 1, \
50 IN_QUOTA, 0, \
51 OUT_QUOTA, OUT_QUOTA, \
52 State)
53
54 #define CheckServerQuota(ServerHandle, InQ, OutQ) \
55 NpCheckServerPipe(ServerHandle, \
56 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
57 MAX_INSTANCES, 1, \
58 IN_QUOTA, InQ, \
59 OUT_QUOTA, OUT_QUOTA - (OutQ), \
60 FILE_PIPE_CONNECTED_STATE)
61
62 #define CheckClientQuota(ClientHandle, InQ, OutQ) \
63 NpCheckClientPipe(ClientHandle, \
64 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
65 MAX_INSTANCES, 1, \
66 IN_QUOTA, InQ, \
67 OUT_QUOTA, OUT_QUOTA - (OutQ), \
68 FILE_PIPE_CONNECTED_STATE)
69
70 #define CheckPipeContext(Context, ExpectedStatus, ExpectedBytes) do \
71 { \
72 ok_bool_true(Okay, "CheckPipeContext"); \
73 ok_eq_hex((Context)->ReadWrite.Status, ExpectedStatus); \
74 ok_eq_ulongptr((Context)->ReadWrite.BytesTransferred, ExpectedBytes); \
75 } while (0)
76
77 static
78 VOID
ConnectPipe(IN OUT PTHREAD_CONTEXT Context)79 ConnectPipe(
80 IN OUT PTHREAD_CONTEXT Context)
81 {
82 HANDLE ClientHandle;
83
84 ClientHandle = NULL;
85 Context->Connect.Status = NpOpenPipeEx(&ClientHandle,
86 Context->Connect.PipePath,
87 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
88 FILE_SHARE_READ | FILE_SHARE_WRITE,
89 FILE_OPEN,
90 Context->Connect.ClientSynchronous ? FILE_SYNCHRONOUS_IO_NONALERT
91 : 0);
92 Context->Connect.ClientHandle = ClientHandle;
93 }
94
95 static
96 VOID
ListenPipe(IN OUT PTHREAD_CONTEXT Context)97 ListenPipe(
98 IN OUT PTHREAD_CONTEXT Context)
99 {
100 Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle);
101 }
102
103 static
104 VOID
ReadPipe(IN OUT PTHREAD_CONTEXT Context)105 ReadPipe(
106 IN OUT PTHREAD_CONTEXT Context)
107 {
108 Context->ReadWrite.Status = NpReadPipe(Context->ReadWrite.PipeHandle,
109 Context->ReadWrite.Buffer,
110 Context->ReadWrite.BufferSize,
111 (PULONG_PTR)&Context->ReadWrite.BytesTransferred);
112 }
113
114 static
115 VOID
WritePipe(IN OUT PTHREAD_CONTEXT Context)116 WritePipe(
117 IN OUT PTHREAD_CONTEXT Context)
118 {
119 Context->ReadWrite.Status = NpWritePipe(Context->ReadWrite.PipeHandle,
120 Context->ReadWrite.Buffer,
121 Context->ReadWrite.BufferSize,
122 (PULONG_PTR)&Context->ReadWrite.BytesTransferred);
123 }
124
125 static
126 BOOLEAN
CheckConnectPipe(IN PTHREAD_CONTEXT Context,IN PCWSTR PipePath,IN BOOLEAN ClientSynchronous,IN ULONG MilliSeconds)127 CheckConnectPipe(
128 IN PTHREAD_CONTEXT Context,
129 IN PCWSTR PipePath,
130 IN BOOLEAN ClientSynchronous,
131 IN ULONG MilliSeconds)
132 {
133 Context->Work = ConnectPipe;
134 Context->Connect.PipePath = PipePath;
135 Context->Connect.ClientSynchronous = ClientSynchronous;
136 return TriggerWork(Context, MilliSeconds);
137 }
138
139 static
140 BOOLEAN
CheckListenPipe(IN PTHREAD_CONTEXT Context,IN HANDLE ServerHandle,IN ULONG MilliSeconds)141 CheckListenPipe(
142 IN PTHREAD_CONTEXT Context,
143 IN HANDLE ServerHandle,
144 IN ULONG MilliSeconds)
145 {
146 Context->Work = ListenPipe;
147 Context->Listen.ServerHandle = ServerHandle;
148 return TriggerWork(Context, MilliSeconds);
149 }
150
151 static
152 BOOLEAN
CheckReadPipe(IN PTHREAD_CONTEXT Context,IN HANDLE PipeHandle,OUT PVOID Buffer,IN ULONG BufferSize,IN ULONG MilliSeconds)153 CheckReadPipe(
154 IN PTHREAD_CONTEXT Context,
155 IN HANDLE PipeHandle,
156 OUT PVOID Buffer,
157 IN ULONG BufferSize,
158 IN ULONG MilliSeconds)
159 {
160 Context->Work = ReadPipe;
161 Context->ReadWrite.PipeHandle = PipeHandle;
162 Context->ReadWrite.Buffer = Buffer;
163 Context->ReadWrite.BufferSize = BufferSize;
164 return TriggerWork(Context, MilliSeconds);
165 }
166
167 static
168 BOOLEAN
CheckWritePipe(IN PTHREAD_CONTEXT Context,IN HANDLE PipeHandle,IN const VOID * Buffer,IN ULONG BufferSize,IN ULONG MilliSeconds)169 CheckWritePipe(
170 IN PTHREAD_CONTEXT Context,
171 IN HANDLE PipeHandle,
172 IN const VOID *Buffer,
173 IN ULONG BufferSize,
174 IN ULONG MilliSeconds)
175 {
176 Context->Work = WritePipe;
177 Context->ReadWrite.PipeHandle = PipeHandle;
178 Context->ReadWrite.Buffer = (PVOID)Buffer;
179 Context->ReadWrite.BufferSize = BufferSize;
180 return TriggerWork(Context, MilliSeconds);
181 }
182
183 static KSTART_ROUTINE TestReadWrite;
184 static
185 VOID
186 NTAPI
TestReadWrite(IN PVOID Context)187 TestReadWrite(
188 IN PVOID Context)
189 {
190 PREAD_WRITE_TEST_CONTEXT TestContext = Context;
191 PCWSTR PipePath = TestContext->PipePath;
192 BOOLEAN ServerSynchronous = TestContext->ServerSynchronous;
193 BOOLEAN ClientSynchronous = TestContext->ClientSynchronous;
194 NTSTATUS Status;
195 HANDLE ServerHandle;
196 LARGE_INTEGER DefaultTimeout;
197 THREAD_CONTEXT ConnectContext;
198 THREAD_CONTEXT ListenContext;
199 THREAD_CONTEXT ClientReadContext;
200 THREAD_CONTEXT ClientWriteContext;
201 THREAD_CONTEXT ServerReadContext;
202 THREAD_CONTEXT ServerWriteContext;
203 BOOLEAN Okay;
204 HANDLE ClientHandle;
205 UCHAR ReadBuffer[128];
206 UCHAR WriteBuffer[128];
207
208 StartWorkerThread(&ConnectContext);
209 StartWorkerThread(&ListenContext);
210 StartWorkerThread(&ClientReadContext);
211 StartWorkerThread(&ClientWriteContext);
212 StartWorkerThread(&ServerReadContext);
213 StartWorkerThread(&ServerWriteContext);
214
215 DefaultTimeout.QuadPart = -50 * 1000 * 10;
216
217 /* Server should start out listening */
218 Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
219 ok_eq_hex(Status, STATUS_SUCCESS);
220 CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
221
222 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, NULL, 0, 100);
223 ok_bool_true(Okay, "CheckWritePipe returned");
224 ok_eq_ulongptr(ServerWriteContext.ReadWrite.BytesTransferred, 0);
225 ok_eq_hex(ServerWriteContext.ReadWrite.Status, STATUS_PIPE_LISTENING);
226
227 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, NULL, 0, 100);
228 ok_bool_true(Okay, "CheckReadPipe returned");
229 ok_eq_ulongptr(ServerReadContext.ReadWrite.BytesTransferred, 0);
230 ok_eq_hex(ServerReadContext.ReadWrite.Status, STATUS_PIPE_LISTENING);
231
232 /* Connect a client */
233 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
234 ok_bool_true(Okay, "CheckConnectPipe returned");
235 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
236 ClientHandle = ConnectContext.Connect.ClientHandle;
237 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
238 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
239
240 /** Server to client, write first, 1 byte */
241 WriteBuffer[0] = 'A';
242 ReadBuffer[0] = 'X';
243 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
244 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
245 CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
246 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
247 CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
248 ok_eq_uint(ReadBuffer[0], 'A');
249 CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
250
251 /** Server to client, read first, 1 byte */
252 WriteBuffer[0] = 'B';
253 ReadBuffer[0] = 'X';
254 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
255 ok_bool_false(Okay, "CheckReadPipe returned");
256 CheckServerQuota(ServerHandle, 0, 1);
257 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
258 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
259 Okay = WaitForWork(&ClientReadContext, 100);
260 CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
261 ok_eq_uint(ReadBuffer[0], 'B');
262 CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
263
264 /** Client to server, write first, 1 byte */
265 WriteBuffer[0] = 'C';
266 ReadBuffer[0] = 'X';
267 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
268 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
269 CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
270 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
271 CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
272 ok_eq_uint(ReadBuffer[0], 'C');
273 CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
274
275 /** Client to server, read first, 1 byte */
276 WriteBuffer[0] = 'D';
277 ReadBuffer[0] = 'X';
278 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
279 ok_bool_false(Okay, "CheckReadPipe returned");
280 CheckClientQuota(ClientHandle, 0, 1);
281 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
282 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
283 Okay = WaitForWork(&ServerReadContext, 100);
284 CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
285 ok_eq_uint(ReadBuffer[0], 'D');
286 CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
287
288 /** Server to client, write 0 bytes */
289 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, (PVOID)1, 0, 100);
290 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 0);
291 CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
292
293 /** Client to Server, write 0 bytes */
294 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, (PVOID)1, 0, 100);
295 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 0);
296 CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
297
298 /** Server to client, read 0 bytes blocks, write 0 bytes does not unblock, write 1 byte unblocks */
299 WriteBuffer[0] = 'E';
300 ReadBuffer[0] = 'X';
301 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, (PVOID)1, 0, 100);
302 ok_bool_false(Okay, "CheckReadPipe returned");
303 CheckServerQuota(ServerHandle, 0, 0);
304 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, (PVOID)1, 0, 100);
305 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 0);
306 Okay = WaitForWork(&ClientReadContext, 100);
307 ok_bool_false(Okay, "WaitForWork returned");
308 CheckServerQuota(ServerHandle, 0, 0);
309 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
310 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
311 Okay = WaitForWork(&ClientReadContext, 100);
312 CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 0);
313 ok_eq_uint(ReadBuffer[0], 'X');
314 CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
315 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
316 CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
317 ok_eq_uint(ReadBuffer[0], 'E');
318 CheckServerQuota(ServerHandle, 0, 0); CheckClientQuota(ClientHandle, 0, 0);
319
320 /** Client to server, read 0 bytes blocks, write 0 bytes does not unblock, write 1 byte unblocks */
321 WriteBuffer[0] = 'F';
322 ReadBuffer[0] = 'X';
323 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, (PVOID)1, 0, 100);
324 ok_bool_false(Okay, "CheckReadPipe returned");
325 CheckClientQuota(ClientHandle, 0, 0);
326 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, (PVOID)1, 0, 100);
327 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 0);
328 Okay = WaitForWork(&ServerReadContext, 100);
329 ok_bool_false(Okay, "WaitForWork returned");
330 CheckClientQuota(ClientHandle, 0, 0);
331 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
332 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
333 Okay = WaitForWork(&ServerReadContext, 100);
334 CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 0);
335 ok_eq_uint(ReadBuffer[0], 'X');
336 CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
337 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
338 CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
339 ok_eq_uint(ReadBuffer[0], 'F');
340 CheckClientQuota(ClientHandle, 0, 0); CheckServerQuota(ServerHandle, 0, 0);
341
342 /** Disconnect server with pending read on client */
343 WriteBuffer[0] = 'G';
344 ReadBuffer[0] = 'X';
345 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
346 ok_bool_false(Okay, "CheckReadPipe returned");
347 CheckServerQuota(ServerHandle, 0, 1);
348 Status = NpDisconnectPipe(ServerHandle);
349 ok_eq_hex(Status, STATUS_SUCCESS);
350 Okay = WaitForWork(&ClientReadContext, 100);
351 CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
352 ok_eq_uint(ReadBuffer[0], 'X');
353
354 /* Read from server when disconnected */
355 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
356 CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
357
358 /* Write to server when disconnected */
359 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
360 CheckPipeContext(&ServerWriteContext, STATUS_PIPE_DISCONNECTED, 0);
361
362 /* Read from client when disconnected */
363 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
364 CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
365
366 /* Write to client when disconnected */
367 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
368 CheckPipeContext(&ClientWriteContext, STATUS_PIPE_DISCONNECTED, 0);
369 Status = ObCloseHandle(ClientHandle, KernelMode);
370 ok_eq_hex(Status, STATUS_SUCCESS);
371
372 /* Restore the connection */
373 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
374 ok_bool_false(Okay, "CheckListenPipe returned");
375 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
376 ok_bool_true(Okay, "CheckConnectPipe returned");
377 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
378 Okay = WaitForWork(&ListenContext, 100);
379 ok_bool_true(Okay, "WaitForWork returned");
380 ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
381 ClientHandle = ConnectContext.Connect.ClientHandle;
382 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
383 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
384
385 /** Close server with pending read on client */
386 WriteBuffer[0] = 'H';
387 ReadBuffer[0] = 'X';
388 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
389 ok_bool_false(Okay, "CheckReadPipe returned");
390 Status = ObCloseHandle(ServerHandle, KernelMode);
391 ok_eq_hex(Status, STATUS_SUCCESS);
392 Okay = WaitForWork(&ClientReadContext, 100);
393 CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
394 ok_eq_uint(ReadBuffer[0], 'X');
395
396 /* Read from client when closed */
397 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
398 CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
399
400 /* Write to client when closed */
401 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
402 CheckPipeContext(&ClientWriteContext, STATUS_PIPE_CLOSING, 0);
403 Status = ObCloseHandle(ClientHandle, KernelMode);
404 ok_eq_hex(Status, STATUS_SUCCESS);
405
406 /* Restore the connection */
407 Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
408 ok_eq_hex(Status, STATUS_SUCCESS);
409 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
410 ok_bool_true(Okay, "CheckConnectPipe returned");
411 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
412 ClientHandle = ConnectContext.Connect.ClientHandle;
413 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
414 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
415
416 /** Close client with pending read on server */
417 WriteBuffer[0] = 'I';
418 ReadBuffer[0] = 'X';
419 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
420 ok_bool_false(Okay, "CheckReadPipe returned");
421 Status = ObCloseHandle(ClientHandle, KernelMode);
422 ok_eq_hex(Status, STATUS_SUCCESS);
423 Okay = WaitForWork(&ServerReadContext, 100);
424 CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
425 ok_eq_uint(ReadBuffer[0], 'X');
426
427 /* Read from server when closed */
428 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
429 CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
430
431 /* Write to server when closed */
432 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
433 CheckPipeContext(&ServerWriteContext, STATUS_PIPE_CLOSING, 0);
434 Status = ObCloseHandle(ServerHandle, KernelMode);
435 ok_eq_hex(Status, STATUS_SUCCESS);
436
437 /* Restore the connection */
438 Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
439 ok_eq_hex(Status, STATUS_SUCCESS);
440 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
441 ok_bool_true(Okay, "CheckConnectPipe returned");
442 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
443 ClientHandle = ConnectContext.Connect.ClientHandle;
444 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
445 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
446
447 /** Write to server and disconnect, then read from client */
448 WriteBuffer[0] = 'J';
449 ReadBuffer[0] = 'X';
450 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
451 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
452 CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
453 Status = NpDisconnectPipe(ServerHandle);
454 ok_eq_hex(Status, STATUS_SUCCESS);
455 NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
456 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
457 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
458 CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
459 ok_eq_uint(ReadBuffer[0], 'X');
460 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
461 CheckPipeContext(&ClientReadContext, STATUS_PIPE_DISCONNECTED, 0);
462 Status = ObCloseHandle(ClientHandle, KernelMode);
463 ok_eq_hex(Status, STATUS_SUCCESS);
464
465 /* Restore the connection */
466 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
467 ok_bool_false(Okay, "CheckListenPipe returned");
468 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
469 ok_bool_true(Okay, "CheckConnectPipe returned");
470 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
471 Okay = WaitForWork(&ListenContext, 100);
472 ok_bool_true(Okay, "WaitForWork returned");
473 ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
474 ClientHandle = ConnectContext.Connect.ClientHandle;
475 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
476 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
477
478 /** Write to server and close, then read from client */
479 WriteBuffer[0] = 'K';
480 ReadBuffer[0] = 'X';
481 Okay = CheckWritePipe(&ServerWriteContext, ServerHandle, WriteBuffer, 1, 100);
482 CheckPipeContext(&ServerWriteContext, STATUS_SUCCESS, 1);
483 CheckServerQuota(ServerHandle, 0, 1); CheckClientQuota(ClientHandle, 1, 0);
484 Status = ObCloseHandle(ServerHandle, KernelMode);
485 ok_eq_hex(Status, STATUS_SUCCESS);
486 NpCheckClientPipe(ClientHandle,
487 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
488 MAX_INSTANCES, 1,
489 IN_QUOTA, 1,
490 OUT_QUOTA, OUT_QUOTA,
491 FILE_PIPE_CLOSING_STATE);
492 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
493 CheckPipeContext(&ClientReadContext, STATUS_SUCCESS, 1);
494 ok_eq_uint(ReadBuffer[0], 'K');
495 Okay = CheckReadPipe(&ClientReadContext, ClientHandle, ReadBuffer, 1, 100);
496 CheckPipeContext(&ClientReadContext, STATUS_PIPE_BROKEN, 0);
497 Status = ObCloseHandle(ClientHandle, KernelMode);
498 ok_eq_hex(Status, STATUS_SUCCESS);
499
500 /* Restore the connection */
501 Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
502 ok_eq_hex(Status, STATUS_SUCCESS);
503 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
504 ok_bool_true(Okay, "CheckConnectPipe returned");
505 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
506 ClientHandle = ConnectContext.Connect.ClientHandle;
507 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
508 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
509
510
511 /** Write to client and close, then read from server */
512 WriteBuffer[0] = 'L';
513 ReadBuffer[0] = 'X';
514 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
515 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
516 CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
517 Status = ObCloseHandle(ClientHandle, KernelMode);
518 ok_eq_hex(Status, STATUS_SUCCESS);
519 NpCheckServerPipe(ServerHandle,
520 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
521 MAX_INSTANCES, 1,
522 IN_QUOTA, 1,
523 OUT_QUOTA, OUT_QUOTA,
524 FILE_PIPE_CLOSING_STATE);
525 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
526 CheckPipeContext(&ServerReadContext, STATUS_SUCCESS, 1);
527 ok_eq_uint(ReadBuffer[0], 'L');
528 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
529 CheckPipeContext(&ServerReadContext, STATUS_PIPE_BROKEN, 0);
530 Status = ObCloseHandle(ServerHandle, KernelMode);
531 ok_eq_hex(Status, STATUS_SUCCESS);
532
533 /* Restore the connection */
534 Status = MakeServer(&ServerHandle, PipePath, ServerSynchronous);
535 ok_eq_hex(Status, STATUS_SUCCESS);
536 Okay = CheckConnectPipe(&ConnectContext, PipePath, ClientSynchronous, 100);
537 ok_bool_true(Okay, "CheckConnectPipe returned");
538 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
539 ClientHandle = ConnectContext.Connect.ClientHandle;
540 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
541 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
542
543 /** Write to client and disconnect server, then read from server */
544 WriteBuffer[0] = 'M';
545 ReadBuffer[0] = 'X';
546 Okay = CheckWritePipe(&ClientWriteContext, ClientHandle, WriteBuffer, 1, 100);
547 CheckPipeContext(&ClientWriteContext, STATUS_SUCCESS, 1);
548 CheckClientQuota(ClientHandle, 0, 1); CheckServerQuota(ServerHandle, 1, 0);
549 Status = NpDisconnectPipe(ServerHandle);
550 ok_eq_hex(Status, STATUS_SUCCESS);
551 NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
552 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
553 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
554 CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
555 ok_eq_uint(ReadBuffer[0], 'X');
556 Okay = CheckReadPipe(&ServerReadContext, ServerHandle, ReadBuffer, 1, 100);
557 CheckPipeContext(&ServerReadContext, STATUS_PIPE_DISCONNECTED, 0);
558 Status = ObCloseHandle(ClientHandle, KernelMode);
559 ok_eq_hex(Status, STATUS_SUCCESS);
560
561 Status = ObCloseHandle(ServerHandle, KernelMode);
562 ok_eq_hex(Status, STATUS_SUCCESS);
563
564 FinishWorkerThread(&ServerWriteContext);
565 FinishWorkerThread(&ServerReadContext);
566 FinishWorkerThread(&ClientWriteContext);
567 FinishWorkerThread(&ClientReadContext);
568 FinishWorkerThread(&ListenContext);
569 FinishWorkerThread(&ConnectContext);
570 }
571
START_TEST(NpfsReadWrite)572 START_TEST(NpfsReadWrite)
573 {
574 PKTHREAD Thread;
575 READ_WRITE_TEST_CONTEXT TestContext;
576
577 TestContext.PipePath = DEVICE_NAMED_PIPE L"\\KmtestNpfsReadWriteTestPipe";
578
579 TestContext.ServerSynchronous = TRUE;
580 TestContext.ClientSynchronous = TRUE;
581 Thread = KmtStartThread(TestReadWrite, &TestContext);
582 KmtFinishThread(Thread, NULL);
583
584 TestContext.ServerSynchronous = FALSE;
585 TestContext.ClientSynchronous = TRUE;
586 Thread = KmtStartThread(TestReadWrite, &TestContext);
587 KmtFinishThread(Thread, NULL);
588
589 TestContext.ServerSynchronous = TRUE;
590 TestContext.ClientSynchronous = FALSE;
591 Thread = KmtStartThread(TestReadWrite, &TestContext);
592 KmtFinishThread(Thread, NULL);
593
594 TestContext.ServerSynchronous = FALSE;
595 TestContext.ClientSynchronous = FALSE;
596 Thread = KmtStartThread(TestReadWrite, &TestContext);
597 KmtFinishThread(Thread, NULL);
598 }
599