Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3332 lines
110 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. fastio.c
  5. Abstract:
  6. This module contains routines for handling fast ("turbo") IO
  7. in AFD.
  8. Author:
  9. David Treadwell (davidtr) 12-Oct-1992
  10. Revision History:
  11. VadimE 14-Jan-1998 Restructurred the code.
  12. --*/
  13. #include "afdp.h"
  14. BOOLEAN
  15. AfdFastConnectionReceive (
  16. IN PAFD_ENDPOINT endpoint,
  17. IN PAFD_RECV_INFO recvInfo,
  18. IN ULONG recvLength,
  19. OUT PIO_STATUS_BLOCK IoStatus
  20. );
  21. BOOLEAN
  22. AfdFastDatagramReceive (
  23. IN PAFD_ENDPOINT endpoint,
  24. IN PAFD_RECV_MESSAGE_INFO recvInfo,
  25. IN ULONG recvLength,
  26. OUT PIO_STATUS_BLOCK IoStatus
  27. );
  28. BOOLEAN
  29. AfdFastConnectionSend (
  30. IN PAFD_ENDPOINT endpoint,
  31. IN PAFD_SEND_INFO sendInfo,
  32. IN ULONG sendLength,
  33. OUT PIO_STATUS_BLOCK IoStatus
  34. );
  35. BOOLEAN
  36. AfdFastDatagramSend (
  37. IN PAFD_ENDPOINT endpoint,
  38. IN PAFD_SEND_DATAGRAM_INFO sendInfo,
  39. IN ULONG sendLength,
  40. OUT PIO_STATUS_BLOCK IoStatus
  41. );
  42. NTSTATUS
  43. AfdRestartFastDatagramSend (
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PIRP Irp,
  46. IN PVOID Context
  47. );
  48. #ifdef ALLOC_PRAGMA
  49. #pragma alloc_text( PAGE, AfdFastIoDeviceControl )
  50. #pragma alloc_text( PAGE, AfdFastIoRead )
  51. #pragma alloc_text( PAGE, AfdFastIoWrite )
  52. #pragma alloc_text( PAGEAFD, AfdFastDatagramSend )
  53. #pragma alloc_text( PAGEAFD, AfdFastDatagramReceive )
  54. #pragma alloc_text( PAGEAFD, AfdFastConnectionSend )
  55. #pragma alloc_text( PAGEAFD, AfdFastConnectionReceive )
  56. #pragma alloc_text( PAGEAFD, AfdRestartFastDatagramSend )
  57. #pragma alloc_text( PAGEAFD, AfdShouldSendBlock )
  58. #endif
  59. #if AFD_PERF_DBG
  60. BOOLEAN
  61. AfdFastIoReadReal (
  62. IN struct _FILE_OBJECT *FileObject,
  63. IN PLARGE_INTEGER FileOffset,
  64. IN ULONG Length,
  65. IN BOOLEAN Wait,
  66. IN ULONG LockKey,
  67. OUT PVOID Buffer,
  68. OUT PIO_STATUS_BLOCK IoStatus,
  69. IN struct _DEVICE_OBJECT *DeviceObject
  70. );
  71. BOOLEAN
  72. AfdFastIoRead (
  73. IN struct _FILE_OBJECT *FileObject,
  74. IN PLARGE_INTEGER FileOffset,
  75. IN ULONG Length,
  76. IN BOOLEAN Wait,
  77. IN ULONG LockKey,
  78. OUT PVOID Buffer,
  79. OUT PIO_STATUS_BLOCK IoStatus,
  80. IN struct _DEVICE_OBJECT *DeviceObject
  81. )
  82. {
  83. BOOLEAN success;
  84. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  85. success = AfdFastIoReadReal (
  86. FileObject,
  87. FileOffset,
  88. Length,
  89. Wait,
  90. LockKey,
  91. Buffer,
  92. IoStatus,
  93. DeviceObject
  94. );
  95. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  96. if ( success ) {
  97. InterlockedIncrement (&AfdFastReadsSucceeded);
  98. ASSERT (IoStatus->Status == STATUS_SUCCESS ||
  99. IoStatus->Status == STATUS_DEVICE_NOT_READY );
  100. } else {
  101. InterlockedIncrement (&AfdFastReadsFailed);
  102. }
  103. return success;
  104. }
  105. BOOLEAN
  106. AfdFastIoReadReal (
  107. IN struct _FILE_OBJECT *FileObject,
  108. IN PLARGE_INTEGER FileOffset,
  109. IN ULONG Length,
  110. IN BOOLEAN Wait,
  111. IN ULONG LockKey,
  112. OUT PVOID Buffer,
  113. OUT PIO_STATUS_BLOCK IoStatus,
  114. IN struct _DEVICE_OBJECT *DeviceObject
  115. )
  116. #else // AFD_PERF_DBG
  117. BOOLEAN
  118. AfdFastIoRead (
  119. IN struct _FILE_OBJECT *FileObject,
  120. IN PLARGE_INTEGER FileOffset,
  121. IN ULONG Length,
  122. IN BOOLEAN Wait,
  123. IN ULONG LockKey,
  124. OUT PVOID Buffer,
  125. OUT PIO_STATUS_BLOCK IoStatus,
  126. IN struct _DEVICE_OBJECT *DeviceObject
  127. )
  128. #endif // AFD_PERF_DBG
  129. {
  130. PAFD_ENDPOINT endpoint;
  131. WSABUF buf;
  132. PAGED_CODE( );
  133. //
  134. // All we want to do is pass the request through to the TDI provider
  135. // if possible. If not, we want to bail out of this code path back
  136. // onto the main code path (with IRPs) with as little performance
  137. // overhead as possible.
  138. //
  139. // Thus this routine only does general preliminary checks and input
  140. // parameter validation. If it is determined that fast io path is
  141. // likely to succeed, an operation specific routine is called
  142. // to handle all the details.
  143. //
  144. endpoint = FileObject->FsContext;
  145. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  146. //
  147. // If fast IO recv is disabled
  148. // or the endpoint is shut down in any way
  149. // or the endpoint isn't connected yet
  150. // or the TDI provider for this endpoint supports bufferring,
  151. // we do not want to do fast IO on it
  152. //
  153. if (endpoint->DisableFastIoRecv ||
  154. endpoint->DisconnectMode != 0 ||
  155. endpoint->State != AfdEndpointStateConnected ||
  156. IS_TDI_BUFFERRING(endpoint)) {
  157. return FALSE;
  158. }
  159. //
  160. // Fake buffer array.
  161. //
  162. buf.buf = Buffer;
  163. buf.len = Length;
  164. //
  165. // Call routine based on endpoint type
  166. //
  167. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  168. //
  169. // Fake input parameter strucuture
  170. //
  171. AFD_RECV_MESSAGE_INFO msgInfo;
  172. msgInfo.dgi.BufferArray = &buf;
  173. msgInfo.dgi.BufferCount = 1;
  174. msgInfo.dgi.AfdFlags = AFD_OVERLAPPED;
  175. msgInfo.dgi.TdiFlags = TDI_RECEIVE_NORMAL;
  176. msgInfo.dgi.Address = NULL;
  177. msgInfo.dgi.AddressLength = 0;
  178. msgInfo.ControlBuffer = NULL;
  179. msgInfo.ControlLength = NULL;
  180. msgInfo.MsgFlags = NULL;
  181. return AfdFastDatagramReceive(
  182. endpoint,
  183. &msgInfo,
  184. Length,
  185. IoStatus
  186. );
  187. }
  188. else if (IS_VC_ENDPOINT(endpoint)) {
  189. //
  190. // Fake input parameter strucuture
  191. //
  192. AFD_RECV_INFO recvInfo;
  193. recvInfo.BufferArray = &buf;
  194. recvInfo.BufferCount = 1;
  195. recvInfo.AfdFlags = AFD_OVERLAPPED;
  196. recvInfo.TdiFlags = TDI_RECEIVE_NORMAL;
  197. return AfdFastConnectionReceive (
  198. endpoint,
  199. &recvInfo,
  200. Length,
  201. IoStatus);
  202. }
  203. else
  204. return FALSE;
  205. } // AfdFastIoRead
  206. #if AFD_PERF_DBG
  207. BOOLEAN
  208. AfdFastIoWriteReal (
  209. IN struct _FILE_OBJECT *FileObject,
  210. IN PLARGE_INTEGER FileOffset,
  211. IN ULONG Length,
  212. IN BOOLEAN Wait,
  213. IN ULONG LockKey,
  214. OUT PVOID Buffer,
  215. OUT PIO_STATUS_BLOCK IoStatus,
  216. IN struct _DEVICE_OBJECT *DeviceObject
  217. );
  218. BOOLEAN
  219. AfdFastIoWrite (
  220. IN struct _FILE_OBJECT *FileObject,
  221. IN PLARGE_INTEGER FileOffset,
  222. IN ULONG Length,
  223. IN BOOLEAN Wait,
  224. IN ULONG LockKey,
  225. OUT PVOID Buffer,
  226. OUT PIO_STATUS_BLOCK IoStatus,
  227. IN struct _DEVICE_OBJECT *DeviceObject
  228. )
  229. {
  230. BOOLEAN success;
  231. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  232. success = AfdFastIoWriteReal (
  233. FileObject,
  234. FileOffset,
  235. Length,
  236. Wait,
  237. LockKey,
  238. Buffer,
  239. IoStatus,
  240. DeviceObject
  241. );
  242. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  243. if ( success ) {
  244. InterlockedIncrement (&AfdFastWritesSucceeded);
  245. ASSERT (IoStatus->Status == STATUS_SUCCESS ||
  246. IoStatus->Status == STATUS_DEVICE_NOT_READY);
  247. } else {
  248. InterlockedIncrement (&AfdFastWritesFailed);
  249. }
  250. return success;
  251. }
  252. BOOLEAN
  253. AfdFastIoWriteReal (
  254. IN struct _FILE_OBJECT *FileObject,
  255. IN PLARGE_INTEGER FileOffset,
  256. IN ULONG Length,
  257. IN BOOLEAN Wait,
  258. IN ULONG LockKey,
  259. IN PVOID Buffer,
  260. OUT PIO_STATUS_BLOCK IoStatus,
  261. IN struct _DEVICE_OBJECT *DeviceObject
  262. )
  263. #else // AFD_PERF_DBG
  264. BOOLEAN
  265. AfdFastIoWrite (
  266. IN struct _FILE_OBJECT *FileObject,
  267. IN PLARGE_INTEGER FileOffset,
  268. IN ULONG Length,
  269. IN BOOLEAN Wait,
  270. IN ULONG LockKey,
  271. IN PVOID Buffer,
  272. OUT PIO_STATUS_BLOCK IoStatus,
  273. IN struct _DEVICE_OBJECT *DeviceObject
  274. )
  275. #endif // AFD_PERF_DBG
  276. {
  277. PAFD_ENDPOINT endpoint;
  278. WSABUF buf;
  279. PAGED_CODE( );
  280. //
  281. // All we want to do is pass the request through to the TDI provider
  282. // if possible. If not, we want to bail out of this code path back
  283. // onto the main code path (with IRPs) with as little performance
  284. // overhead as possible.
  285. //
  286. // Thus this routine only does general preliminary checks and input
  287. // parameter validation. If it is determined that fast io path is
  288. // likely to succeed, an operation specific routine is called
  289. // to handle all the details.
  290. //
  291. endpoint = FileObject->FsContext;
  292. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  293. //
  294. // If fast IO send is disabled
  295. // or the endpoint is shut down in any way
  296. // or the endpoint isn't connected yet
  297. // or the TDI provider for this endpoint supports bufferring,
  298. // we do not want to do fast IO on it
  299. //
  300. if (endpoint->DisableFastIoSend ||
  301. endpoint->DisconnectMode != 0 ||
  302. endpoint->State != AfdEndpointStateConnected ||
  303. IS_TDI_BUFFERRING(endpoint) ) {
  304. return FALSE;
  305. }
  306. //
  307. // Fake buffer array.
  308. //
  309. buf.buf = Buffer;
  310. buf.len = Length;
  311. //
  312. // Call routine based on endpoint type
  313. //
  314. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  315. //
  316. // Fake input parameter strucuture
  317. //
  318. AFD_SEND_DATAGRAM_INFO sendInfo;
  319. sendInfo.BufferArray = &buf;
  320. sendInfo.BufferCount = 1;
  321. sendInfo.AfdFlags = AFD_OVERLAPPED;
  322. sendInfo.TdiConnInfo.RemoteAddress = NULL;
  323. sendInfo.TdiConnInfo.RemoteAddressLength = 0;
  324. return AfdFastDatagramSend(
  325. endpoint,
  326. &sendInfo,
  327. Length,
  328. IoStatus
  329. );
  330. }
  331. else if (IS_VC_ENDPOINT (endpoint)) {
  332. //
  333. // Fake input parameter strucuture
  334. //
  335. AFD_SEND_INFO sendInfo;
  336. sendInfo.BufferArray = &buf;
  337. sendInfo.BufferCount = 1;
  338. sendInfo.AfdFlags = AFD_OVERLAPPED;
  339. sendInfo.TdiFlags = 0;
  340. return AfdFastConnectionSend (
  341. endpoint,
  342. &sendInfo,
  343. Length,
  344. IoStatus);
  345. }
  346. else
  347. return FALSE;
  348. } // AfdFastIoWrite
  349. #if AFD_PERF_DBG
  350. BOOLEAN
  351. AfdFastIoDeviceControlReal (
  352. IN struct _FILE_OBJECT *FileObject,
  353. IN BOOLEAN Wait,
  354. IN PVOID InputBuffer OPTIONAL,
  355. IN ULONG InputBufferLength,
  356. OUT PVOID OutputBuffer OPTIONAL,
  357. IN ULONG OutputBufferLength,
  358. IN ULONG IoControlCode,
  359. OUT PIO_STATUS_BLOCK IoStatus,
  360. IN struct _DEVICE_OBJECT *DeviceObject
  361. );
  362. BOOLEAN
  363. AfdFastIoDeviceControl (
  364. IN struct _FILE_OBJECT *FileObject,
  365. IN BOOLEAN Wait,
  366. IN PVOID InputBuffer OPTIONAL,
  367. IN ULONG InputBufferLength,
  368. OUT PVOID OutputBuffer OPTIONAL,
  369. IN ULONG OutputBufferLength,
  370. IN ULONG IoControlCode,
  371. OUT PIO_STATUS_BLOCK IoStatus,
  372. IN struct _DEVICE_OBJECT *DeviceObject
  373. )
  374. {
  375. BOOLEAN success;
  376. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  377. success = AfdFastIoDeviceControlReal (
  378. FileObject,
  379. Wait,
  380. InputBuffer,
  381. InputBufferLength,
  382. OutputBuffer,
  383. OutputBufferLength,
  384. IoControlCode,
  385. IoStatus,
  386. DeviceObject
  387. );
  388. ASSERT( KeGetCurrentIrql( ) == LOW_LEVEL );
  389. switch ( IoControlCode ) {
  390. case IOCTL_AFD_SEND:
  391. if ( success ) {
  392. InterlockedIncrement (&AfdFastSendsSucceeded);
  393. } else {
  394. InterlockedIncrement (&AfdFastSendsFailed);
  395. }
  396. break;
  397. case IOCTL_AFD_RECEIVE:
  398. if ( success ) {
  399. InterlockedIncrement (&AfdFastReceivesSucceeded);
  400. } else {
  401. InterlockedIncrement (&AfdFastReceivesFailed);
  402. }
  403. break;
  404. case IOCTL_AFD_SEND_DATAGRAM:
  405. if ( success ) {
  406. InterlockedIncrement (&AfdFastSendDatagramsSucceeded);
  407. } else {
  408. InterlockedIncrement (&AfdFastSendDatagramsFailed);
  409. }
  410. break;
  411. case IOCTL_AFD_RECEIVE_MESSAGE:
  412. case IOCTL_AFD_RECEIVE_DATAGRAM:
  413. if ( success ) {
  414. InterlockedIncrement (&AfdFastReceiveDatagramsSucceeded);
  415. } else {
  416. InterlockedIncrement (&AfdFastReceiveDatagramsFailed);
  417. }
  418. break;
  419. case IOCTL_AFD_TRANSMIT_FILE:
  420. if ( success ) {
  421. InterlockedIncrement (&AfdFastTfSucceeded);
  422. } else {
  423. InterlockedIncrement (&AfdFastTfFailed);
  424. }
  425. break;
  426. }
  427. return success;
  428. } // AfdFastIoDeviceControl
  429. BOOLEAN
  430. AfdFastIoDeviceControlReal (
  431. IN struct _FILE_OBJECT *FileObject,
  432. IN BOOLEAN Wait,
  433. IN PVOID InputBuffer OPTIONAL,
  434. IN ULONG InputBufferLength,
  435. OUT PVOID OutputBuffer OPTIONAL,
  436. IN ULONG OutputBufferLength,
  437. IN ULONG IoControlCode,
  438. OUT PIO_STATUS_BLOCK IoStatus,
  439. IN struct _DEVICE_OBJECT *DeviceObject
  440. )
  441. #else
  442. BOOLEAN
  443. AfdFastIoDeviceControl (
  444. IN struct _FILE_OBJECT *FileObject,
  445. IN BOOLEAN Wait,
  446. IN PVOID InputBuffer OPTIONAL,
  447. IN ULONG InputBufferLength,
  448. OUT PVOID OutputBuffer OPTIONAL,
  449. IN ULONG OutputBufferLength,
  450. IN ULONG IoControlCode,
  451. OUT PIO_STATUS_BLOCK IoStatus,
  452. IN struct _DEVICE_OBJECT *DeviceObject
  453. )
  454. #endif
  455. {
  456. PAFD_ENDPOINT endpoint;
  457. KPROCESSOR_MODE previousMode;
  458. BOOLEAN res;
  459. PAFD_IMMEDIATE_CALL proc;
  460. ULONG request;
  461. #ifdef _WIN64
  462. WSABUF localArray[8];
  463. LPWSABUF pArray = localArray;
  464. #endif
  465. PAGED_CODE( );
  466. //
  467. // All we want to do is pass the request through to the TDI provider
  468. // if possible. If not, we want to bail out of this code path back
  469. // onto the main code path (with IRPs) with as little performance
  470. // overhead as possible.
  471. //
  472. // Thus this routine only does general preliminary checks and input
  473. // parameter validation. If it is determined that fast io path is
  474. // likely to succeed, an operation specific routine is called
  475. // to handle all the details.
  476. //
  477. //
  478. // First get the endpoint pointer and previous mode for input parameter
  479. // validation.
  480. //
  481. endpoint = FileObject->FsContext;
  482. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  483. previousMode = ExGetPreviousMode ();
  484. //
  485. // Switch based on control code
  486. //
  487. switch (IoControlCode) {
  488. case IOCTL_AFD_RECEIVE:
  489. {
  490. union {
  491. AFD_RECV_INFO recvInfo;
  492. AFD_RECV_MESSAGE_INFO msgInfo;
  493. } u;
  494. ULONG recvLength;
  495. #if !defined (_ALPHA_)
  496. //
  497. // Alpha compiler does not see that the following FIELD_OFFSET
  498. // is in fact a constant expression.
  499. //
  500. //
  501. // Check the validity of the union above.
  502. //
  503. C_ASSERT (FIELD_OFFSET (AFD_RECV_MESSAGE_INFO, dgi.BufferArray)
  504. == FIELD_OFFSET (AFD_RECV_INFO, BufferArray));
  505. C_ASSERT (FIELD_OFFSET (AFD_RECV_MESSAGE_INFO, dgi.BufferCount)
  506. == FIELD_OFFSET (AFD_RECV_INFO, BufferCount));
  507. C_ASSERT (FIELD_OFFSET (AFD_RECV_MESSAGE_INFO, dgi.AfdFlags)
  508. == FIELD_OFFSET (AFD_RECV_INFO, AfdFlags));
  509. C_ASSERT (FIELD_OFFSET (AFD_RECV_MESSAGE_INFO, dgi.TdiFlags)
  510. == FIELD_OFFSET (AFD_RECV_INFO, TdiFlags));
  511. //
  512. #endif //!defined (_ALPHA_)
  513. //
  514. // If fast IO send is disabled
  515. // or the endpoint is shut down in any way
  516. // or the endpoint isn't connected yet
  517. // or the TDI provider for this endpoint supports bufferring,
  518. // we do not want to do fast IO on it
  519. //
  520. if (endpoint->DisableFastIoRecv ||
  521. endpoint->DisconnectMode != 0 ||
  522. endpoint->State != AfdEndpointStateConnected ||
  523. IS_TDI_BUFFERRING(endpoint) ) {
  524. res = FALSE;
  525. break;
  526. }
  527. try {
  528. #ifdef _WIN64
  529. if (IoIs32bitProcess (NULL)) {
  530. PAFD_RECV_INFO32 recvInfo32;
  531. LPWSABUF32 tempArray;
  532. ULONG i;
  533. //
  534. // If the input structure isn't large enough, return error.
  535. //
  536. if( InputBufferLength < sizeof(*recvInfo32) ) {
  537. // Fast io can't handle error returns
  538. // if call is overlapped (completion port)
  539. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  540. res = FALSE;
  541. break;
  542. }
  543. //
  544. // Validate the input structure if it comes from the user mode
  545. // application
  546. //
  547. if (previousMode != KernelMode ) {
  548. ProbeForRead (InputBuffer,
  549. sizeof (*recvInfo32),
  550. PROBE_ALIGNMENT32(AFD_RECV_INFO32));
  551. }
  552. recvInfo32 = InputBuffer;
  553. //
  554. // Make local copies of the embeded pointer and parameters
  555. // that we will be using more than once in case malicios
  556. // application attempts to change them while we are
  557. // validating
  558. //
  559. tempArray = recvInfo32->BufferArray;
  560. u.recvInfo.BufferCount = recvInfo32->BufferCount;
  561. u.recvInfo.AfdFlags = recvInfo32->AfdFlags;
  562. u.recvInfo.TdiFlags = recvInfo32->TdiFlags;
  563. //
  564. // If fast IO is not possible or this is not a normal receive.
  565. // bail.
  566. //
  567. if( (u.recvInfo.AfdFlags & AFD_NO_FAST_IO) ||
  568. u.recvInfo.TdiFlags != TDI_RECEIVE_NORMAL ) {
  569. res = FALSE;
  570. break;
  571. }
  572. //
  573. // Validate all the pointers that app gave to us and
  574. // calculate the length of the send buffer.
  575. // Buffers in the array will be validated in the
  576. // process of copying
  577. //
  578. if ((tempArray == NULL) ||
  579. (u.recvInfo.BufferCount == 0) ||
  580. // Check for integer overflow (disabled by compiler)
  581. (u.recvInfo.BufferCount>(MAXULONG/sizeof (WSABUF32))) ) {
  582. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  583. }
  584. if (previousMode != KernelMode) {
  585. ProbeForRead(
  586. tempArray, // Address
  587. // Note check for overflow above (should actually be
  588. // done here by the compiler generating code
  589. // that causes exception on integer overflow)
  590. u.recvInfo.BufferCount * sizeof (WSABUF32), // Length
  591. PROBE_ALIGNMENT32(WSABUF32) // Alignment
  592. );
  593. }
  594. if (u.recvInfo.BufferCount>sizeof(localArray)/sizeof(localArray[0])) {
  595. try {
  596. pArray = AFD_ALLOCATE_POOL_WITH_QUOTA (
  597. NonPagedPool,
  598. sizeof (WSABUF)*u.recvInfo.BufferCount,
  599. AFD_TEMPORARY_POOL_TAG);
  600. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets
  601. // POOL_RAISE_IF_ALLOCATION_FAILURE flag
  602. ASSERT (pArray!=NULL);
  603. }
  604. except (EXCEPTION_EXECUTE_HANDLER) {
  605. // Fast io can't handle error returns
  606. // if call is overlapped (completion port)
  607. // IoStatus->Status = GetExceptionCode ();
  608. pArray = localArray;
  609. res = FALSE;
  610. break;
  611. }
  612. }
  613. for (i=0; i<u.recvInfo.BufferCount; i++) {
  614. pArray[i].buf = tempArray[i].buf;
  615. pArray[i].len = tempArray[i].len;
  616. }
  617. u.recvInfo.BufferArray = pArray;
  618. }
  619. else
  620. #endif // _WIN64
  621. {
  622. //
  623. // If the input structure isn't large enough, return error.
  624. //
  625. if( InputBufferLength < sizeof(u.recvInfo) ) {
  626. // Fast io can't handle error returns
  627. // if call is overlapped (completion port)
  628. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  629. res = FALSE;
  630. break;
  631. }
  632. //
  633. // Validate the input structure if it comes from the user mode
  634. // application
  635. //
  636. if (previousMode != KernelMode ) {
  637. ProbeForRead (InputBuffer,
  638. sizeof (u.recvInfo),
  639. PROBE_ALIGNMENT(AFD_RECV_INFO));
  640. }
  641. //
  642. // Make local copies of the embeded pointer and parameters
  643. // that we will be using more than once in case malicios
  644. // application attempts to change them while we are
  645. // validating
  646. //
  647. u.recvInfo = *((PAFD_RECV_INFO)InputBuffer);
  648. //
  649. // If fast IO is not possible or this is not a normal receive.
  650. // bail.
  651. //
  652. if( (u.recvInfo.AfdFlags & AFD_NO_FAST_IO) ||
  653. u.recvInfo.TdiFlags != TDI_RECEIVE_NORMAL ) {
  654. res = FALSE;
  655. break;
  656. }
  657. //
  658. // Validate all the pointers that app gave to us and
  659. // calculate the length of the send buffer.
  660. // Buffers in the array will be validated in the
  661. // process of copying
  662. //
  663. if ((u.recvInfo.BufferArray == NULL) ||
  664. (u.recvInfo.BufferCount == 0) ||
  665. // Check for integer overflow (disabled by compiler)
  666. (u.recvInfo.BufferCount>(MAXULONG/sizeof (WSABUF))) ) {
  667. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  668. }
  669. if (previousMode != KernelMode) {
  670. ProbeForRead(
  671. u.recvInfo.BufferArray, // Address
  672. // Note check for overflow above (should actually be
  673. // done here by the compiler generating code
  674. // that causes exception on integer overflow)
  675. u.recvInfo.BufferCount * sizeof (WSABUF), // Length
  676. PROBE_ALIGNMENT(WSABUF) // Alignment
  677. );
  678. }
  679. }
  680. recvLength = AfdCalcBufferArrayByteLength(
  681. u.recvInfo.BufferArray,
  682. u.recvInfo.BufferCount
  683. );
  684. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  685. // Fast io can't handle error returns
  686. // if call is overlapped (completion port)
  687. // IoStatus->Status = GetExceptionCode ();
  688. res = FALSE;
  689. break;
  690. }
  691. //
  692. // Call routine based on endpoint type
  693. //
  694. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  695. u.msgInfo.dgi.Address = NULL;
  696. u.msgInfo.dgi.AddressLength = 0;
  697. u.msgInfo.ControlBuffer = NULL;
  698. u.msgInfo.ControlLength = NULL;
  699. u.msgInfo.MsgFlags = NULL;
  700. res = AfdFastDatagramReceive(
  701. endpoint,
  702. &u.msgInfo,
  703. recvLength,
  704. IoStatus
  705. );
  706. }
  707. else if (IS_VC_ENDPOINT (endpoint)) {
  708. res = AfdFastConnectionReceive (
  709. endpoint,
  710. &u.recvInfo,
  711. recvLength,
  712. IoStatus);
  713. }
  714. else
  715. res = FALSE;
  716. }
  717. break;
  718. case IOCTL_AFD_RECEIVE_DATAGRAM:
  719. case IOCTL_AFD_RECEIVE_MESSAGE:
  720. {
  721. AFD_RECV_MESSAGE_INFO msgInfo;
  722. ULONG recvLength;
  723. if (endpoint->DisableFastIoRecv ||
  724. !IS_DGRAM_ENDPOINT(endpoint) ||
  725. ((endpoint->State != AfdEndpointStateBound ) &&
  726. (endpoint->State != AfdEndpointStateConnected)) ) {
  727. return FALSE;
  728. }
  729. if (IoControlCode==IOCTL_AFD_RECEIVE_MESSAGE) {
  730. #ifdef _WIN64
  731. if (IoIs32bitProcess (NULL)) {
  732. PAFD_RECV_MESSAGE_INFO32 msgInfo32;
  733. //
  734. // If the input structure isn't large enough, return error.
  735. //
  736. if( InputBufferLength < sizeof(*msgInfo32) ) {
  737. // Fast io can't handle error returns
  738. // if call is overlapped (completion port)
  739. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  740. res = FALSE;
  741. break;
  742. }
  743. //
  744. // Validate the input structure if it comes from the user mode
  745. // application
  746. //
  747. if (previousMode != KernelMode ) {
  748. ProbeForRead (InputBuffer,
  749. sizeof (*msgInfo32),
  750. PROBE_ALIGNMENT32 (AFD_RECV_MESSAGE_INFO32));
  751. }
  752. msgInfo32 = InputBuffer;
  753. //
  754. // Make local copies of the embeded pointer and parameters
  755. // that we will be using more than once in case malicios
  756. // application attempts to change them while we are
  757. // validating
  758. //
  759. msgInfo.ControlBuffer = msgInfo32->ControlBuffer;
  760. msgInfo.ControlLength = msgInfo32->ControlLength;
  761. msgInfo.MsgFlags = msgInfo32->MsgFlags;
  762. }
  763. else
  764. #endif // _WIN64
  765. {
  766. if( InputBufferLength < sizeof(msgInfo) ) {
  767. // Fast io can't handle error returns
  768. // if call is overlapped (completion port)
  769. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  770. res = FALSE;
  771. break;
  772. }
  773. //
  774. // Capture the input structure.
  775. //
  776. //
  777. // Validate the input structure if it comes from the user mode
  778. // application
  779. //
  780. if (previousMode != KernelMode ) {
  781. ProbeForRead (InputBuffer,
  782. sizeof (msgInfo),
  783. PROBE_ALIGNMENT (AFD_RECV_MESSAGE_INFO));
  784. }
  785. msgInfo = *(PAFD_RECV_MESSAGE_INFO)InputBuffer;
  786. }
  787. if (previousMode != KernelMode ) {
  788. ProbeForWrite (msgInfo.MsgFlags,
  789. sizeof (*msgInfo.MsgFlags),
  790. PROBE_ALIGNMENT (ULONG));
  791. ProbeForWrite (msgInfo.ControlLength,
  792. sizeof (*msgInfo.ControlLength),
  793. PROBE_ALIGNMENT (ULONG));
  794. //
  795. // Checking of recvInfo->Address is postponed till
  796. // we know the length of the address.
  797. //
  798. }
  799. }
  800. else
  801. {
  802. msgInfo.ControlBuffer = NULL;
  803. msgInfo.ControlLength = NULL;
  804. msgInfo.MsgFlags = NULL;
  805. }
  806. //
  807. // If the input structure isn't large enough, return error.
  808. //
  809. try {
  810. #ifdef _WIN64
  811. if (IoIs32bitProcess (NULL)) {
  812. PAFD_RECV_DATAGRAM_INFO32 recvInfo32;
  813. LPWSABUF32 tempArray;
  814. ULONG i;
  815. //
  816. // If the input structure isn't large enough, return error.
  817. //
  818. if( InputBufferLength < sizeof(*recvInfo32) ) {
  819. // Fast io can't handle error returns
  820. // if call is overlapped (completion port)
  821. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  822. res = FALSE;
  823. break;
  824. }
  825. //
  826. // Validate the input structure if it comes from the user mode
  827. // application
  828. //
  829. if (previousMode != KernelMode ) {
  830. ProbeForRead (InputBuffer,
  831. sizeof (*recvInfo32),
  832. PROBE_ALIGNMENT32 (AFD_RECV_DATAGRAM_INFO32));
  833. }
  834. recvInfo32 = InputBuffer;
  835. //
  836. // Make local copies of the embeded pointer and parameters
  837. // that we will be using more than once in case malicios
  838. // application attempts to change them while we are
  839. // validating
  840. //
  841. tempArray = recvInfo32->BufferArray;
  842. msgInfo.dgi.BufferCount = recvInfo32->BufferCount;
  843. msgInfo.dgi.AfdFlags = recvInfo32->AfdFlags;
  844. msgInfo.dgi.TdiFlags = recvInfo32->TdiFlags;
  845. msgInfo.dgi.Address = recvInfo32->Address;
  846. msgInfo.dgi.AddressLength = recvInfo32->AddressLength;
  847. //
  848. // If fast IO is not possible or this is not a normal receive.
  849. // bail.
  850. //
  851. if( (msgInfo.dgi.AfdFlags & AFD_NO_FAST_IO) ||
  852. msgInfo.dgi.TdiFlags != TDI_RECEIVE_NORMAL ) {
  853. res = FALSE;
  854. break;
  855. }
  856. //
  857. // Validate all the pointers that app gave to us and
  858. // calculate the length of the send buffer.
  859. // Buffers in the array will be validated in the
  860. // process of copying
  861. //
  862. if ((tempArray == NULL) ||
  863. (msgInfo.dgi.BufferCount == 0) ||
  864. // Check for integer overflow (disabled by compiler)
  865. (msgInfo.dgi.BufferCount>(MAXULONG/sizeof (WSABUF32))) ) {
  866. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  867. }
  868. if (previousMode != KernelMode) {
  869. ProbeForRead(
  870. tempArray, // Address
  871. // Note check for overflow above (should actually be
  872. // done here by the compiler generating code
  873. // that causes exception on integer overflow)
  874. msgInfo.dgi.BufferCount * sizeof (WSABUF32), // Length
  875. PROBE_ALIGNMENT (WSABUF32) // Alignment
  876. );
  877. }
  878. if (msgInfo.dgi.BufferCount>sizeof(localArray)/sizeof(localArray[0])) {
  879. try {
  880. pArray = AFD_ALLOCATE_POOL_WITH_QUOTA (
  881. NonPagedPool,
  882. sizeof (WSABUF)*msgInfo.dgi.BufferCount,
  883. AFD_TEMPORARY_POOL_TAG);
  884. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets
  885. // POOL_RAISE_IF_ALLOCATION_FAILURE flag
  886. ASSERT (pArray!=NULL);
  887. }
  888. except (EXCEPTION_EXECUTE_HANDLER) {
  889. // Fast io can't handle error returns
  890. // if call is overlapped (completion port)
  891. // IoStatus->Status = GetExceptionCode ();
  892. pArray = localArray;
  893. res = FALSE;
  894. break;
  895. }
  896. }
  897. for (i=0; i<msgInfo.dgi.BufferCount; i++) {
  898. pArray[i].buf = tempArray[i].buf;
  899. pArray[i].len = tempArray[i].len;
  900. }
  901. msgInfo.dgi.BufferArray = pArray;
  902. }
  903. else
  904. #endif // _WIN64
  905. {
  906. if( InputBufferLength < sizeof(AFD_RECV_DATAGRAM_INFO) ) {
  907. // Fast io can't handle error returns
  908. // if call is overlapped (completion port)
  909. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  910. res = FALSE;
  911. break;
  912. }
  913. //
  914. // Capture the input structure.
  915. //
  916. //
  917. // Validate the input structure if it comes from the user mode
  918. // application
  919. //
  920. if (previousMode != KernelMode ) {
  921. ProbeForRead (InputBuffer,
  922. sizeof (AFD_RECV_DATAGRAM_INFO),
  923. PROBE_ALIGNMENT (AFD_RECV_DATAGRAM_INFO));
  924. }
  925. //
  926. // Make local copies of the embeded pointer and parameters
  927. // that we will be using more than once in case malicios
  928. // application attempts to change them while we are
  929. // validating
  930. //
  931. msgInfo.dgi = *(PAFD_RECV_DATAGRAM_INFO)InputBuffer;
  932. //
  933. // If fast IO is disabled or this is not a simple
  934. // recv, fail
  935. //
  936. if( (msgInfo.dgi.AfdFlags & AFD_NO_FAST_IO) != 0 ||
  937. msgInfo.dgi.TdiFlags != TDI_RECEIVE_NORMAL ||
  938. ( (msgInfo.dgi.Address == NULL) ^
  939. (msgInfo.dgi.AddressLength == NULL) ) ) {
  940. res = FALSE;
  941. break;
  942. }
  943. //
  944. // Validate all the pointers that app gave to us.
  945. // and calculate total recv length.
  946. // Buffers in the array will be validated in the
  947. // process of copying
  948. //
  949. if ((msgInfo.dgi.BufferArray == NULL) ||
  950. (msgInfo.dgi.BufferCount == 0) ||
  951. // Check for integer overflow (disabled by compiler)
  952. (msgInfo.dgi.BufferCount>(MAXULONG/sizeof (WSABUF))) ) {
  953. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  954. }
  955. if (previousMode != KernelMode) {
  956. ProbeForRead(
  957. msgInfo.dgi.BufferArray, // Address
  958. // Note check for overflow above (should actually be
  959. // done here by the compiler generating code
  960. // that causes exception on integer overflow)
  961. msgInfo.dgi.BufferCount * sizeof (WSABUF), // Length
  962. PROBE_ALIGNMENT(WSABUF) // Alignment
  963. );
  964. }
  965. }
  966. recvLength = AfdCalcBufferArrayByteLength(
  967. msgInfo.dgi.BufferArray,
  968. msgInfo.dgi.BufferCount
  969. );
  970. if (previousMode != KernelMode ) {
  971. if (msgInfo.dgi.AddressLength!=NULL) {
  972. ProbeForWrite (msgInfo.dgi.AddressLength,
  973. sizeof (*msgInfo.dgi.AddressLength),
  974. PROBE_ALIGNMENT (ULONG));
  975. }
  976. //
  977. // Checking of recvInfo->Address is postponed till
  978. // we know the length of the address.
  979. //
  980. }
  981. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  982. // Fast io can't handle error returns
  983. // if call is overlapped (completion port)
  984. // IoStatus->Status = GetExceptionCode ();
  985. res = FALSE;
  986. break;
  987. }
  988. //
  989. // Attempt to perform fast IO on the endpoint.
  990. //
  991. res = AfdFastDatagramReceive(
  992. endpoint,
  993. &msgInfo,
  994. recvLength,
  995. IoStatus
  996. );
  997. }
  998. break;
  999. case IOCTL_AFD_SEND:
  1000. {
  1001. union {
  1002. AFD_SEND_INFO sendInfo;
  1003. AFD_SEND_DATAGRAM_INFO sendInfoDg;
  1004. } u;
  1005. ULONG sendLength;
  1006. //
  1007. // Check the validity of the union above.
  1008. //
  1009. C_ASSERT (FIELD_OFFSET (AFD_SEND_DATAGRAM_INFO, BufferArray)
  1010. == FIELD_OFFSET (AFD_SEND_INFO, BufferArray));
  1011. C_ASSERT (FIELD_OFFSET (AFD_SEND_DATAGRAM_INFO, BufferCount)
  1012. == FIELD_OFFSET (AFD_SEND_INFO, BufferCount));
  1013. C_ASSERT (FIELD_OFFSET (AFD_SEND_DATAGRAM_INFO, AfdFlags)
  1014. == FIELD_OFFSET (AFD_SEND_INFO, AfdFlags));
  1015. //
  1016. // If fast IO send is disabled
  1017. // or the endpoint is shut down in any way
  1018. // or the endpoint isn't connected yet
  1019. // or the TDI provider for this endpoint supports bufferring,
  1020. // we do not want to do fast IO on it
  1021. //
  1022. if (endpoint->DisableFastIoSend ||
  1023. endpoint->DisconnectMode != 0 ||
  1024. endpoint->State != AfdEndpointStateConnected ||
  1025. IS_TDI_BUFFERRING(endpoint) ) {
  1026. return FALSE;
  1027. }
  1028. try {
  1029. #ifdef _WIN64
  1030. if (IoIs32bitProcess (NULL)) {
  1031. PAFD_SEND_INFO32 sendInfo32;
  1032. LPWSABUF32 tempArray;
  1033. ULONG i;
  1034. //
  1035. // If the input structure isn't large enough, return error.
  1036. //
  1037. if( InputBufferLength < sizeof(*sendInfo32) ) {
  1038. // Fast io can't handle error returns
  1039. // if call is overlapped (completion port)
  1040. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  1041. res = FALSE;
  1042. break;
  1043. }
  1044. //
  1045. // Validate the input structure if it comes from the user mode
  1046. // application
  1047. //
  1048. if (previousMode != KernelMode ) {
  1049. ProbeForRead (InputBuffer,
  1050. sizeof (*sendInfo32),
  1051. PROBE_ALIGNMENT32 (AFD_SEND_INFO32));
  1052. }
  1053. sendInfo32 = InputBuffer;
  1054. //
  1055. // Make local copies of the embeded pointer and parameters
  1056. // that we will be using more than once in case malicios
  1057. // application attempts to change them while we are
  1058. // validating
  1059. //
  1060. tempArray = sendInfo32->BufferArray;
  1061. u.sendInfo.BufferCount = sendInfo32->BufferCount;
  1062. u.sendInfo.AfdFlags = sendInfo32->AfdFlags;
  1063. u.sendInfo.TdiFlags = sendInfo32->TdiFlags;
  1064. //
  1065. // If fast IO is not possible or this is not a normal receive.
  1066. // bail.
  1067. //
  1068. if( (u.sendInfo.AfdFlags & AFD_NO_FAST_IO) ||
  1069. u.sendInfo.TdiFlags != 0 ) {
  1070. res = FALSE;
  1071. break;
  1072. }
  1073. //
  1074. // Validate all the pointers that app gave to us and
  1075. // calculate the length of the send buffer.
  1076. // Buffers in the array will be validated in the
  1077. // process of copying
  1078. //
  1079. if ((tempArray == NULL) ||
  1080. (u.sendInfo.BufferCount == 0) ||
  1081. // Check for integer overflow (disabled by compiler)
  1082. (u.sendInfo.BufferCount>(MAXULONG/sizeof (WSABUF32))) ) {
  1083. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  1084. }
  1085. if (previousMode != KernelMode) {
  1086. ProbeForRead(
  1087. tempArray, // Address
  1088. // Note check for overflow above (should actually be
  1089. // done here by the compiler generating code
  1090. // that causes exception on integer overflow)
  1091. u.sendInfo.BufferCount * sizeof (WSABUF32), // Length
  1092. PROBE_ALIGNMENT32(WSABUF32) // Alignment
  1093. );
  1094. }
  1095. if (u.sendInfo.BufferCount>sizeof(localArray)/sizeof(localArray[0])) {
  1096. try {
  1097. pArray = AFD_ALLOCATE_POOL_WITH_QUOTA (
  1098. NonPagedPool,
  1099. sizeof (WSABUF)*u.sendInfo.BufferCount,
  1100. AFD_TEMPORARY_POOL_TAG);
  1101. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets
  1102. // POOL_RAISE_IF_ALLOCATION_FAILURE flag
  1103. ASSERT (pArray!=NULL);
  1104. }
  1105. except (EXCEPTION_EXECUTE_HANDLER) {
  1106. // Fast io can't handle error returns
  1107. // if call is overlapped (completion port)
  1108. // IoStatus->Status = GetExceptionCode ();
  1109. pArray = localArray;
  1110. res = FALSE;
  1111. break;
  1112. }
  1113. }
  1114. for (i=0; i<u.sendInfo.BufferCount; i++) {
  1115. pArray[i].buf = tempArray[i].buf;
  1116. pArray[i].len = tempArray[i].len;
  1117. }
  1118. u.sendInfo.BufferArray = pArray;
  1119. }
  1120. else
  1121. #endif // _WIN64
  1122. {
  1123. //
  1124. // If the input structure isn't large enough, return error.
  1125. //
  1126. if( InputBufferLength < sizeof(u.sendInfo) ) {
  1127. // Fast io can't handle error returns
  1128. // if call is overlapped (completion port)
  1129. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  1130. res = FALSE;
  1131. break;
  1132. }
  1133. //
  1134. // Validate the input structure if it comes from the user mode
  1135. // application
  1136. //
  1137. if (previousMode != KernelMode) {
  1138. ProbeForRead (InputBuffer,
  1139. sizeof (u.sendInfo),
  1140. PROBE_ALIGNMENT(AFD_SEND_INFO));
  1141. }
  1142. //
  1143. // Make local copies of the embeded pointer and parameters
  1144. // that we will be using more than once in case malicios
  1145. // application attempts to change them while we are
  1146. // validating
  1147. //
  1148. u.sendInfo = *((PAFD_SEND_INFO)InputBuffer);
  1149. if( (u.sendInfo.AfdFlags & AFD_NO_FAST_IO) != 0 ||
  1150. u.sendInfo.TdiFlags != 0 ) {
  1151. res = FALSE;
  1152. break;
  1153. }
  1154. if ((u.sendInfo.BufferArray == NULL) ||
  1155. (u.sendInfo.BufferCount == 0) ||
  1156. // Check for integer overflow (disabled by compiler)
  1157. (u.sendInfo.BufferCount>(MAXULONG/sizeof (WSABUF))) ) {
  1158. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  1159. }
  1160. if (previousMode != KernelMode) {
  1161. ProbeForRead(
  1162. u.sendInfo.BufferArray, // Address
  1163. // Note check for overflow above (should actually be
  1164. // done here by the compiler generating code
  1165. // that causes exception on integer overflow)
  1166. u.sendInfo.BufferCount * sizeof (WSABUF), // Length
  1167. PROBE_ALIGNMENT(WSABUF) // Alignment
  1168. );
  1169. }
  1170. }
  1171. sendLength = AfdCalcBufferArrayByteLength(
  1172. u.sendInfo.BufferArray,
  1173. u.sendInfo.BufferCount
  1174. );
  1175. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  1176. // Fast io can't handle error returns
  1177. // if call is overlapped (completion port)
  1178. // IoStatus->Status = GetExceptionCode ();
  1179. res = FALSE;
  1180. break;
  1181. }
  1182. if (IS_DGRAM_ENDPOINT (endpoint)) {
  1183. u.sendInfoDg.TdiConnInfo.RemoteAddress = NULL;
  1184. u.sendInfoDg.TdiConnInfo.RemoteAddressLength = 0;
  1185. res = AfdFastDatagramSend (
  1186. endpoint,
  1187. &u.sendInfoDg,
  1188. sendLength,
  1189. IoStatus);
  1190. }
  1191. else if (IS_VC_ENDPOINT (endpoint)) {
  1192. res = AfdFastConnectionSend (
  1193. endpoint,
  1194. &u.sendInfo,
  1195. sendLength,
  1196. IoStatus);
  1197. }
  1198. else
  1199. res = FALSE;
  1200. }
  1201. break;
  1202. case IOCTL_AFD_SEND_DATAGRAM:
  1203. {
  1204. AFD_SEND_DATAGRAM_INFO sendInfo;
  1205. ULONG sendLength;
  1206. if (endpoint->DisableFastIoSend ||
  1207. !IS_DGRAM_ENDPOINT(endpoint) ||
  1208. ((endpoint->State != AfdEndpointStateBound ) &&
  1209. (endpoint->State != AfdEndpointStateConnected)) ) {
  1210. res = FALSE;
  1211. break;
  1212. }
  1213. try {
  1214. #ifdef _WIN64
  1215. if (IoIs32bitProcess (NULL)) {
  1216. PAFD_SEND_DATAGRAM_INFO32 sendInfo32;
  1217. LPWSABUF32 tempArray;
  1218. ULONG i;
  1219. //
  1220. // If the input structure isn't large enough, return error.
  1221. //
  1222. if( InputBufferLength < sizeof(*sendInfo32) ) {
  1223. // Fast io can't handle error returns
  1224. // if call is overlapped (completion port)
  1225. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  1226. res = FALSE;
  1227. break;
  1228. }
  1229. //
  1230. // Validate the input structure if it comes from the user mode
  1231. // application
  1232. //
  1233. if (previousMode != KernelMode ) {
  1234. ProbeForRead (InputBuffer,
  1235. sizeof (*sendInfo32),
  1236. PROBE_ALIGNMENT32(AFD_SEND_DATAGRAM_INFO32));
  1237. }
  1238. sendInfo32 = InputBuffer;
  1239. //
  1240. // Make local copies of the embeded pointer and parameters
  1241. // that we will be using more than once in case malicios
  1242. // application attempts to change them while we are
  1243. // validating
  1244. //
  1245. tempArray = sendInfo32->BufferArray;
  1246. sendInfo.BufferCount = sendInfo32->BufferCount;
  1247. sendInfo.AfdFlags = sendInfo32->AfdFlags;
  1248. sendInfo.TdiConnInfo.RemoteAddress = sendInfo32->TdiConnInfo.RemoteAddress;
  1249. sendInfo.TdiConnInfo.RemoteAddressLength = sendInfo32->TdiConnInfo.RemoteAddressLength;
  1250. //
  1251. // If fast IO is not possible bail.
  1252. //
  1253. if(sendInfo.AfdFlags & AFD_NO_FAST_IO) {
  1254. res = FALSE;
  1255. break;
  1256. }
  1257. //
  1258. // Validate all the pointers that app gave to us and
  1259. // calculate the length of the send buffer.
  1260. // Buffers in the array will be validated in the
  1261. // process of copying
  1262. //
  1263. if ((tempArray == NULL) ||
  1264. (sendInfo.BufferCount == 0) ||
  1265. // Check for integer overflow (disabled by compiler)
  1266. (sendInfo.BufferCount>(MAXULONG/sizeof (WSABUF32))) ) {
  1267. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  1268. }
  1269. if (previousMode != KernelMode) {
  1270. ProbeForRead(
  1271. tempArray, // Address
  1272. // Note check for overflow above (should actually be
  1273. // done here by the compiler generating code
  1274. // that causes exception on integer overflow)
  1275. sendInfo.BufferCount * sizeof (WSABUF32), // Length
  1276. PROBE_ALIGNMENT32(WSABUF32) // Alignment
  1277. );
  1278. }
  1279. if (sendInfo.BufferCount>sizeof(localArray)/sizeof(localArray[0])) {
  1280. try {
  1281. pArray = AFD_ALLOCATE_POOL_WITH_QUOTA (
  1282. NonPagedPool,
  1283. sizeof (WSABUF)*sendInfo.BufferCount,
  1284. AFD_TEMPORARY_POOL_TAG);
  1285. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets
  1286. // POOL_RAISE_IF_ALLOCATION_FAILURE flag
  1287. ASSERT (pArray!=NULL);
  1288. }
  1289. except (EXCEPTION_EXECUTE_HANDLER) {
  1290. // Fast io can't handle error returns
  1291. // if call is overlapped (completion port)
  1292. // IoStatus->Status = GetExceptionCode ();
  1293. pArray = localArray;
  1294. res = FALSE;
  1295. break;
  1296. }
  1297. }
  1298. for (i=0; i<sendInfo.BufferCount; i++) {
  1299. pArray[i].buf = tempArray[i].buf;
  1300. pArray[i].len = tempArray[i].len;
  1301. }
  1302. sendInfo.BufferArray = pArray;
  1303. }
  1304. else
  1305. #endif // _WIN64
  1306. {
  1307. //
  1308. // If the input structure isn't large enough, bail on fast IO.
  1309. //
  1310. if( InputBufferLength < sizeof(sendInfo) ) {
  1311. // Fast io can't handle error returns
  1312. // if call is overlapped (completion port)
  1313. // IoStatus->Status = STATUS_INVALID_PARAMETER;
  1314. res = FALSE;
  1315. break;
  1316. }
  1317. //
  1318. // Validate the input structure if it comes from the user mode
  1319. // application
  1320. //
  1321. if (previousMode != KernelMode) {
  1322. ProbeForRead (InputBuffer,
  1323. sizeof (sendInfo),
  1324. PROBE_ALIGNMENT(AFD_SEND_DATAGRAM_INFO));
  1325. }
  1326. //
  1327. // Make local copies of the embeded pointer and parameters
  1328. // that we will be using more than once in case malicios
  1329. // application attempts to change them while we are
  1330. // validating
  1331. //
  1332. sendInfo = *((PAFD_SEND_DATAGRAM_INFO)InputBuffer);
  1333. //
  1334. // If fast IO is disabled, bail
  1335. //
  1336. if( (sendInfo.AfdFlags & AFD_NO_FAST_IO) != 0) {
  1337. res = FALSE;
  1338. break;
  1339. }
  1340. //
  1341. // Validate all the pointers that app gave to us
  1342. // and calculate total send length
  1343. // Buffers in the array will be validated in the
  1344. // process of copying
  1345. //
  1346. if ((sendInfo.BufferArray == NULL) ||
  1347. (sendInfo.BufferCount == 0) ||
  1348. // Check for integer overflow (disabled by compiler)
  1349. (sendInfo.BufferCount>(MAXULONG/sizeof (WSABUF))) ) {
  1350. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  1351. }
  1352. if (previousMode != KernelMode) {
  1353. ProbeForRead(
  1354. sendInfo.BufferArray, // Address
  1355. // Note check for overflow above (should actually be
  1356. // done here by the compiler generating code
  1357. // that causes exception on integer overflow)
  1358. sendInfo.BufferCount * sizeof (WSABUF), // Length
  1359. PROBE_ALIGNMENT(WSABUF) // Alignment
  1360. );
  1361. }
  1362. }
  1363. sendLength = AfdCalcBufferArrayByteLength(
  1364. sendInfo.BufferArray,
  1365. sendInfo.BufferCount
  1366. );
  1367. if (previousMode != KernelMode ) {
  1368. ProbeForRead (
  1369. sendInfo.TdiConnInfo.RemoteAddress, // Address
  1370. sendInfo.TdiConnInfo.RemoteAddressLength, // Length,
  1371. sizeof (UCHAR) // Aligment
  1372. );
  1373. }
  1374. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  1375. // Fast io can't handle error returns
  1376. // if call is overlapped (completion port)
  1377. // IoStatus->Status = GetExceptionCode ();
  1378. res = FALSE;
  1379. break;
  1380. }
  1381. //
  1382. // Attempt to perform fast IO on the endpoint.
  1383. //
  1384. res = AfdFastDatagramSend(
  1385. endpoint,
  1386. &sendInfo,
  1387. sendLength,
  1388. IoStatus
  1389. );
  1390. }
  1391. break;
  1392. case IOCTL_AFD_TRANSMIT_FILE:
  1393. {
  1394. AFD_TRANSMIT_FILE_INFO userTransmitInfo;
  1395. try {
  1396. #ifdef _WIN64
  1397. if (IoIs32bitProcess (NULL)) {
  1398. PAFD_TRANSMIT_FILE_INFO32 userTransmitInfo32;
  1399. if ( InputBufferLength < sizeof(AFD_TRANSMIT_FILE_INFO32) ) {
  1400. return FALSE;
  1401. }
  1402. if (previousMode != KernelMode) {
  1403. ProbeForRead (InputBuffer,
  1404. sizeof (*userTransmitInfo32),
  1405. PROBE_ALIGNMENT32(AFD_TRANSMIT_FILE_INFO32));
  1406. userTransmitInfo32 = InputBuffer;
  1407. userTransmitInfo.Offset = userTransmitInfo32->Offset;
  1408. userTransmitInfo.WriteLength = userTransmitInfo32->WriteLength;
  1409. userTransmitInfo.SendPacketLength = userTransmitInfo32->SendPacketLength;
  1410. userTransmitInfo.FileHandle = userTransmitInfo32->FileHandle;
  1411. userTransmitInfo.Head = userTransmitInfo32->Head;
  1412. userTransmitInfo.HeadLength = userTransmitInfo32->HeadLength;
  1413. userTransmitInfo.Tail = userTransmitInfo32->Tail;
  1414. userTransmitInfo.TailLength = userTransmitInfo32->TailLength;
  1415. userTransmitInfo.Flags = userTransmitInfo32->Flags;
  1416. if (userTransmitInfo.HeadLength>0)
  1417. ProbeForRead (userTransmitInfo.Head,
  1418. userTransmitInfo.HeadLength,
  1419. sizeof (UCHAR));
  1420. if (userTransmitInfo.TailLength>0)
  1421. ProbeForRead (userTransmitInfo.Tail,
  1422. userTransmitInfo.TailLength,
  1423. sizeof (UCHAR));
  1424. }
  1425. else
  1426. {
  1427. ASSERT (FALSE);
  1428. }
  1429. }
  1430. else
  1431. #endif // _WIN64
  1432. {
  1433. if ( InputBufferLength < sizeof(AFD_TRANSMIT_FILE_INFO) ) {
  1434. return FALSE;
  1435. }
  1436. if (previousMode != KernelMode) {
  1437. ProbeForRead (InputBuffer,
  1438. sizeof (userTransmitInfo),
  1439. PROBE_ALIGNMENT(AFD_TRANSMIT_FILE_INFO));
  1440. userTransmitInfo = *((PAFD_TRANSMIT_FILE_INFO)InputBuffer);
  1441. if (userTransmitInfo.HeadLength>0)
  1442. ProbeForRead (userTransmitInfo.Head,
  1443. userTransmitInfo.HeadLength,
  1444. sizeof (UCHAR));
  1445. if (userTransmitInfo.TailLength>0)
  1446. ProbeForRead (userTransmitInfo.Tail,
  1447. userTransmitInfo.TailLength,
  1448. sizeof (UCHAR));
  1449. }
  1450. else {
  1451. userTransmitInfo = *((PAFD_TRANSMIT_FILE_INFO)InputBuffer);
  1452. }
  1453. }
  1454. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  1455. res = FALSE;
  1456. break;
  1457. }
  1458. res = AfdFastTransmitFile (endpoint,
  1459. &userTransmitInfo,
  1460. IoStatus);
  1461. }
  1462. return res;
  1463. default:
  1464. request = _AFD_REQUEST(IoControlCode);
  1465. if( request < AFD_NUM_IOCTLS &&
  1466. AfdIoctlTable[request] == IoControlCode &&
  1467. AfdImmediateCallDispatch[request]!=NULL) {
  1468. proc = AfdImmediateCallDispatch[request];
  1469. IoStatus->Status = (*proc) (
  1470. FileObject,
  1471. IoControlCode,
  1472. previousMode,
  1473. InputBuffer,
  1474. InputBufferLength,
  1475. OutputBuffer,
  1476. OutputBufferLength,
  1477. &IoStatus->Information
  1478. );
  1479. ASSERT (IoStatus->Status!=STATUS_PENDING);
  1480. res = TRUE;
  1481. }
  1482. else {
  1483. res = FALSE;
  1484. }
  1485. break;
  1486. }
  1487. #ifdef _WIN64
  1488. if (pArray!=localArray) {
  1489. AFD_FREE_POOL (pArray, AFD_TEMPORARY_POOL_TAG);
  1490. }
  1491. #endif
  1492. return res;
  1493. }
  1494. BOOLEAN
  1495. AfdFastConnectionSend (
  1496. IN PAFD_ENDPOINT endpoint,
  1497. IN PAFD_SEND_INFO sendInfo,
  1498. IN ULONG sendLength,
  1499. OUT PIO_STATUS_BLOCK IoStatus
  1500. )
  1501. {
  1502. PAFD_BUFFER afdBuffer;
  1503. PAFD_CONNECTION connection;
  1504. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1505. NTSTATUS status;
  1506. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1507. endpoint->Type == AfdBlockTypeVcBoth );
  1508. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1509. connection = endpoint->Common.VcConnecting.Connection;
  1510. if (connection==NULL) {
  1511. //
  1512. // connection might have been cleaned up by transmit file.
  1513. //
  1514. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1515. return FALSE;
  1516. }
  1517. ASSERT( connection->Type == AfdBlockTypeConnection );
  1518. //
  1519. // If the connection has been aborted, then we don't want to try
  1520. // fast IO on it.
  1521. //
  1522. if ( connection->CleanupBegun || connection->AbortIndicated ) {
  1523. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1524. return FALSE;
  1525. }
  1526. //
  1527. // Determine whether we can do fast IO with this send. In order
  1528. // to perform fast IO, there must be no other sends pended on this
  1529. // connection and there must be enough space left for bufferring
  1530. // the requested amount of data.
  1531. //
  1532. if ( AfdShouldSendBlock( endpoint, connection, sendLength ) ) {
  1533. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1534. //
  1535. // If this is a nonblocking endpoint, fail the request here and
  1536. // save going through the regular path.
  1537. //
  1538. if ( endpoint->NonBlocking && !( sendInfo->AfdFlags & AFD_OVERLAPPED ) ) {
  1539. // Fast io can't handle error returns
  1540. // if call is overlapped (completion port), but we know
  1541. // that it is not overlapped
  1542. IoStatus->Status = STATUS_DEVICE_NOT_READY;
  1543. return TRUE;
  1544. }
  1545. return FALSE;
  1546. }
  1547. //
  1548. // Add a reference to the connection object since the send
  1549. // request will complete asynchronously.
  1550. //
  1551. REFERENCE_CONNECTION( connection );
  1552. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1553. IF_DEBUG(FAST_IO) {
  1554. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1555. "AfdFastConnectionSend: attempting fast IO on endp %p, conn %p\n",
  1556. endpoint, connection));
  1557. }
  1558. //
  1559. // Next get an AFD buffer structure that contains an IRP and a
  1560. // buffer to hold the data.
  1561. //
  1562. afdBuffer = AfdGetBuffer( sendLength, 0, connection->OwningProcess );
  1563. if ( afdBuffer == NULL) {
  1564. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1565. connection->VcBufferredSendBytes -= sendLength;
  1566. connection->VcBufferredSendCount -= 1;
  1567. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1568. DEREFERENCE_CONNECTION (connection);
  1569. return FALSE;
  1570. }
  1571. //
  1572. // We have to rebuild the MDL in the AFD buffer structure to
  1573. // represent exactly the number of bytes we're going to be
  1574. // sending.
  1575. //
  1576. afdBuffer->Mdl->ByteCount = sendLength;
  1577. //
  1578. // Remember the connection in the AFD buffer structure. We need
  1579. // this in order to access the connection in the restart routine.
  1580. //
  1581. afdBuffer->Context = connection;
  1582. //
  1583. // Copy the user's data into the AFD buffer.
  1584. //
  1585. if( sendLength > 0 ) {
  1586. try {
  1587. AfdCopyBufferArrayToBuffer(
  1588. afdBuffer->Buffer,
  1589. sendLength,
  1590. sendInfo->BufferArray,
  1591. sendInfo->BufferCount
  1592. );
  1593. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  1594. afdBuffer->Mdl->ByteCount = afdBuffer->BufferLength;
  1595. AfdReturnBuffer( &afdBuffer->Header, connection->OwningProcess );
  1596. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1597. connection->VcBufferredSendBytes -= sendLength;
  1598. connection->VcBufferredSendCount -= 1;
  1599. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1600. DEREFERENCE_CONNECTION (connection);
  1601. // Fast io can't handle error returns
  1602. // if call is overlapped (completion port)
  1603. // IoStatus->Status = GetExceptionCode ();
  1604. return FALSE;
  1605. }
  1606. }
  1607. //
  1608. // Use the IRP in the AFD buffer structure to give to the TDI
  1609. // provider. Build the TDI send request.
  1610. //
  1611. TdiBuildSend(
  1612. afdBuffer->Irp,
  1613. connection->DeviceObject,
  1614. connection->FileObject,
  1615. AfdRestartBufferSend,
  1616. afdBuffer,
  1617. afdBuffer->Mdl,
  1618. 0,
  1619. sendLength
  1620. );
  1621. //
  1622. // Call the transport to actually perform the send.
  1623. //
  1624. status = IoCallDriver(
  1625. connection->DeviceObject,
  1626. afdBuffer->Irp
  1627. );
  1628. //
  1629. // Complete the user's IRP as appropriate. Note that we change the
  1630. // status code from what was returned by the TDI provider into
  1631. // STATUS_SUCCESS. This is because we don't want to complete
  1632. // the IRP with STATUS_PENDING etc.
  1633. //
  1634. if ( NT_SUCCESS(status) ) {
  1635. IoStatus->Information = sendLength;
  1636. IoStatus->Status = STATUS_SUCCESS;
  1637. return TRUE;
  1638. }
  1639. //
  1640. // The call failed for some reason. Fail fast IO.
  1641. //
  1642. return FALSE;
  1643. }
  1644. BOOLEAN
  1645. AfdFastConnectionReceive (
  1646. IN PAFD_ENDPOINT endpoint,
  1647. IN PAFD_RECV_INFO recvInfo,
  1648. IN ULONG recvLength,
  1649. OUT PIO_STATUS_BLOCK IoStatus
  1650. )
  1651. {
  1652. PLIST_ENTRY listEntry;
  1653. ULONG totalOffset, partialLength;
  1654. PAFD_BUFFER_HEADER afdBuffer, partialAfdBuffer=NULL;
  1655. PAFD_CONNECTION connection;
  1656. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1657. LIST_ENTRY bufferListHead;
  1658. BOOLEAN retryReceive = FALSE; // Retry receive if additional data
  1659. // was indicated by the transport and buffered
  1660. // while we were copying current batch.
  1661. ASSERT( endpoint->Type == AfdBlockTypeVcConnecting ||
  1662. endpoint->Type == AfdBlockTypeVcBoth );
  1663. IoStatus->Status = STATUS_SUCCESS;
  1664. IoStatus->Information = 0;
  1665. Retry:
  1666. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1667. connection = endpoint->Common.VcConnecting.Connection;
  1668. if (connection==NULL) {
  1669. //
  1670. // connection might have been cleaned up by transmit file.
  1671. //
  1672. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  1673. //
  1674. // If we have already copied something before retrying,
  1675. // return success, next receive will report the error.
  1676. //
  1677. return retryReceive;
  1678. }
  1679. ASSERT( connection->Type == AfdBlockTypeConnection );
  1680. IF_DEBUG(FAST_IO) {
  1681. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1682. "AfdFastConnectionReceive: attempting fast IO on endp %p, conn %p\n",
  1683. endpoint, connection));
  1684. }
  1685. //
  1686. // Determine whether we'll be able to perform fast IO. In order
  1687. // to do fast IO, there must be some bufferred data on the
  1688. // connection, there must not be any pended receives on the
  1689. // connection, and there must not be any bufferred expedited
  1690. // data on the connection. This last requirement is for
  1691. // the sake of simplicity only.
  1692. //
  1693. if ( !IsListEmpty( &connection->VcReceiveIrpListHead ) ||
  1694. connection->VcBufferredExpeditedCount != 0 ||
  1695. connection->DisconnectIndicated ||
  1696. connection->AbortIndicated) {
  1697. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1698. //
  1699. // If we have already copied something before retrying,
  1700. // return success, next receive will report the error.
  1701. //
  1702. return retryReceive;
  1703. }
  1704. if (connection->VcBufferredReceiveCount == 0) {
  1705. ASSERT( IsListEmpty( &connection->VcReceiveBufferListHead ) );
  1706. //
  1707. // If this is a nonblocking endpoint, fail the request here and
  1708. // save going through the regular path.
  1709. if (!retryReceive &&
  1710. endpoint->NonBlocking &&
  1711. !(recvInfo->AfdFlags & AFD_OVERLAPPED)) {
  1712. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  1713. IF_DEBUG(EVENT_SELECT) {
  1714. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1715. "AfdFastConnectionReceive: Endp %p, Active %lx\n",
  1716. endpoint,
  1717. endpoint->EventsActive
  1718. ));
  1719. }
  1720. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1721. IoStatus->Status = STATUS_DEVICE_NOT_READY;
  1722. return TRUE;
  1723. }
  1724. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1725. //
  1726. // If we have already copied something before retrying,
  1727. // return success, next receive will report the error.
  1728. //
  1729. return retryReceive;
  1730. }
  1731. ASSERT( !IsListEmpty( &connection->VcReceiveBufferListHead ) );
  1732. //
  1733. // Get a pointer to the first bufferred AFD buffer structure on
  1734. // the connection.
  1735. //
  1736. afdBuffer = CONTAINING_RECORD(
  1737. connection->VcReceiveBufferListHead.Flink,
  1738. AFD_BUFFER_HEADER,
  1739. BufferListEntry
  1740. );
  1741. ASSERT( !afdBuffer->ExpeditedData );
  1742. //
  1743. // For message endpoints if the buffer contains a partial message
  1744. // or doesn't fit into the buffer, bail out.
  1745. // We don't want the added complexity of handling
  1746. // partial messages in the fast path.
  1747. //
  1748. if ( IS_MESSAGE_ENDPOINT(endpoint) &&
  1749. (afdBuffer->PartialMessage || afdBuffer->DataLength>recvLength)) {
  1750. //
  1751. // We shouldn't be retry-ing for message oriented endpoint
  1752. // since we only allow fast path if complete message is available.
  1753. //
  1754. ASSERT (retryReceive == FALSE);
  1755. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1756. return FALSE;
  1757. }
  1758. //
  1759. // Remeber current offset before we update
  1760. // information field (it is not 0 if we are
  1761. // re-trying).
  1762. //
  1763. totalOffset = (ULONG)IoStatus->Information;
  1764. InitializeListHead( &bufferListHead );
  1765. //
  1766. // Reference the connection object so it doen't go away
  1767. // until we return the buffer.
  1768. //
  1769. REFERENCE_CONNECTION (connection);
  1770. //
  1771. // Loop getting AFD buffers that will fill in the user's
  1772. // buffer with as much data as will fit, or else with a
  1773. // single buffer if this is not a stream endpoint. We don't
  1774. // actually do the copy within this loop because this loop
  1775. // must occur while holding a lock, and we cannot hold a
  1776. // lock while copying the data into the user's buffer
  1777. // because the user's buffer is not locked and we cannot
  1778. // take a page fault at raised IRQL.
  1779. //
  1780. while (IoStatus->Information<recvLength) {
  1781. ASSERT( connection->VcBufferredReceiveBytes >= afdBuffer->DataLength );
  1782. ASSERT( connection->VcBufferredReceiveCount > 0 );
  1783. if (recvLength-IoStatus->Information>=afdBuffer->DataLength) {
  1784. //
  1785. // If we can copy the whole buffer, remove it from the connection's list of
  1786. // buffers and place it on our local list of buffers.
  1787. //
  1788. RemoveEntryList( &afdBuffer->BufferListEntry );
  1789. InsertTailList( &bufferListHead, &afdBuffer->BufferListEntry );
  1790. //
  1791. // Update the count of bytes on the connection.
  1792. //
  1793. connection->VcBufferredReceiveBytes -= afdBuffer->DataLength;
  1794. connection->VcBufferredReceiveCount -= 1;
  1795. IoStatus->Information += afdBuffer->DataLength;
  1796. //
  1797. // If this is a stream endpoint and more buffers are available,
  1798. // try to fit the next one it as well..
  1799. //
  1800. if (!IS_MESSAGE_ENDPOINT(endpoint) &&
  1801. !IsListEmpty( &connection->VcReceiveBufferListHead ) ) {
  1802. afdBuffer = CONTAINING_RECORD(
  1803. connection->VcReceiveBufferListHead.Flink,
  1804. AFD_BUFFER_HEADER,
  1805. BufferListEntry
  1806. );
  1807. ASSERT( !afdBuffer->ExpeditedData );
  1808. continue;
  1809. }
  1810. }
  1811. else {
  1812. //
  1813. // Copy just a part of the buffer that fits and
  1814. // increment its reference count so it doesn't get
  1815. // destroyed until we done copying.
  1816. //
  1817. ASSERT (!IS_MESSAGE_ENDPOINT (endpoint));
  1818. partialLength = recvLength-(ULONG)IoStatus->Information;
  1819. partialAfdBuffer = afdBuffer;
  1820. partialAfdBuffer->DataLength -= partialLength;
  1821. partialAfdBuffer->DataOffset += partialLength;
  1822. InterlockedIncrement (&partialAfdBuffer->RefCount);
  1823. connection->VcBufferredReceiveBytes -= partialLength;
  1824. IoStatus->Information = recvLength;
  1825. }
  1826. break;
  1827. }
  1828. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  1829. if( !IsListEmpty( &connection->VcReceiveBufferListHead )) {
  1830. AfdIndicateEventSelectEvent(
  1831. endpoint,
  1832. AFD_POLL_RECEIVE,
  1833. STATUS_SUCCESS
  1834. );
  1835. retryReceive = FALSE;
  1836. }
  1837. else {
  1838. //
  1839. // We got all the data buffered. It is possible
  1840. // that while we are copying data, more gets indicated
  1841. // by the transport since we copy at passive level
  1842. // and indication occur at DPC (or even on another processor).
  1843. // We'll check again after copying, so we return as much data
  1844. // as possible to the application (to improve performance).
  1845. // For message oriented transports we can only
  1846. // deliver one message at a time and we shouldn't be on the fast path
  1847. // if we do not have a complete message.
  1848. // If application has EventSelect/select/AsyncSelect outstanding.
  1849. // we can't copy more data as well since it would receive a signal
  1850. // to come back and we would already consumed the data. We are not
  1851. // concerned with the case when application calls some form of select
  1852. // while we are in this routine because signaling is not guaranteed
  1853. // to be multithread safe (e.g. if select comes right before we take
  1854. // the spinlock in the beginning of this routine, application will
  1855. // get false signal as well).
  1856. //
  1857. retryReceive = IoStatus->Information<recvLength &&
  1858. !IS_MESSAGE_ENDPOINT (endpoint) &&
  1859. (endpoint->EventsEnabled & AFD_POLL_RECEIVE)==0 &&
  1860. !endpoint->PollCalled;
  1861. //
  1862. // Disable fast IO path to avoid performance penalty
  1863. // of unneccessarily going through it.
  1864. //
  1865. if (!endpoint->NonBlocking)
  1866. endpoint->DisableFastIoRecv = TRUE;
  1867. }
  1868. //
  1869. // If there is indicated but unreceived data in the TDI provider,
  1870. // and we have available buffer space, fire off an IRP to receive
  1871. // the data.
  1872. //
  1873. if ( connection->VcReceiveBytesInTransport > 0
  1874. &&
  1875. connection->VcBufferredReceiveBytes <
  1876. connection->MaxBufferredReceiveBytes
  1877. ) {
  1878. ULONG bytesToReceive;
  1879. PAFD_BUFFER newAfdBuffer;
  1880. //
  1881. // Remember the count of data that we're going to receive,
  1882. // then reset the fields in the connection where we keep
  1883. // track of how much data is available in the transport.
  1884. // We reset it here before releasing the lock so that
  1885. // another thread doesn't try to receive the data at the
  1886. // same time as us.
  1887. //
  1888. if ( connection->VcReceiveBytesInTransport > AfdLargeBufferSize ) {
  1889. bytesToReceive = connection->VcReceiveBytesInTransport;
  1890. } else {
  1891. bytesToReceive = AfdLargeBufferSize;
  1892. }
  1893. //
  1894. // Get an AFD buffer structure to hold the data.
  1895. //
  1896. newAfdBuffer = AfdGetBuffer( bytesToReceive, 0,
  1897. connection->OwningProcess );
  1898. if ( newAfdBuffer == NULL ) {
  1899. //
  1900. // If we were unable to get a buffer, just remember
  1901. // that we still have data in transport
  1902. //
  1903. if (connection->VcBufferredReceiveBytes == 0 &&
  1904. !connection->OnLRList) {
  1905. //
  1906. // Since we do not have any data buffered, application
  1907. // is not notified and will never call with recv.
  1908. // We will have to put this on low resource list
  1909. // and attempt to allocate memory and pull the data
  1910. // later.
  1911. //
  1912. connection->OnLRList = TRUE;
  1913. REFERENCE_CONNECTION (connection);
  1914. AfdLRListAddItem (&connection->LRListItem, AfdLRRepostReceive);
  1915. }
  1916. else {
  1917. UPDATE_CONN (connection);
  1918. }
  1919. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1920. } else {
  1921. connection->VcReceiveBytesInTransport = 0;
  1922. ASSERT (InterlockedDecrement (&connection->VcReceiveIrpsInTransport)==-1);
  1923. //
  1924. // We need to remember the connection in the AFD buffer
  1925. // because we'll need to access it in the completion
  1926. // routine.
  1927. //
  1928. newAfdBuffer->Context = connection;
  1929. //
  1930. // Acquire connection reference to be released in completion routine
  1931. //
  1932. REFERENCE_CONNECTION (connection);
  1933. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1934. //
  1935. // Finish building the receive IRP to give to the TDI provider.
  1936. //
  1937. TdiBuildReceive(
  1938. newAfdBuffer->Irp,
  1939. connection->DeviceObject,
  1940. connection->FileObject,
  1941. AfdRestartBufferReceive,
  1942. newAfdBuffer,
  1943. newAfdBuffer->Mdl,
  1944. TDI_RECEIVE_NORMAL,
  1945. (CLONG)bytesToReceive
  1946. );
  1947. //
  1948. // Hand off the IRP to the TDI provider.
  1949. //
  1950. (VOID)IoCallDriver(
  1951. connection->DeviceObject,
  1952. newAfdBuffer->Irp
  1953. );
  1954. }
  1955. } else {
  1956. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1957. }
  1958. //
  1959. // We have in a local list all the data we'll use for this
  1960. // IO. Start copying data to the user buffer.
  1961. //
  1962. while ( !IsListEmpty( &bufferListHead ) ) {
  1963. //
  1964. // Take the first buffer from the list.
  1965. //
  1966. listEntry = RemoveHeadList( &bufferListHead );
  1967. afdBuffer = CONTAINING_RECORD(
  1968. listEntry,
  1969. AFD_BUFFER_HEADER,
  1970. BufferListEntry
  1971. );
  1972. DEBUG afdBuffer->BufferListEntry.Flink = NULL;
  1973. if( afdBuffer->DataLength > 0 ) {
  1974. ASSERTMSG (
  1975. "NIC Driver freed the packet before it was returned!!!",
  1976. !afdBuffer->NdisPacket ||
  1977. (MmIsAddressValid (afdBuffer->Context) &&
  1978. MmIsAddressValid (MmGetSystemAddressForMdl (afdBuffer->Mdl))) );
  1979. try {
  1980. //
  1981. // Copy the data in the buffer to the user buffer.
  1982. //
  1983. AfdCopyMdlChainToBufferArray(
  1984. recvInfo->BufferArray,
  1985. totalOffset,
  1986. recvInfo->BufferCount,
  1987. afdBuffer->Mdl,
  1988. afdBuffer->DataOffset,
  1989. afdBuffer->DataLength
  1990. );
  1991. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  1992. //
  1993. // If an exception is hit, there is the possibility of
  1994. // data corruption. However, it is nearly impossible to
  1995. // avoid this in all cases, so just throw out the
  1996. // remainder of the data that we would have copied to
  1997. // the user buffer.
  1998. //
  1999. if (afdBuffer->RefCount==1 || // Can't change once off the list
  2000. InterlockedDecrement (&afdBuffer->RefCount)==0) {
  2001. AfdReturnBuffer( afdBuffer, connection->OwningProcess );
  2002. }
  2003. while ( !IsListEmpty( &bufferListHead ) ) {
  2004. listEntry = RemoveHeadList( &bufferListHead );
  2005. afdBuffer = CONTAINING_RECORD(
  2006. listEntry,
  2007. AFD_BUFFER_HEADER,
  2008. BufferListEntry
  2009. );
  2010. DEBUG afdBuffer->BufferListEntry.Flink = NULL;
  2011. if (afdBuffer->RefCount==1 || // Can't change once off the list
  2012. InterlockedDecrement (&afdBuffer->RefCount)==0) {
  2013. AfdReturnBuffer( afdBuffer, connection->OwningProcess );
  2014. }
  2015. }
  2016. //
  2017. // We'll have to abort since there is a possibility of data corruption.
  2018. // Shame on application for giving us bogus buffers.
  2019. // This also releases the reference that we needed to return the buffer.
  2020. //
  2021. AfdAbortConnection (connection);
  2022. // Fast io can't handle error returns
  2023. // if call is overlapped (completion port)
  2024. // IoStatus->Status = GetExceptionCode ();
  2025. return FALSE;
  2026. }
  2027. totalOffset += afdBuffer->DataLength;
  2028. }
  2029. //
  2030. // We're done with the AFD buffer.
  2031. //
  2032. if (afdBuffer->RefCount==1 || // Can't change once off the list
  2033. InterlockedDecrement (&afdBuffer->RefCount)==0) {
  2034. AfdReturnBuffer( afdBuffer, connection->OwningProcess );
  2035. }
  2036. }
  2037. //
  2038. // Copy any partial buffers
  2039. //
  2040. if (partialAfdBuffer) {
  2041. ASSERT (partialLength>0);
  2042. ASSERTMSG (
  2043. "NIC Driver freed the packet before it was returned!!!",
  2044. !partialAfdBuffer->NdisPacket ||
  2045. (MmIsAddressValid (partialAfdBuffer->Context) &&
  2046. MmIsAddressValid (MmGetSystemAddressForMdl (partialAfdBuffer->Mdl))) );
  2047. try {
  2048. //
  2049. // Copy the data in the buffer to the user buffer.
  2050. //
  2051. AfdCopyMdlChainToBufferArray(
  2052. recvInfo->BufferArray,
  2053. totalOffset,
  2054. recvInfo->BufferCount,
  2055. partialAfdBuffer->Mdl,
  2056. partialAfdBuffer->DataOffset-partialLength,
  2057. partialLength
  2058. );
  2059. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  2060. if (InterlockedDecrement (&partialAfdBuffer->RefCount)==0) {
  2061. ASSERT (partialAfdBuffer->BufferListEntry.Flink == NULL);
  2062. AfdReturnBuffer( partialAfdBuffer, connection->OwningProcess );
  2063. }
  2064. //
  2065. // We'll have to abort since there is a possibility of data corruption.
  2066. // Shame on application for giving us bogus buffers.
  2067. // This also releases the reference that we needed to return the buffer.
  2068. //
  2069. AfdAbortConnection (connection);
  2070. // Fast io can't handle error returns
  2071. // if call is overlapped (completion port)
  2072. // IoStatus->Status = GetExceptionCode ();
  2073. return FALSE;
  2074. }
  2075. if (InterlockedDecrement (&partialAfdBuffer->RefCount)==0) {
  2076. ASSERT (partialAfdBuffer->BufferListEntry.Flink == NULL);
  2077. AfdReturnBuffer( partialAfdBuffer, connection->OwningProcess );
  2078. }
  2079. totalOffset += partialLength;
  2080. }
  2081. ASSERT (IoStatus->Information==totalOffset);
  2082. //
  2083. // If more data is available, we need to retry and attempt to completely
  2084. // fill application's buffer.
  2085. //
  2086. if (retryReceive && (endpoint->EventsActive & AFD_POLL_RECEIVE)) {
  2087. ASSERT (IoStatus->Information<recvLength && !IS_MESSAGE_ENDPOINT (endpoint));
  2088. DEREFERENCE_CONNECTION2 (connection, "Fast retry receive 0x%lX bytes", (ULONG)IoStatus->Information);
  2089. goto Retry;
  2090. }
  2091. else {
  2092. //
  2093. // Release the reference needed to return the buffer(s).
  2094. //
  2095. DEREFERENCE_CONNECTION2 (connection, "Fast receive 0x%lX bytes", (ULONG)IoStatus->Information);
  2096. }
  2097. ASSERT( IoStatus->Information <= recvLength );
  2098. ASSERT (IoStatus->Status == STATUS_SUCCESS);
  2099. return TRUE;
  2100. }
  2101. BOOLEAN
  2102. AfdFastDatagramSend (
  2103. IN PAFD_ENDPOINT endpoint,
  2104. IN PAFD_SEND_DATAGRAM_INFO sendInfo,
  2105. IN ULONG sendLength,
  2106. OUT PIO_STATUS_BLOCK IoStatus
  2107. )
  2108. {
  2109. PAFD_BUFFER afdBuffer = NULL;
  2110. NTSTATUS status;
  2111. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2112. //
  2113. // If this is a send for more than the threshold number of
  2114. // bytes, don't use the fast path. We don't allow larger sends
  2115. // in the fast path because of the extra data copy it entails,
  2116. // which is more expensive for large buffers. For smaller
  2117. // buffers, however, the cost of the copy is small compared to
  2118. // the IO system overhead of the slow path.
  2119. //
  2120. // We also copy and return for non-blocking endpoints regardless
  2121. // of the size. That's what we are supposed to do according
  2122. // to the spec.
  2123. //
  2124. if ( !endpoint->NonBlocking && sendLength > AfdFastSendDatagramThreshold ) {
  2125. return FALSE;
  2126. }
  2127. //
  2128. // If we already buffered to many sends, go the long way.
  2129. //
  2130. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2131. if ( endpoint->DgBufferredSendBytes >=
  2132. endpoint->Common.Datagram.MaxBufferredSendBytes &&
  2133. endpoint->DgBufferredSendBytes>0) {
  2134. if ( endpoint->NonBlocking && !( sendInfo->AfdFlags & AFD_OVERLAPPED ) ) {
  2135. endpoint->EventsActive &= ~AFD_POLL_SEND;
  2136. endpoint->EnableSendEvent = TRUE;
  2137. IF_DEBUG(EVENT_SELECT) {
  2138. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2139. "AfdFastIoDeviceControl: Endp %p, Active %lX\n",
  2140. endpoint,
  2141. endpoint->EventsActive
  2142. ));
  2143. }
  2144. }
  2145. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2146. //
  2147. // If this is a nonblocking endpoint, fail the request here and
  2148. // save going through the regular path.(check for non-blocking is
  2149. // below, otherwise status code is ignored).
  2150. //
  2151. status = STATUS_DEVICE_NOT_READY;
  2152. goto errorset;
  2153. }
  2154. endpoint->DgBufferredSendBytes += sendLength;
  2155. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2156. IF_DEBUG(FAST_IO) {
  2157. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2158. "AfdFastDatagramSend: attempting fast IO on endp %p\n",
  2159. endpoint));
  2160. }
  2161. //
  2162. // Get an AFD buffer to use for the request. We'll copy the
  2163. // user's data to the AFD buffer then submit the IRP in the AFD
  2164. // buffer to the TDI provider.
  2165. if ((sendInfo->TdiConnInfo.RemoteAddressLength==0) &&
  2166. !IS_TDI_DGRAM_CONNECTION(endpoint)) {
  2167. retry:
  2168. try {
  2169. //
  2170. // Get an AFD buffer to use for the request. We'll copy the
  2171. // user to the AFD buffer then submit the IRP in the AFD
  2172. // buffer to the TDI provider.
  2173. //
  2174. afdBuffer = AfdGetBufferRaiseOnFailure(
  2175. sendLength,
  2176. endpoint->Common.Datagram.RemoteAddressLength,
  2177. endpoint->OwningProcess
  2178. );
  2179. }
  2180. except (AFD_EXCEPTION_FILTER (&status)) {
  2181. goto exit;
  2182. }
  2183. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2184. //
  2185. // If the endpoint is not connected, fail.
  2186. //
  2187. if ( endpoint->State != AfdEndpointStateConnected ) {
  2188. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2189. AfdReturnBuffer (&afdBuffer->Header, endpoint->OwningProcess);
  2190. status = STATUS_INVALID_CONNECTION;
  2191. goto exit;
  2192. }
  2193. if (afdBuffer->AllocatedAddressLength <
  2194. endpoint->Common.Datagram.RemoteAddressLength ) {
  2195. //
  2196. // Apparently connection address length has changed
  2197. // on us while we were allocating the buffer.
  2198. // This is extremely unlikely (even if endpoint got
  2199. // connected to a different address, the length is unlikely
  2200. // to change), but we must handle this, just try again.
  2201. //
  2202. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2203. AfdReturnBuffer (&afdBuffer->Header, endpoint->OwningProcess);
  2204. goto retry;
  2205. }
  2206. //
  2207. // Copy the address to the AFD buffer.
  2208. //
  2209. RtlCopyMemory(
  2210. afdBuffer->TdiInfo.RemoteAddress,
  2211. endpoint->Common.Datagram.RemoteAddress,
  2212. endpoint->Common.Datagram.RemoteAddressLength
  2213. );
  2214. afdBuffer->TdiInfo.RemoteAddressLength = endpoint->Common.Datagram.RemoteAddressLength;
  2215. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2216. }
  2217. else {
  2218. try {
  2219. afdBuffer = AfdGetBufferRaiseOnFailure( sendLength, sendInfo->TdiConnInfo.RemoteAddressLength,
  2220. endpoint->OwningProcess);
  2221. //
  2222. // Copy address if necessary.
  2223. //
  2224. if (sendInfo->TdiConnInfo.RemoteAddressLength!=0) {
  2225. RtlCopyMemory(
  2226. afdBuffer->TdiInfo.RemoteAddress,
  2227. sendInfo->TdiConnInfo.RemoteAddress,
  2228. sendInfo->TdiConnInfo.RemoteAddressLength
  2229. );
  2230. //
  2231. // Validate internal consistency of the transport address structure.
  2232. // Note that we HAVE to do this after copying since the malicious
  2233. // application can change the content of the buffer on us any time
  2234. // and our check will be bypassed.
  2235. //
  2236. if ((((PTRANSPORT_ADDRESS)afdBuffer->TdiInfo.RemoteAddress)->TAAddressCount!=1) ||
  2237. (LONG)sendInfo->TdiConnInfo.RemoteAddressLength<
  2238. FIELD_OFFSET (TRANSPORT_ADDRESS,
  2239. Address[0].Address[((PTRANSPORT_ADDRESS)afdBuffer->TdiInfo.RemoteAddress)->Address[0].AddressLength])) {
  2240. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2241. }
  2242. }
  2243. } except( AFD_EXCEPTION_FILTER(&status) ) {
  2244. if (afdBuffer!=NULL) {
  2245. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  2246. }
  2247. goto exit;
  2248. }
  2249. afdBuffer->TdiInfo.RemoteAddressLength = sendInfo->TdiConnInfo.RemoteAddressLength;
  2250. }
  2251. //
  2252. // Copy the output buffer to the AFD buffer.
  2253. //
  2254. try {
  2255. AfdCopyBufferArrayToBuffer(
  2256. afdBuffer->Buffer,
  2257. sendLength,
  2258. sendInfo->BufferArray,
  2259. sendInfo->BufferCount
  2260. );
  2261. //
  2262. // Store the length of the data and the address we're going to
  2263. // send.
  2264. //
  2265. afdBuffer->DataLength = sendLength;
  2266. } except( AFD_EXCEPTION_FILTER(&status) ) {
  2267. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  2268. goto exit;
  2269. }
  2270. if (IS_TDI_DGRAM_CONNECTION(endpoint)
  2271. && (afdBuffer->TdiInfo.RemoteAddressLength==0)) {
  2272. TdiBuildSend(
  2273. afdBuffer->Irp,
  2274. endpoint->AddressDeviceObject,
  2275. endpoint->AddressFileObject,
  2276. AfdRestartFastDatagramSend,
  2277. afdBuffer,
  2278. afdBuffer->Irp->MdlAddress,
  2279. 0,
  2280. sendLength
  2281. );
  2282. }
  2283. else {
  2284. //
  2285. // Set up the input TDI information to point to the destination
  2286. // address.
  2287. //
  2288. afdBuffer->TdiInfo.Options = NULL;
  2289. afdBuffer->TdiInfo.OptionsLength = 0;
  2290. afdBuffer->TdiInfo.UserData = NULL;
  2291. afdBuffer->TdiInfo.UserDataLength = 0;
  2292. //
  2293. // Initialize the IRP in the AFD buffer to do a fast datagram send.
  2294. //
  2295. TdiBuildSendDatagram(
  2296. afdBuffer->Irp,
  2297. endpoint->AddressDeviceObject,
  2298. endpoint->AddressFileObject,
  2299. AfdRestartFastDatagramSend,
  2300. afdBuffer,
  2301. afdBuffer->Irp->MdlAddress,
  2302. sendLength,
  2303. &afdBuffer->TdiInfo
  2304. );
  2305. }
  2306. //
  2307. // Change the MDL in the AFD buffer to specify only the number
  2308. // of bytes we're actually sending. This is a requirement of TDI--
  2309. // the MDL chain cannot describe a longer buffer than the send
  2310. // request.
  2311. //
  2312. afdBuffer->Mdl->ByteCount = sendLength;
  2313. //
  2314. // Reference the endpoint so that it does not go away until the send
  2315. // completes. This is necessary to ensure that a send which takes a
  2316. // very long time and lasts longer than the process will not cause a
  2317. // crash when the send datragram finally completes.
  2318. //
  2319. REFERENCE_ENDPOINT2( endpoint, "AfdFastDatagramSend, length", sendLength );
  2320. //
  2321. // Set the context to NULL initially so that if the IRP is completed
  2322. // by the stack before IoCallDriver returns, the completion routine
  2323. // does not free the buffer (and IRP in it) and we can figure out
  2324. // what the final status of the operation was and report it to the
  2325. // application
  2326. //
  2327. afdBuffer->Context = NULL;
  2328. //
  2329. // Give the IRP to the TDI provider. If the request fails
  2330. // immediately, then fail fast IO. If the request fails later on,
  2331. // there's nothing we can do about it.
  2332. //
  2333. status = IoCallDriver(
  2334. endpoint->AddressDeviceObject,
  2335. afdBuffer->Irp
  2336. );
  2337. //
  2338. // Check if completion routine has already been called and we
  2339. // can figure out what the final status is
  2340. //
  2341. if (InterlockedCompareExchangePointer (
  2342. &afdBuffer->Context,
  2343. endpoint,
  2344. NULL)!=NULL) {
  2345. BOOLEAN indicateSendEvent;
  2346. //
  2347. // Completion routine has been called, pick the final status
  2348. // and dereference the endpoint and free the buffer
  2349. //
  2350. status = afdBuffer->Irp->IoStatus.Status;
  2351. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2352. endpoint->DgBufferredSendBytes -= sendLength;
  2353. if (endpoint->DgBufferredSendBytes <
  2354. endpoint->Common.Datagram.MaxBufferredSendBytes ||
  2355. endpoint->DgBufferredSendBytes==0) {
  2356. indicateSendEvent = TRUE;
  2357. AfdIndicateEventSelectEvent (endpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  2358. }
  2359. else {
  2360. indicateSendEvent = FALSE;
  2361. }
  2362. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2363. if (indicateSendEvent) {
  2364. AfdIndicatePollEvent (endpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  2365. }
  2366. AfdReturnBuffer (&afdBuffer->Header, endpoint->OwningProcess);
  2367. DEREFERENCE_ENDPOINT2 (endpoint, "AfdFastDatagramSend-inline completion, status", status );
  2368. }
  2369. //else Completion routine has not been called, we set the pointer
  2370. // to the endpoint in the buffer context, so it can derefernce it
  2371. // and knows to free the buffer
  2372. //
  2373. if ( NT_SUCCESS(status) ) {
  2374. IoStatus->Information = sendLength;
  2375. IoStatus->Status = STATUS_SUCCESS;
  2376. return TRUE;
  2377. } else {
  2378. goto errorset;
  2379. }
  2380. exit:
  2381. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2382. endpoint->DgBufferredSendBytes -= sendLength;
  2383. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2384. errorset:
  2385. // Fast io can't handle error returns
  2386. // if call is overlapped (completion port),
  2387. if ( endpoint->NonBlocking && !( sendInfo->AfdFlags & AFD_OVERLAPPED ) ) {
  2388. // We know that it is not overlapped
  2389. IoStatus->Status = status;
  2390. return TRUE;
  2391. }
  2392. else {
  2393. return FALSE;
  2394. }
  2395. } // AfdFastDatagramSend
  2396. NTSTATUS
  2397. AfdRestartFastDatagramSend (
  2398. IN PDEVICE_OBJECT DeviceObject,
  2399. IN PIRP Irp,
  2400. IN PVOID Context
  2401. )
  2402. {
  2403. PAFD_BUFFER afdBuffer;
  2404. PAFD_ENDPOINT endpoint;
  2405. ULONG sendLength;
  2406. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2407. afdBuffer = Context;
  2408. ASSERT (IS_VALID_AFD_BUFFER (afdBuffer));
  2409. //
  2410. // Reset the AFD buffer structure.
  2411. //
  2412. ASSERT( afdBuffer->Irp == Irp );
  2413. sendLength = afdBuffer->Mdl->ByteCount;
  2414. ASSERT (afdBuffer->DataLength==sendLength);
  2415. afdBuffer->Mdl->ByteCount = afdBuffer->BufferLength;
  2416. //
  2417. // If call succeeded, transport should have sent the number of bytes requested
  2418. //
  2419. ASSERT (Irp->IoStatus.Status!=STATUS_SUCCESS ||
  2420. Irp->IoStatus.Information==sendLength);
  2421. //
  2422. // Find the endpoint used for this request if
  2423. // the IoCallDriver call has completed already
  2424. //
  2425. endpoint = InterlockedCompareExchangePointer (&afdBuffer->Context,
  2426. (PVOID)-1,
  2427. NULL);
  2428. if (endpoint!=NULL) {
  2429. BOOLEAN indicateSendEvent;
  2430. #if REFERENCE_DEBUG
  2431. NTSTATUS status;
  2432. #endif
  2433. //
  2434. // IoCallDriver has completed, free the buffer and
  2435. // dereference endpoint here
  2436. //
  2437. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  2438. AfdAcquireSpinLock (&endpoint->SpinLock, &lockHandle);
  2439. endpoint->DgBufferredSendBytes -= sendLength;
  2440. if (endpoint->DgBufferredSendBytes <
  2441. endpoint->Common.Datagram.MaxBufferredSendBytes ||
  2442. endpoint->DgBufferredSendBytes==0) {
  2443. AfdIndicateEventSelectEvent (endpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  2444. indicateSendEvent = TRUE;
  2445. }
  2446. else
  2447. indicateSendEvent = FALSE;
  2448. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  2449. if (indicateSendEvent) {
  2450. AfdIndicatePollEvent (endpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  2451. }
  2452. //
  2453. // Get rid of the reference we put on the endpoint when we started
  2454. // this I/O.
  2455. //
  2456. #if REFERENCE_DEBUG
  2457. status = Irp->IoStatus.Status;
  2458. #endif
  2459. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  2460. DEREFERENCE_ENDPOINT2 (endpoint, "AfdRestartFastDatagramSend, status", status );
  2461. }
  2462. // else IoCallDriver is not done yet, it will free the buffer
  2463. // and endpoint when done (it will look at final status and
  2464. // report it to the application).
  2465. //
  2466. // Tell the IO system to stop processing this IRP.
  2467. //
  2468. return STATUS_MORE_PROCESSING_REQUIRED;
  2469. } // AfdRestartFastSendDatagram
  2470. BOOLEAN
  2471. AfdFastDatagramReceive (
  2472. IN PAFD_ENDPOINT endpoint,
  2473. IN PAFD_RECV_MESSAGE_INFO msgInfo,
  2474. IN ULONG recvLength,
  2475. OUT PIO_STATUS_BLOCK IoStatus
  2476. )
  2477. {
  2478. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2479. PLIST_ENTRY listEntry;
  2480. PAFD_BUFFER_HEADER afdBuffer;
  2481. PTRANSPORT_ADDRESS tdiAddress;
  2482. ULONG length;
  2483. IF_DEBUG(FAST_IO) {
  2484. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2485. "AfdFastDatagramReceive: attempting fast IO on endp %p\n",
  2486. endpoint));
  2487. }
  2488. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2489. //
  2490. // If there are no datagrams available to be received, don't
  2491. // bother with the fast path.
  2492. //
  2493. if ( !ARE_DATAGRAMS_ON_ENDPOINT( endpoint ) ) {
  2494. //
  2495. // If this is a nonblocking endpoint, fail the request here and
  2496. // save going through the regular path.
  2497. //
  2498. if ( endpoint->NonBlocking && !( msgInfo->dgi.AfdFlags & AFD_OVERLAPPED ) ) {
  2499. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  2500. IF_DEBUG(EVENT_SELECT) {
  2501. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2502. "AfdFastDatagramReceive: Endp %p, Active %lX\n",
  2503. endpoint,
  2504. endpoint->EventsActive
  2505. ));
  2506. }
  2507. // Fast io can't handle error returns
  2508. // if call is overlapped (completion port), but we know here
  2509. // that call is not overlapped
  2510. IoStatus->Status = STATUS_DEVICE_NOT_READY;
  2511. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2512. return TRUE;
  2513. }
  2514. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2515. return FALSE;
  2516. }
  2517. //
  2518. // There is at least one datagram bufferred on the endpoint. Use it
  2519. // for this receive.
  2520. //
  2521. listEntry = RemoveHeadList( &endpoint->ReceiveDatagramBufferListHead );
  2522. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  2523. //
  2524. // If the datagram is too large or it is an error indication
  2525. // fail fast IO.
  2526. //
  2527. if ( (afdBuffer->DataLength > recvLength) ||
  2528. !NT_SUCCESS (afdBuffer->Status)) {
  2529. InsertHeadList(
  2530. &endpoint->ReceiveDatagramBufferListHead,
  2531. &afdBuffer->BufferListEntry
  2532. );
  2533. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2534. return FALSE;
  2535. }
  2536. //
  2537. // Update counts of bufferred datagrams and bytes on the endpoint.
  2538. //
  2539. endpoint->DgBufferredReceiveCount--;
  2540. endpoint->DgBufferredReceiveBytes -= afdBuffer->DataLength;
  2541. //
  2542. // Release the lock and copy the datagram into the user buffer. We
  2543. // can't continue to hold the lock, because it is not legal to take
  2544. // an exception at raised IRQL. Releasing the lock may result in a
  2545. // misordered datagram if there is an exception in copying to the
  2546. // user's buffer, but that is the application's fault for giving us a bogus
  2547. // pointer. Besides, datagram order is not guaranteed.
  2548. //
  2549. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2550. try {
  2551. if (afdBuffer->DataLength>0) {
  2552. AfdCopyMdlChainToBufferArray(
  2553. msgInfo->dgi.BufferArray,
  2554. 0,
  2555. msgInfo->dgi.BufferCount,
  2556. afdBuffer->Mdl,
  2557. 0,
  2558. afdBuffer->DataLength
  2559. );
  2560. }
  2561. //
  2562. // If we need to return the source address, copy it to the
  2563. // user's output buffer.
  2564. //
  2565. if ( msgInfo->dgi.Address != NULL ) {
  2566. tdiAddress = afdBuffer->TdiInfo.RemoteAddress;
  2567. length = tdiAddress->Address[0].AddressLength +
  2568. sizeof(u_short); // sa_family
  2569. if( *msgInfo->dgi.AddressLength < length ) {
  2570. ExRaiseAccessViolation();
  2571. }
  2572. if (ExGetPreviousMode ()!=KernelMode) {
  2573. ProbeForWrite (msgInfo->dgi.Address,
  2574. length,
  2575. sizeof (UCHAR));
  2576. }
  2577. RtlCopyMemory(
  2578. msgInfo->dgi.Address,
  2579. &tdiAddress->Address[0].AddressType,
  2580. length
  2581. );
  2582. *msgInfo->dgi.AddressLength = length;
  2583. }
  2584. if (msgInfo->ControlLength!=NULL) {
  2585. if (afdBuffer->DatagramFlags & TDI_RECEIVE_CONTROL_INFO &&
  2586. afdBuffer->DataOffset>0) {
  2587. PAFD_BUFFER buf = CONTAINING_RECORD (afdBuffer, AFD_BUFFER, Header);
  2588. ASSERT (msgInfo->MsgFlags!=NULL);
  2589. ASSERT (buf->BufferLength != AfdBufferTagSize);
  2590. length = buf->DataOffset;
  2591. #ifdef _WIN64
  2592. if (IoIs32bitProcess (NULL)) {
  2593. length = AfdComputeCMSGLength32 (
  2594. (PUCHAR)buf->Buffer+afdBuffer->DataLength,
  2595. length);
  2596. if (length>*msgInfo->ControlLength) {
  2597. ExRaiseAccessViolation ();
  2598. }
  2599. if (ExGetPreviousMode ()!=KernelMode) {
  2600. ProbeForWrite (msgInfo->ControlBuffer,
  2601. length,
  2602. sizeof (UCHAR));
  2603. }
  2604. AfdCopyCMSGBuffer32 (
  2605. msgInfo->ControlBuffer,
  2606. (PUCHAR)buf->Buffer+afdBuffer->DataLength,
  2607. length);
  2608. }
  2609. else
  2610. #endif // _WIN64
  2611. {
  2612. if (length>*msgInfo->ControlLength) {
  2613. ExRaiseAccessViolation ();
  2614. }
  2615. if (ExGetPreviousMode ()!=KernelMode) {
  2616. ProbeForWrite (msgInfo->ControlBuffer,
  2617. length,
  2618. sizeof (UCHAR));
  2619. }
  2620. RtlCopyMemory(
  2621. msgInfo->ControlBuffer,
  2622. (PUCHAR)buf->Buffer+afdBuffer->DataLength,
  2623. length
  2624. );
  2625. }
  2626. }
  2627. else {
  2628. length = 0;
  2629. }
  2630. *msgInfo->ControlLength = length;
  2631. }
  2632. if (msgInfo->MsgFlags!=NULL) {
  2633. ULONG flags = 0;
  2634. if (afdBuffer->DatagramFlags & TDI_RECEIVE_BROADCAST)
  2635. flags |= MSG_BCAST;
  2636. if (afdBuffer->DatagramFlags & TDI_RECEIVE_MULTICAST)
  2637. flags |= MSG_MCAST;
  2638. *msgInfo->MsgFlags = flags;
  2639. }
  2640. IoStatus->Information = afdBuffer->DataLength;
  2641. IoStatus->Status = STATUS_SUCCESS;
  2642. } except( AFD_EXCEPTION_FILTER(NULL) ) {
  2643. //
  2644. // Put the buffer back on the endpoint's list.
  2645. //
  2646. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2647. InsertHeadList(
  2648. &endpoint->ReceiveDatagramBufferListHead,
  2649. &afdBuffer->BufferListEntry
  2650. );
  2651. endpoint->DgBufferredReceiveCount++;
  2652. endpoint->DgBufferredReceiveBytes += afdBuffer->DataLength;
  2653. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2654. // Fast io can't handle error returns
  2655. // if call is overlapped (completion port)
  2656. // IoStatus->Status = GetExceptionCode ();
  2657. return FALSE;
  2658. }
  2659. //
  2660. // Clear the receive data active bit. If there's more data
  2661. // available, set the corresponding event.
  2662. //
  2663. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  2664. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  2665. if( ARE_DATAGRAMS_ON_ENDPOINT( endpoint ) ) {
  2666. AfdIndicateEventSelectEvent(
  2667. endpoint,
  2668. AFD_POLL_RECEIVE,
  2669. STATUS_SUCCESS
  2670. );
  2671. }
  2672. else {
  2673. //
  2674. // Disable fast IO path to avoid performance penalty
  2675. // of going through it.
  2676. //
  2677. if (!endpoint->NonBlocking)
  2678. endpoint->DisableFastIoRecv = TRUE;
  2679. }
  2680. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  2681. //
  2682. // The fast IO worked! Clean up and return to the user.
  2683. //
  2684. AfdReturnBuffer( afdBuffer, endpoint->OwningProcess );
  2685. ASSERT (IoStatus->Status == STATUS_SUCCESS);
  2686. return TRUE;
  2687. } // AfdFastDatagramReceive
  2688. BOOLEAN
  2689. AfdShouldSendBlock (
  2690. IN PAFD_ENDPOINT Endpoint,
  2691. IN PAFD_CONNECTION Connection,
  2692. IN ULONG SendLength
  2693. )
  2694. /*++
  2695. Routine Description:
  2696. Determines whether a nonblocking send can be performed on the
  2697. connection, and if the send is possible, updates the connection's
  2698. send tracking information.
  2699. Arguments:
  2700. Endpoint - the AFD endpoint for the send.
  2701. Connection - the AFD connection for the send.
  2702. SendLength - the number of bytes that the caller wants to send.
  2703. Return Value:
  2704. TRUE if the there is not too much data on the endpoint to perform
  2705. the send; FALSE otherwise.
  2706. Note:
  2707. This routine assumes that endpoint spinlock is held when calling it.
  2708. --*/
  2709. {
  2710. //
  2711. // Determine whether we can do fast IO with this send. In order
  2712. // to perform fast IO, there must be no other sends pended on this
  2713. // connection and there must be enough space left for bufferring
  2714. // the requested amount of data.
  2715. //
  2716. if ( !IsListEmpty( &Connection->VcSendIrpListHead )
  2717. ||
  2718. Connection->VcBufferredSendBytes >= Connection->MaxBufferredSendBytes
  2719. ) {
  2720. //
  2721. // If this is a nonblocking endpoint, fail the request here and
  2722. // save going through the regular path.
  2723. //
  2724. if ( Endpoint->NonBlocking ) {
  2725. Endpoint->EventsActive &= ~AFD_POLL_SEND;
  2726. Endpoint->EnableSendEvent = TRUE;
  2727. IF_DEBUG(EVENT_SELECT) {
  2728. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2729. "AfdFastIoDeviceControl: Endp %p, Active %lX\n",
  2730. Endpoint,
  2731. Endpoint->EventsActive
  2732. ));
  2733. }
  2734. }
  2735. return TRUE;
  2736. }
  2737. //
  2738. // Update count of send bytes pending on the connection.
  2739. //
  2740. Connection->VcBufferredSendBytes += SendLength;
  2741. Connection->VcBufferredSendCount += 1;
  2742. //
  2743. // Indicate to the caller that it is OK to proceed with the send.
  2744. //
  2745. return FALSE;
  2746. } // AfdShouldSendBlock