Leaked source code of windows server 2003
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.

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