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 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 97 ListenPipe( 98 IN OUT PTHREAD_CONTEXT Context) 99 { 100 Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle); 101 } 102 103 static 104 VOID 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 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 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 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 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 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 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 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