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

2309 lines
68 KiB

  1. /*++
  2. Copyright (c) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. recvdg.c
  5. Abstract:
  6. This module contains routines for handling data receive for datagram
  7. endpoints.
  8. Author:
  9. David Treadwell (davidtr) 7-Oct-1993
  10. Revision History:
  11. --*/
  12. #include "afdp.h"
  13. NTSTATUS
  14. AfdRestartReceiveDatagramWithUserIrp (
  15. IN PDEVICE_OBJECT DeviceObject,
  16. IN PIRP Irp,
  17. IN PVOID Context
  18. );
  19. NTSTATUS
  20. AfdRestartBufferReceiveDatagram (
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN PIRP Irp,
  23. IN PVOID Context
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text( PAGEAFD, AfdReceiveDatagram )
  27. #pragma alloc_text( PAGEAFD, AfdReceiveDatagramEventHandler )
  28. #pragma alloc_text( PAGEAFD, AfdSetupReceiveDatagramIrp )
  29. #pragma alloc_text( PAGEAFD, AfdRestartBufferReceiveDatagram )
  30. #pragma alloc_text( PAGEAFD, AfdRestartReceiveDatagramWithUserIrp )
  31. #pragma alloc_text( PAGEAFD, AfdCancelReceiveDatagram )
  32. #pragma alloc_text( PAGEAFD, AfdCleanupReceiveDatagramIrp )
  33. #endif
  34. //
  35. // Macros to make the receive datagram code more maintainable.
  36. //
  37. #define AfdRecvDatagramInfo Others
  38. #define AfdRecvAddressMdl Argument1
  39. #define AfdRecvAddressLenMdl Argument2
  40. #define AfdRecvControlLenMdl Argument3
  41. #define AfdRecvFlagsMdl Argument4
  42. #define AfdRecvMsgControlMdl Tail.Overlay.DriverContext[0]
  43. #define AfdRecvLength Tail.Overlay.DriverContext[1]
  44. #define AfdRecvDgIndStatus DeviceIoControl.OutputBufferLength
  45. NTSTATUS
  46. FASTCALL
  47. AfdReceiveDatagram (
  48. IN PIRP Irp,
  49. IN PIO_STACK_LOCATION IrpSp
  50. )
  51. {
  52. NTSTATUS status;
  53. AFD_LOCK_QUEUE_HANDLE lockHandle;
  54. PAFD_ENDPOINT endpoint;
  55. PLIST_ENTRY listEntry;
  56. BOOLEAN peek;
  57. PAFD_BUFFER_HEADER afdBuffer;
  58. ULONG recvFlags;
  59. ULONG afdFlags;
  60. ULONG recvLength;
  61. PVOID addressPointer;
  62. PMDL addressMdl;
  63. PULONG addressLengthPointer;
  64. ULONG addressLength;
  65. PMDL lengthMdl;
  66. PVOID controlPointer;
  67. PMDL controlMdl;
  68. ULONG controlLength;
  69. PULONG controlLengthPointer;
  70. PMDL controlLengthMdl;
  71. PULONG flagsPointer;
  72. PMDL flagsMdl;
  73. ULONG bufferCount;
  74. //
  75. // Set up some local variables.
  76. //
  77. endpoint = IrpSp->FileObject->FsContext;
  78. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  79. Irp->IoStatus.Information = 0;
  80. addressMdl = NULL;
  81. lengthMdl = NULL;
  82. controlMdl = NULL;
  83. flagsMdl = NULL;
  84. controlLengthMdl = NULL;
  85. if (!IS_DGRAM_ENDPOINT(endpoint)) {
  86. status = STATUS_INVALID_PARAMETER;
  87. goto complete;
  88. }
  89. //
  90. // If receive has been shut down or the endpoint aborted, fail.
  91. //
  92. // !!! Do we care if datagram endpoints get aborted?
  93. //
  94. if ( (endpoint->DisconnectMode & AFD_PARTIAL_DISCONNECT_RECEIVE) ) {
  95. status = STATUS_PIPE_DISCONNECTED;
  96. goto complete;
  97. }
  98. //
  99. // Make sure that the endpoint is in the correct state.
  100. //
  101. if ( endpoint->State != AfdEndpointStateBound &&
  102. endpoint->State != AfdEndpointStateConnected) {
  103. status = STATUS_INVALID_PARAMETER;
  104. goto complete;
  105. }
  106. //
  107. // Do some special processing based on whether this is a receive
  108. // datagram IRP, a receive IRP, or a read IRP.
  109. //
  110. if ( IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL ) {
  111. if ( IrpSp->Parameters.DeviceIoControl.IoControlCode ==
  112. IOCTL_AFD_RECEIVE_MESSAGE) {
  113. #ifdef _WIN64
  114. if (IoIs32bitProcess (Irp)) {
  115. PAFD_RECV_MESSAGE_INFO32 msgInfo32;
  116. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  117. sizeof(*msgInfo32) ) {
  118. status = STATUS_INVALID_PARAMETER;
  119. goto complete;
  120. }
  121. try {
  122. msgInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  123. if( Irp->RequestorMode != KernelMode ) {
  124. ProbeForRead(
  125. msgInfo32,
  126. sizeof(*msgInfo32),
  127. PROBE_ALIGNMENT32 (AFD_RECV_MESSAGE_INFO32)
  128. );
  129. }
  130. controlPointer = msgInfo32->ControlBuffer;
  131. controlLengthPointer = msgInfo32->ControlLength;
  132. flagsPointer = msgInfo32->MsgFlags;
  133. }
  134. except (AFD_EXCEPTION_FILTER (&status)) {
  135. goto complete;
  136. }
  137. }
  138. else
  139. #endif _WIN64
  140. {
  141. PAFD_RECV_MESSAGE_INFO msgInfo;
  142. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  143. sizeof(*msgInfo) ) {
  144. status = STATUS_INVALID_PARAMETER;
  145. goto complete;
  146. }
  147. try {
  148. msgInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  149. if( Irp->RequestorMode != KernelMode ) {
  150. ProbeForRead(
  151. msgInfo,
  152. sizeof(*msgInfo),
  153. PROBE_ALIGNMENT (AFD_RECV_MESSAGE_INFO)
  154. );
  155. }
  156. controlPointer = msgInfo->ControlBuffer;
  157. controlLengthPointer = msgInfo->ControlLength;
  158. flagsPointer = msgInfo->MsgFlags;
  159. }
  160. except (AFD_EXCEPTION_FILTER (&status)) {
  161. goto complete;
  162. }
  163. }
  164. try {
  165. //
  166. // Create a MDL describing the length buffer, then probe it
  167. // for write access.
  168. //
  169. flagsMdl = IoAllocateMdl(
  170. flagsPointer, // VirtualAddress
  171. sizeof(*flagsPointer), // Length
  172. FALSE, // SecondaryBuffer
  173. TRUE, // ChargeQuota
  174. NULL // Irp
  175. );
  176. if( flagsMdl == NULL ) {
  177. status = STATUS_INSUFFICIENT_RESOURCES;
  178. goto complete;
  179. }
  180. MmProbeAndLockPages(
  181. flagsMdl, // MemoryDescriptorList
  182. Irp->RequestorMode, // AccessMode
  183. IoWriteAccess // Operation
  184. );
  185. controlLengthMdl = IoAllocateMdl(
  186. controlLengthPointer, // VirtualAddress
  187. sizeof(*controlLengthPointer),// Length
  188. FALSE, // SecondaryBuffer
  189. TRUE, // ChargeQuota
  190. NULL // Irp
  191. );
  192. if( controlLengthMdl == NULL ) {
  193. status = STATUS_INSUFFICIENT_RESOURCES;
  194. goto complete;
  195. }
  196. MmProbeAndLockPages(
  197. controlLengthMdl, // MemoryDescriptorList
  198. Irp->RequestorMode, // AccessMode
  199. IoWriteAccess // Operation
  200. );
  201. controlLength = *controlLengthPointer;
  202. if (controlLength!=0) {
  203. //
  204. // Create a MDL describing the control buffer, then probe
  205. // it for write access.
  206. //
  207. controlMdl = IoAllocateMdl(
  208. controlPointer, // VirtualAddress
  209. controlLength, // Length
  210. FALSE, // SecondaryBuffer
  211. TRUE, // ChargeQuota
  212. NULL // Irp
  213. );
  214. if( controlMdl == NULL ) {
  215. status = STATUS_INSUFFICIENT_RESOURCES;
  216. goto complete;
  217. }
  218. MmProbeAndLockPages(
  219. controlMdl, // MemoryDescriptorList
  220. Irp->RequestorMode, // AccessMode
  221. IoWriteAccess // Operation
  222. );
  223. }
  224. } except( AFD_EXCEPTION_FILTER(&status) ) {
  225. goto complete;
  226. }
  227. //
  228. // Change the control code to continue processing of the regular
  229. // RecvFrom parameters.
  230. //
  231. IrpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_AFD_RECEIVE_DATAGRAM;
  232. }
  233. if ( IrpSp->Parameters.DeviceIoControl.IoControlCode ==
  234. IOCTL_AFD_RECEIVE_DATAGRAM) {
  235. #ifdef _WIN64
  236. if (IoIs32bitProcess (Irp)) {
  237. PAFD_RECV_DATAGRAM_INFO32 recvInfo32;
  238. LPWSABUF32 bufferArray32;
  239. //
  240. // Grab the parameters from the input structure.
  241. //
  242. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  243. sizeof(*recvInfo32) ) {
  244. try {
  245. //
  246. // Validate the input structure if it comes from the user mode
  247. // application
  248. //
  249. recvInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  250. if( Irp->RequestorMode != KernelMode ) {
  251. ProbeForRead(
  252. recvInfo32,
  253. sizeof(*recvInfo32),
  254. PROBE_ALIGNMENT32(AFD_RECV_DATAGRAM_INFO32)
  255. );
  256. }
  257. //
  258. // Make local copies of the embeded pointer and parameters
  259. // that we will be using more than once in case malicios
  260. // application attempts to change them while we are
  261. // validating
  262. //
  263. recvFlags = recvInfo32->TdiFlags;
  264. afdFlags = recvInfo32->AfdFlags;
  265. bufferArray32 = recvInfo32->BufferArray;
  266. bufferCount = recvInfo32->BufferCount;
  267. addressPointer = recvInfo32->Address;
  268. addressLengthPointer = recvInfo32->AddressLength;
  269. //
  270. // Validate the WSABUF parameters.
  271. //
  272. if ( bufferArray32 != NULL &&
  273. bufferCount > 0 ) {
  274. //
  275. // Create the MDL chain describing the WSABUF array.
  276. // This will also validate the buffer array and individual
  277. // buffers
  278. //
  279. status = AfdAllocateMdlChain32(
  280. Irp, // Requestor mode passed along
  281. bufferArray32,
  282. bufferCount,
  283. IoWriteAccess,
  284. &recvLength
  285. );
  286. } else {
  287. //
  288. // Zero-length input buffer. This is OK for datagrams.
  289. //
  290. ASSERT( Irp->MdlAddress == NULL );
  291. status = STATUS_SUCCESS;
  292. recvLength = 0;
  293. }
  294. } except ( AFD_EXCEPTION_FILTER(&status) ) {
  295. //
  296. // Exception accessing input structure.
  297. //
  298. }
  299. } else {
  300. //
  301. // Invalid input buffer length.
  302. //
  303. status = STATUS_INVALID_PARAMETER;
  304. }
  305. }
  306. else
  307. #endif _WIN64
  308. {
  309. PAFD_RECV_DATAGRAM_INFO recvInfo;
  310. LPWSABUF bufferArray;
  311. //
  312. // Grab the parameters from the input structure.
  313. //
  314. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  315. sizeof(*recvInfo) ) {
  316. try {
  317. //
  318. // Validate the input structure if it comes from the user mode
  319. // application
  320. //
  321. recvInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  322. if( Irp->RequestorMode != KernelMode ) {
  323. ProbeForRead(
  324. recvInfo,
  325. sizeof(*recvInfo),
  326. PROBE_ALIGNMENT(AFD_RECV_DATAGRAM_INFO)
  327. );
  328. }
  329. //
  330. // Make local copies of the embeded pointer and parameters
  331. // that we will be using more than once in case malicios
  332. // application attempts to change them while we are
  333. // validating
  334. //
  335. recvFlags = recvInfo->TdiFlags;
  336. afdFlags = recvInfo->AfdFlags;
  337. bufferArray = recvInfo->BufferArray;
  338. bufferCount = recvInfo->BufferCount;
  339. addressPointer = recvInfo->Address;
  340. addressLengthPointer = recvInfo->AddressLength;
  341. //
  342. // Validate the WSABUF parameters.
  343. //
  344. if ( bufferArray != NULL &&
  345. bufferCount > 0 ) {
  346. //
  347. // Create the MDL chain describing the WSABUF array.
  348. // This will also validate the buffer array and individual
  349. // buffers
  350. //
  351. status = AfdAllocateMdlChain(
  352. Irp, // Requestor mode passed along
  353. bufferArray,
  354. bufferCount,
  355. IoWriteAccess,
  356. &recvLength
  357. );
  358. } else {
  359. //
  360. // Zero-length input buffer. This is OK for datagrams.
  361. //
  362. ASSERT( Irp->MdlAddress == NULL );
  363. recvLength = 0;
  364. status = STATUS_SUCCESS;
  365. }
  366. } except ( AFD_EXCEPTION_FILTER(&status) ) {
  367. //
  368. // Exception accessing input structure.
  369. //
  370. }
  371. } else {
  372. //
  373. // Invalid input buffer length.
  374. //
  375. status = STATUS_INVALID_PARAMETER;
  376. }
  377. }
  378. if( !NT_SUCCESS(status) ) {
  379. goto complete;
  380. }
  381. //
  382. // Validate the receive flags.
  383. //
  384. if( ( recvFlags & TDI_RECEIVE_EITHER ) != TDI_RECEIVE_NORMAL ) {
  385. status = STATUS_NOT_SUPPORTED;
  386. goto complete;
  387. }
  388. peek = (BOOLEAN)( (recvFlags & TDI_RECEIVE_PEEK) != 0 );
  389. //
  390. // If only one of addressPointer or addressLength are NULL, then
  391. // fail the request.
  392. //
  393. if( (addressPointer == NULL) ^ (addressLengthPointer == NULL) ) {
  394. status = STATUS_INVALID_PARAMETER;
  395. goto complete;
  396. }
  397. //
  398. // If the user wants the source address from the receive datagram,
  399. // then create MDLs for the address & address length, then probe
  400. // and lock the MDLs.
  401. //
  402. if( addressPointer != NULL ) {
  403. ASSERT( addressLengthPointer != NULL );
  404. try {
  405. //
  406. // Create a MDL describing the length buffer, then probe it
  407. // for write access.
  408. //
  409. lengthMdl = IoAllocateMdl(
  410. addressLengthPointer, // VirtualAddress
  411. sizeof(*addressLengthPointer),// Length
  412. FALSE, // SecondaryBuffer
  413. TRUE, // ChargeQuota
  414. NULL // Irp
  415. );
  416. if( lengthMdl == NULL ) {
  417. status = STATUS_INSUFFICIENT_RESOURCES;
  418. goto complete;
  419. }
  420. MmProbeAndLockPages(
  421. lengthMdl, // MemoryDescriptorList
  422. Irp->RequestorMode, // AccessMode
  423. IoWriteAccess // Operation
  424. );
  425. //
  426. // Save length to a local so that malicious app
  427. // cannot break us by modifying the value in the middle of
  428. // us processing it below here. Also, we can use this pointer now
  429. // since we probed it above.
  430. //
  431. addressLength = *addressLengthPointer;
  432. //
  433. // Bomb off if the user is trying to do something bad, like
  434. // specify a zero-length address, or one that's unreasonably
  435. // huge. Here, we define "unreasonably huge" as MAXUSHORT
  436. // or greater because TDI address length field is USHORT.
  437. //
  438. if( addressLength == 0 ||
  439. addressLength >= MAXUSHORT ) {
  440. status = STATUS_INVALID_PARAMETER;
  441. goto complete;
  442. }
  443. //
  444. // Create a MDL describing the address buffer, then probe
  445. // it for write access.
  446. //
  447. addressMdl = IoAllocateMdl(
  448. addressPointer, // VirtualAddress
  449. addressLength, // Length
  450. FALSE, // SecondaryBuffer
  451. TRUE, // ChargeQuota
  452. NULL // Irp
  453. );
  454. if( addressMdl == NULL ) {
  455. status = STATUS_INSUFFICIENT_RESOURCES;
  456. goto complete;
  457. }
  458. MmProbeAndLockPages(
  459. addressMdl, // MemoryDescriptorList
  460. Irp->RequestorMode, // AccessMode
  461. IoWriteAccess // Operation
  462. );
  463. } except( AFD_EXCEPTION_FILTER(&status) ) {
  464. goto complete;
  465. }
  466. ASSERT( addressMdl != NULL );
  467. ASSERT( lengthMdl != NULL );
  468. } else {
  469. ASSERT( addressMdl == NULL );
  470. ASSERT( lengthMdl == NULL );
  471. }
  472. } else {
  473. ASSERT( (Irp->Flags & IRP_INPUT_OPERATION) == 0 );
  474. //
  475. // Grab the input parameters from the IRP.
  476. //
  477. ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode ==
  478. IOCTL_AFD_RECEIVE );
  479. recvFlags = ((PAFD_RECV_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->TdiFlags;
  480. afdFlags = ((PAFD_RECV_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer)->AfdFlags;
  481. recvLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  482. //
  483. // It is illegal to attempt to receive expedited data on a
  484. // datagram endpoint.
  485. //
  486. if ( (recvFlags & TDI_RECEIVE_EXPEDITED) != 0 ) {
  487. status = STATUS_NOT_SUPPORTED;
  488. goto complete;
  489. }
  490. ASSERT( ( recvFlags & TDI_RECEIVE_EITHER ) == TDI_RECEIVE_NORMAL );
  491. peek = (BOOLEAN)( (recvFlags & TDI_RECEIVE_PEEK) != 0 );
  492. }
  493. } else {
  494. //
  495. // This must be a read IRP. There are no special options
  496. // for a read IRP.
  497. //
  498. ASSERT( IrpSp->MajorFunction == IRP_MJ_READ );
  499. recvFlags = TDI_RECEIVE_NORMAL;
  500. afdFlags = AFD_OVERLAPPED;
  501. recvLength = IrpSp->Parameters.Read.Length;
  502. peek = FALSE;
  503. }
  504. //
  505. // Save the address & length MDLs in the current IRP stack location.
  506. // These will be used later in SetupReceiveDatagramIrp(). Note that
  507. // they should either both be NULL or both be non-NULL.
  508. //
  509. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  510. //
  511. // Check if endpoint was cleaned-up and cancel the request.
  512. //
  513. if (endpoint->EndpointCleanedUp) {
  514. AfdReleaseSpinLock (&endpoint->SpinLock, &lockHandle);
  515. status = STATUS_CANCELLED;
  516. goto complete;
  517. }
  518. ASSERT( !( ( addressMdl == NULL ) ^ ( lengthMdl == NULL ) ) );
  519. IrpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl = addressMdl;
  520. IrpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl = lengthMdl;
  521. IrpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl = controlLengthMdl;
  522. IrpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl = flagsMdl;
  523. Irp->AfdRecvMsgControlMdl = controlMdl;
  524. Irp->AfdRecvLength = UlongToPtr (recvLength);
  525. //
  526. // Determine whether there are any datagrams already bufferred on
  527. // this endpoint. If there is a bufferred datagram, we'll use it to
  528. // complete the IRP.
  529. //
  530. if ( ARE_DATAGRAMS_ON_ENDPOINT(endpoint) ) {
  531. //
  532. // There is at least one datagram bufferred on the endpoint.
  533. // Use it for this receive.
  534. //
  535. ASSERT( !IsListEmpty( &endpoint->ReceiveDatagramBufferListHead ) );
  536. listEntry = endpoint->ReceiveDatagramBufferListHead.Flink;
  537. afdBuffer = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  538. //
  539. // Prepare the user's IRP for completion.
  540. //
  541. if (NT_SUCCESS(afdBuffer->Status)) {
  542. PAFD_BUFFER buf = CONTAINING_RECORD (afdBuffer, AFD_BUFFER, Header);
  543. ASSERT (afdBuffer->BufferLength!=AfdBufferTagSize);
  544. status = AfdSetupReceiveDatagramIrp (
  545. Irp,
  546. buf->Buffer,
  547. buf->DataLength,
  548. (PUCHAR)buf->Buffer+afdBuffer->DataLength,
  549. buf->DataOffset,
  550. buf->TdiInfo.RemoteAddress,
  551. buf->TdiInfo.RemoteAddressLength,
  552. buf->DatagramFlags
  553. );
  554. }
  555. else {
  556. //
  557. // This is error report from the transport
  558. // (ICMP_PORT_UNREACHEABLE)
  559. //
  560. Irp->IoStatus.Status = afdBuffer->Status;
  561. ASSERT (afdBuffer->DataLength==0);
  562. Irp->IoStatus.Information = 0;
  563. status = AfdSetupReceiveDatagramIrp (
  564. Irp,
  565. NULL, 0,
  566. NULL, 0,
  567. afdBuffer->TdiInfo.RemoteAddress,
  568. afdBuffer->TdiInfo.RemoteAddressLength,
  569. 0
  570. );
  571. }
  572. //
  573. // If this wasn't a peek IRP, remove the buffer from the endpoint's
  574. // list of bufferred datagrams.
  575. //
  576. if ( !peek ) {
  577. RemoveHeadList( &endpoint->ReceiveDatagramBufferListHead );
  578. //
  579. // Update the counts of bytes and datagrams on the endpoint.
  580. //
  581. endpoint->DgBufferredReceiveCount--;
  582. endpoint->DgBufferredReceiveBytes -= afdBuffer->DataLength;
  583. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  584. IF_DEBUG(EVENT_SELECT) {
  585. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  586. "AfdReceiveDatagram: Endp %p, Active %lx\n",
  587. endpoint,
  588. endpoint->EventsActive
  589. ));
  590. }
  591. if( ARE_DATAGRAMS_ON_ENDPOINT(endpoint)) {
  592. AfdIndicateEventSelectEvent(
  593. endpoint,
  594. AFD_POLL_RECEIVE,
  595. STATUS_SUCCESS
  596. );
  597. }
  598. else {
  599. //
  600. // Disable fast IO path to avoid performance penalty
  601. // of unneccessarily going through it.
  602. //
  603. if (!endpoint->NonBlocking)
  604. endpoint->DisableFastIoRecv = TRUE;
  605. }
  606. }
  607. //
  608. // We've set up all return information. Clean up and complete
  609. // the IRP.
  610. //
  611. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  612. if ( !peek ) {
  613. AfdReturnBuffer( afdBuffer, endpoint->OwningProcess );
  614. }
  615. UPDATE_ENDPOINT2 (endpoint,
  616. "AfdReceiveDatagram, completing with error/bytes: 0x%lX",
  617. NT_SUCCESS (Irp->IoStatus.Status)
  618. ? (ULONG)Irp->IoStatus.Information
  619. : (ULONG)Irp->IoStatus.Status);
  620. IoCompleteRequest( Irp, 0 );
  621. return status;
  622. }
  623. //
  624. // There were no datagrams bufferred on the endpoint. If this is a
  625. // nonblocking endpoint and the request was a normal receive (as
  626. // opposed to a read IRP), fail the request. We don't fail reads
  627. // under the asumption that if the application is doing reads they
  628. // don't want nonblocking behavior.
  629. //
  630. if ( endpoint->NonBlocking && !ARE_DATAGRAMS_ON_ENDPOINT( endpoint ) &&
  631. !( afdFlags & AFD_OVERLAPPED ) ) {
  632. endpoint->EventsActive &= ~AFD_POLL_RECEIVE;
  633. IF_DEBUG(EVENT_SELECT) {
  634. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  635. "AfdReceiveDatagram: Endp %p, Active %lx\n",
  636. endpoint,
  637. endpoint->EventsActive
  638. ));
  639. }
  640. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  641. status = STATUS_DEVICE_NOT_READY;
  642. goto complete;
  643. }
  644. //
  645. // We'll have to pend the IRP. Place the IRP on the appropriate IRP
  646. // list in the endpoint.
  647. //
  648. if ( peek ) {
  649. InsertTailList(
  650. &endpoint->PeekDatagramIrpListHead,
  651. &Irp->Tail.Overlay.ListEntry
  652. );
  653. } else {
  654. InsertTailList(
  655. &endpoint->ReceiveDatagramIrpListHead,
  656. &Irp->Tail.Overlay.ListEntry
  657. );
  658. }
  659. //
  660. // Set up the cancellation routine in the IRP. If the IRP has already
  661. // been cancelled, just call the cancellation routine here.
  662. //
  663. IoSetCancelRoutine( Irp, AfdCancelReceiveDatagram );
  664. if ( Irp->Cancel ) {
  665. RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
  666. if (IoSetCancelRoutine( Irp, NULL ) != NULL) {
  667. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  668. status = STATUS_CANCELLED;
  669. goto complete;
  670. }
  671. //
  672. // The cancel routine will run and complete the irp.
  673. // Set Flink to NULL so it knows that IRP is not on the list.
  674. //
  675. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  676. }
  677. IoMarkIrpPending( Irp );
  678. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  679. return STATUS_PENDING;
  680. complete:
  681. ASSERT( !NT_SUCCESS(status) );
  682. if( addressMdl != NULL ) {
  683. if( (addressMdl->MdlFlags & MDL_PAGES_LOCKED) != 0 ) {
  684. MmUnlockPages( addressMdl );
  685. }
  686. IoFreeMdl( addressMdl );
  687. }
  688. if( lengthMdl != NULL ) {
  689. if( (lengthMdl->MdlFlags & MDL_PAGES_LOCKED) != 0 ) {
  690. MmUnlockPages( lengthMdl );
  691. }
  692. IoFreeMdl( lengthMdl );
  693. }
  694. if (controlMdl != NULL) {
  695. if( (controlMdl->MdlFlags & MDL_PAGES_LOCKED) != 0 ) {
  696. MmUnlockPages( controlMdl );
  697. }
  698. IoFreeMdl( controlMdl );
  699. }
  700. if (controlLengthMdl != NULL) {
  701. if( (controlLengthMdl->MdlFlags & MDL_PAGES_LOCKED) != 0 ) {
  702. MmUnlockPages( controlLengthMdl );
  703. }
  704. IoFreeMdl( controlLengthMdl );
  705. }
  706. if (flagsMdl != NULL) {
  707. if( (flagsMdl->MdlFlags & MDL_PAGES_LOCKED) != 0 ) {
  708. MmUnlockPages( flagsMdl );
  709. }
  710. IoFreeMdl( flagsMdl );
  711. }
  712. UPDATE_ENDPOINT2 (endpoint,
  713. "AfdReceiveDatagram, completing with error 0x%lX",
  714. (ULONG)Irp->IoStatus.Status);
  715. Irp->IoStatus.Status = status;
  716. IoCompleteRequest( Irp, 0 );
  717. return status;
  718. } // AfdReceiveDatagram
  719. NTSTATUS
  720. AfdReceiveDatagramEventHandler (
  721. IN PVOID TdiEventContext,
  722. IN int SourceAddressLength,
  723. IN PVOID SourceAddress,
  724. IN int OptionsLength,
  725. IN PVOID Options,
  726. IN ULONG ReceiveDatagramFlags,
  727. IN ULONG BytesIndicated,
  728. IN ULONG BytesAvailable,
  729. OUT ULONG *BytesTaken,
  730. IN PVOID Tsdu,
  731. OUT PIRP *IoRequestPacket
  732. )
  733. /*++
  734. Routine Description:
  735. Handles receive datagram events for nonbufferring transports.
  736. Arguments:
  737. Return Value:
  738. --*/
  739. {
  740. AFD_LOCK_QUEUE_HANDLE lockHandle;
  741. PAFD_ENDPOINT endpoint;
  742. PAFD_BUFFER afdBuffer;
  743. BOOLEAN result;
  744. //
  745. // Reference the endpoint so that it doesn't go away beneath us.
  746. //
  747. endpoint = TdiEventContext;
  748. ASSERT( endpoint != NULL );
  749. CHECK_REFERENCE_ENDPOINT (endpoint, result);
  750. if (!result)
  751. return STATUS_INSUFFICIENT_RESOURCES;
  752. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  753. #if AFD_PERF_DBG
  754. if ( BytesAvailable == BytesIndicated ) {
  755. AfdFullReceiveDatagramIndications++;
  756. } else {
  757. AfdPartialReceiveDatagramIndications++;
  758. }
  759. #endif
  760. //
  761. // If this endpoint is connected and the datagram is for a different
  762. // address than the one the endpoint is connected to, drop the
  763. // datagram.
  764. //
  765. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  766. if ( (endpoint->State == AfdEndpointStateConnected &&
  767. !endpoint->Common.Datagram.HalfConnect &&
  768. !AfdAreTransportAddressesEqual(
  769. endpoint->Common.Datagram.RemoteAddress,
  770. endpoint->Common.Datagram.RemoteAddressLength,
  771. SourceAddress,
  772. SourceAddressLength,
  773. TRUE ))) {
  774. endpoint->Common.Datagram.AddressDrop = TRUE;
  775. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  776. *BytesTaken = BytesAvailable;
  777. DEREFERENCE_ENDPOINT (endpoint);
  778. return STATUS_SUCCESS;
  779. }
  780. //
  781. // Check whether there are any IRPs waiting on the endpoint. If
  782. // there is such an IRP, use it to receive the datagram.
  783. //
  784. while ( !IsListEmpty( &endpoint->ReceiveDatagramIrpListHead ) ) {
  785. PLIST_ENTRY listEntry;
  786. PIRP irp;
  787. ASSERT( *BytesTaken == 0 );
  788. ASSERT( endpoint->DgBufferredReceiveCount == 0 );
  789. ASSERT( endpoint->DgBufferredReceiveBytes == 0 );
  790. listEntry = RemoveHeadList( &endpoint->ReceiveDatagramIrpListHead );
  791. //
  792. // Get a pointer to the IRP and reset the cancel routine in
  793. // the IRP. The IRP is no longer cancellable.
  794. //
  795. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  796. if ( IoSetCancelRoutine( irp, NULL ) == NULL ) {
  797. //
  798. // This IRP is about to be canceled. Look for another in the
  799. // list. Set the Flink to NULL so the cancel routine knows
  800. // it is not on the list.
  801. //
  802. irp->Tail.Overlay.ListEntry.Flink = NULL;
  803. continue;
  804. }
  805. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  806. //
  807. // Copy the datagram and source address to the IRP. This
  808. // prepares the IRP to be completed.
  809. //
  810. // !!! do we need a special version of this routine to
  811. // handle special RtlCopyMemory, like for
  812. // TdiCopyLookaheadBuffer?
  813. //
  814. if( BytesIndicated == BytesAvailable ||
  815. irp->MdlAddress == NULL ) {
  816. //
  817. // Set BytesTaken to indicate that we've taken all the
  818. // data. We do it here because we already have
  819. // BytesAvailable in a register, which probably won't
  820. // be true after making function calls.
  821. //
  822. *BytesTaken = BytesAvailable;
  823. //
  824. // If the entire datagram is being indicated to us here, just
  825. // copy the information to the MDL in the IRP and return.
  826. //
  827. // Note that we'll also take the entire datagram if the user
  828. // has pended a zero-byte datagram receive (detectable as a
  829. // NULL Irp->MdlAddress). We'll eat the datagram and fall
  830. // through to AfdSetupReceiveDatagramIrp(), which will store
  831. // an error status in the IRP since the user's buffer is
  832. // insufficient to hold the datagram.
  833. //
  834. (VOID)AfdSetupReceiveDatagramIrp (
  835. irp,
  836. Tsdu,
  837. BytesAvailable,
  838. Options,
  839. OptionsLength,
  840. SourceAddress,
  841. SourceAddressLength,
  842. ReceiveDatagramFlags
  843. );
  844. DEREFERENCE_ENDPOINT2 (endpoint,
  845. "AfdReceiveDatagramEventHandler, completing with error/bytes: 0x%lX",
  846. NT_SUCCESS (irp->IoStatus.Status)
  847. ? (ULONG)irp->IoStatus.Information
  848. : (ULONG)irp->IoStatus.Status);
  849. //
  850. // Complete the IRP. We've already set BytesTaken
  851. // to tell the provider that we have taken all the data.
  852. //
  853. IoCompleteRequest( irp, AfdPriorityBoost );
  854. return STATUS_SUCCESS;
  855. }
  856. else {
  857. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
  858. //
  859. // Otherwise, just copy the address and options.
  860. // and remember the error code if any.
  861. //
  862. irpSp->Parameters.AfdRecvDgIndStatus =
  863. AfdSetupReceiveDatagramIrp (
  864. irp,
  865. NULL,
  866. BytesAvailable,
  867. Options,
  868. OptionsLength,
  869. SourceAddress,
  870. SourceAddressLength,
  871. ReceiveDatagramFlags
  872. );
  873. TdiBuildReceiveDatagram(
  874. irp,
  875. endpoint->AddressDeviceObject,
  876. endpoint->AddressFileObject,
  877. AfdRestartReceiveDatagramWithUserIrp,
  878. endpoint,
  879. irp->MdlAddress,
  880. BytesAvailable,
  881. NULL,
  882. NULL,
  883. 0
  884. );
  885. //
  886. // Make the next stack location current. Normally IoCallDriver would
  887. // do this, but since we're bypassing that, we do it directly.
  888. //
  889. IoSetNextIrpStackLocation( irp );
  890. *IoRequestPacket = irp;
  891. *BytesTaken = 0;
  892. return STATUS_MORE_PROCESSING_REQUIRED;
  893. }
  894. }
  895. //
  896. // There were no IRPs available to take the datagram, so we'll have
  897. // to buffer it. First make sure that we're not over the limit
  898. // of bufferring that we can do. If we're over the limit, toss
  899. // this datagram.
  900. //
  901. if (( (endpoint->DgBufferredReceiveBytes >=
  902. endpoint->Common.Datagram.MaxBufferredReceiveBytes) ||
  903. (endpoint->DgBufferredReceiveBytes==0 &&
  904. (endpoint->DgBufferredReceiveCount*sizeof (AFD_BUFFER_TAG)) >=
  905. endpoint->Common.Datagram.MaxBufferredReceiveBytes) )
  906. ) {
  907. //
  908. // If circular queueing is not enabled, then just drop the
  909. // datagram on the floor.
  910. //
  911. if( !endpoint->Common.Datagram.CircularQueueing ) {
  912. endpoint->Common.Datagram.BufferDrop = TRUE;
  913. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  914. *BytesTaken = BytesAvailable;
  915. DEREFERENCE_ENDPOINT (endpoint);
  916. return STATUS_SUCCESS;
  917. }
  918. //
  919. // Circular queueing is enabled, so drop packets at the head of
  920. // the receive queue until we're below the receive limit.
  921. //
  922. while( endpoint->DgBufferredReceiveBytes >=
  923. endpoint->Common.Datagram.MaxBufferredReceiveBytes ||
  924. (endpoint->DgBufferredReceiveBytes==0 &&
  925. (endpoint->DgBufferredReceiveCount*sizeof (AFD_BUFFER_TAG)) >=
  926. endpoint->Common.Datagram.MaxBufferredReceiveBytes) ) {
  927. PLIST_ENTRY listEntry;
  928. PAFD_BUFFER_HEADER afdBufferHdr;
  929. endpoint->DgBufferredReceiveCount--;
  930. listEntry = RemoveHeadList( &endpoint->ReceiveDatagramBufferListHead );
  931. afdBufferHdr = CONTAINING_RECORD( listEntry, AFD_BUFFER_HEADER, BufferListEntry );
  932. endpoint->DgBufferredReceiveBytes -= afdBufferHdr->DataLength;
  933. AfdReturnBuffer( afdBufferHdr, endpoint->OwningProcess );
  934. }
  935. //
  936. // Proceed to accept the incoming packet.
  937. //
  938. }
  939. //
  940. // We're able to buffer the datagram. Now acquire a buffer of
  941. // appropriate size.
  942. //
  943. afdBuffer = AfdGetBuffer (
  944. BytesAvailable
  945. + ((ReceiveDatagramFlags & TDI_RECEIVE_CONTROL_INFO)
  946. ? OptionsLength
  947. : 0),
  948. SourceAddressLength,
  949. endpoint->OwningProcess );
  950. if (afdBuffer==NULL) {
  951. endpoint->Common.Datagram.ResourceDrop = TRUE;
  952. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  953. *BytesTaken = BytesAvailable;
  954. DEREFERENCE_ENDPOINT (endpoint);
  955. return STATUS_SUCCESS;
  956. }
  957. //
  958. // Store the address of the sender of the datagram.
  959. //
  960. RtlCopyMemory(
  961. afdBuffer->TdiInfo.RemoteAddress,
  962. SourceAddress,
  963. SourceAddressLength
  964. );
  965. afdBuffer->TdiInfo.RemoteAddressLength = SourceAddressLength;
  966. //
  967. // Store what transport is supposed to return to us.
  968. //
  969. afdBuffer->DataLength = BytesAvailable;
  970. //
  971. // Note the receive flags.
  972. afdBuffer->DatagramFlags = ReceiveDatagramFlags;
  973. //
  974. // Copy control info into the buffer after the data and
  975. // store the length as data offset
  976. //
  977. if (ReceiveDatagramFlags & TDI_RECEIVE_CONTROL_INFO) {
  978. RtlMoveMemory (
  979. (PUCHAR)afdBuffer->Buffer+BytesAvailable,
  980. Options,
  981. OptionsLength);
  982. afdBuffer->DataOffset = OptionsLength;
  983. }
  984. else {
  985. afdBuffer->DataOffset = 0;
  986. }
  987. //
  988. // If the entire datagram is being indicated to us, just copy it
  989. // here.
  990. //
  991. if ( BytesIndicated == BytesAvailable ) {
  992. PIRP irp;
  993. //
  994. // If there is a peek IRP on the endpoint, remove it from the
  995. // list and prepare to complete it. We can't complete it now
  996. // because we hold a spin lock.
  997. //
  998. irp = NULL;
  999. while ( !IsListEmpty( &endpoint->PeekDatagramIrpListHead ) ) {
  1000. PLIST_ENTRY listEntry;
  1001. //
  1002. // Remove the first peek IRP from the list and get a pointer
  1003. // to it.
  1004. //
  1005. listEntry = RemoveHeadList( &endpoint->PeekDatagramIrpListHead );
  1006. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1007. //
  1008. // Reset the cancel routine in the IRP. The IRP is no
  1009. // longer cancellable, since we're about to complete it.
  1010. //
  1011. if ( IoSetCancelRoutine( irp, NULL ) == NULL ) {
  1012. //
  1013. // This IRP is about to be canceled. Look for another in the
  1014. // list. Set the Flink to NULL so the cancel routine knows
  1015. // it is not on the list.
  1016. //
  1017. irp->Tail.Overlay.ListEntry.Flink = NULL;
  1018. irp = NULL;
  1019. continue;
  1020. }
  1021. break;
  1022. }
  1023. //
  1024. // Use the special function to copy the data instead of
  1025. // RtlCopyMemory in case the data is coming from a special place
  1026. // (DMA, etc.) which cannot work with RtlCopyMemory.
  1027. //
  1028. TdiCopyLookaheadData(
  1029. afdBuffer->Buffer,
  1030. Tsdu,
  1031. BytesAvailable,
  1032. ReceiveDatagramFlags
  1033. );
  1034. //
  1035. // Store the results in the IRP as though it is completed
  1036. // by the transport.
  1037. //
  1038. afdBuffer->Irp->IoStatus.Status = STATUS_SUCCESS;
  1039. afdBuffer->Irp->IoStatus.Information = BytesAvailable;
  1040. //
  1041. // Store success status do distinguish this from
  1042. // ICMP rejects reported by ErrorEventHandler(Ex).
  1043. //
  1044. afdBuffer->Status = STATUS_SUCCESS;
  1045. //
  1046. // Place the buffer on this endpoint's list of bufferred datagrams
  1047. // and update the counts of datagrams and datagram bytes on the
  1048. // endpoint.
  1049. //
  1050. InsertTailList(
  1051. &endpoint->ReceiveDatagramBufferListHead,
  1052. &afdBuffer->BufferListEntry
  1053. );
  1054. endpoint->DgBufferredReceiveCount++;
  1055. endpoint->DgBufferredReceiveBytes += BytesAvailable;
  1056. //
  1057. // Reenable FAST IO on the endpoint to allow quick
  1058. // copying of buffered data.
  1059. //
  1060. endpoint->DisableFastIoRecv = FALSE;
  1061. //
  1062. // All done. Release the lock and tell the provider that we
  1063. // took all the data.
  1064. //
  1065. AfdIndicateEventSelectEvent(
  1066. endpoint,
  1067. AFD_POLL_RECEIVE,
  1068. STATUS_SUCCESS
  1069. );
  1070. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1071. //
  1072. // Indicate that it is possible to receive on the endpoint now.
  1073. //
  1074. AfdIndicatePollEvent(
  1075. endpoint,
  1076. AFD_POLL_RECEIVE,
  1077. STATUS_SUCCESS
  1078. );
  1079. //
  1080. // If there was a peek IRP on the endpoint, complete it now.
  1081. //
  1082. if ( irp != NULL ) {
  1083. //
  1084. // Copy the datagram and source address to the IRP. This
  1085. // prepares the IRP to be completed.
  1086. //
  1087. (VOID)AfdSetupReceiveDatagramIrp (
  1088. irp,
  1089. Tsdu,
  1090. BytesAvailable,
  1091. Options,
  1092. OptionsLength,
  1093. SourceAddress,
  1094. SourceAddressLength,
  1095. ReceiveDatagramFlags
  1096. );
  1097. IoCompleteRequest( irp, AfdPriorityBoost );
  1098. }
  1099. *BytesTaken = BytesAvailable;
  1100. DEREFERENCE_ENDPOINT (endpoint);
  1101. return STATUS_SUCCESS;
  1102. }
  1103. else {
  1104. //
  1105. // We'll have to format up an IRP and give it to the provider to
  1106. // handle. We don't need any locks to do this--the restart routine
  1107. // will check whether new receive datagram IRPs were pended on the
  1108. // endpoint.
  1109. //
  1110. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1111. //
  1112. // We need to remember the endpoint in the AFD buffer because we'll
  1113. // need to access it in the completion routine.
  1114. //
  1115. afdBuffer->Context = endpoint;
  1116. ASSERT (afdBuffer->Irp->MdlAddress==afdBuffer->Mdl);
  1117. TdiBuildReceiveDatagram(
  1118. afdBuffer->Irp,
  1119. endpoint->AddressDeviceObject,
  1120. endpoint->AddressFileObject,
  1121. AfdRestartBufferReceiveDatagram,
  1122. afdBuffer,
  1123. afdBuffer->Irp->MdlAddress,
  1124. BytesAvailable,
  1125. NULL,
  1126. NULL,
  1127. 0
  1128. );
  1129. //
  1130. // Make the next stack location current. Normally IoCallDriver would
  1131. // do this, but since we're bypassing that, we do it directly.
  1132. //
  1133. IoSetNextIrpStackLocation( afdBuffer->Irp );
  1134. *IoRequestPacket = afdBuffer->Irp;
  1135. *BytesTaken = 0;
  1136. return STATUS_MORE_PROCESSING_REQUIRED;
  1137. }
  1138. } // AfdReceiveDatagramEventHandler
  1139. NTSTATUS
  1140. AfdRestartReceiveDatagramWithUserIrp (
  1141. IN PDEVICE_OBJECT DeviceObject,
  1142. IN PIRP Irp,
  1143. IN PVOID Context
  1144. )
  1145. /*++
  1146. Routine Description:
  1147. Handles completion of datagram receives that were started
  1148. in the datagram indication handler and application IRP was
  1149. available for direct transfer.
  1150. Arguments:
  1151. DeviceObject - not used.
  1152. Irp - the IRP that is completing.
  1153. Context - referenced endpoint pointer.
  1154. Return Value:
  1155. STATUS_SUCCESS to indicate that IO completion should continue.
  1156. --*/
  1157. {
  1158. PAFD_ENDPOINT endpoint = Context;
  1159. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  1160. NTSTATUS indStatus = irpSp->Parameters.AfdRecvDgIndStatus;
  1161. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  1162. //
  1163. // Pick the worst status
  1164. //
  1165. if ((Irp->IoStatus.Status==STATUS_SUCCESS) ||
  1166. (!NT_ERROR (Irp->IoStatus.Status) && NT_ERROR(indStatus)) ||
  1167. (NT_SUCCESS (Irp->IoStatus.Status) && !NT_SUCCESS (indStatus)) ) {
  1168. Irp->IoStatus.Status = indStatus;
  1169. }
  1170. //
  1171. // If pending has be returned for this irp then mark the current
  1172. // stack as pending.
  1173. //
  1174. if ( Irp->PendingReturned ) {
  1175. IoMarkIrpPending(Irp);
  1176. }
  1177. DEREFERENCE_ENDPOINT2 (endpoint,
  1178. "AfdRestartReceiveDatagramWithUserIrp, error/bytes 0x%lX",
  1179. NT_SUCCESS (Irp->IoStatus.Status)
  1180. ? (ULONG)Irp->IoStatus.Information
  1181. : (ULONG)Irp->IoStatus.Status);
  1182. return STATUS_SUCCESS;
  1183. }
  1184. NTSTATUS
  1185. AfdRestartBufferReceiveDatagram (
  1186. IN PDEVICE_OBJECT DeviceObject,
  1187. IN PIRP Irp,
  1188. IN PVOID Context
  1189. )
  1190. /*++
  1191. Routine Description:
  1192. Handles completion of bufferred datagram receives that were started
  1193. in the datagram indication handler.
  1194. Arguments:
  1195. DeviceObject - not used.
  1196. Irp - the IRP that is completing.
  1197. Context - AfdBuffer structure.
  1198. Return Value:
  1199. STATUS_MORE_PROCESSING_REQUIRED to indicate to the IO system that we
  1200. own the IRP and the IO system should stop processing the it.
  1201. --*/
  1202. {
  1203. PAFD_ENDPOINT endpoint;
  1204. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1205. PAFD_BUFFER afdBuffer;
  1206. PIRP pendedIrp;
  1207. ASSERT( NT_SUCCESS(Irp->IoStatus.Status) );
  1208. afdBuffer = Context;
  1209. ASSERT (IS_VALID_AFD_BUFFER (afdBuffer));
  1210. ASSERT (afdBuffer->DataOffset==0 ||
  1211. (afdBuffer->DatagramFlags & TDI_RECEIVE_CONTROL_INFO));
  1212. endpoint = afdBuffer->Context;
  1213. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  1214. //
  1215. // If the IO failed, then just return the AFD buffer to our buffer
  1216. // pool.
  1217. //
  1218. if ( !NT_SUCCESS(Irp->IoStatus.Status) ) {
  1219. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  1220. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1221. endpoint->Common.Datagram.ErrorDrop = TRUE;
  1222. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1223. DEREFERENCE_ENDPOINT2 (endpoint,
  1224. "AfdRestartBufferReceiveDatagram, status: 0x%lX",
  1225. Irp->IoStatus.Status);
  1226. return STATUS_MORE_PROCESSING_REQUIRED;
  1227. }
  1228. //
  1229. // Make sure transport did not lie to us in indication handler.
  1230. //
  1231. ASSERT (afdBuffer->DataLength == (ULONG)Irp->IoStatus.Information);
  1232. //
  1233. // If there are any pended IRPs on the endpoint, complete as
  1234. // appropriate with the new information.
  1235. //
  1236. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1237. while ( !IsListEmpty( &endpoint->ReceiveDatagramIrpListHead ) ) {
  1238. PLIST_ENTRY listEntry;
  1239. //
  1240. // There was a pended receive datagram IRP. Remove it from the
  1241. // head of the list.
  1242. //
  1243. listEntry = RemoveHeadList( &endpoint->ReceiveDatagramIrpListHead );
  1244. //
  1245. // Get a pointer to the IRP and reset the cancel routine in
  1246. // the IRP. The IRP is no longer cancellable.
  1247. //
  1248. pendedIrp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1249. //
  1250. // Reset the cancel routine in the IRP. The IRP is no
  1251. // longer cancellable, since we're about to complete it.
  1252. //
  1253. if ( IoSetCancelRoutine( pendedIrp, NULL ) == NULL ) {
  1254. //
  1255. // This IRP is about to be canceled. Look for another in the
  1256. // list. Set the Flink to NULL so the cancel routine knows
  1257. // it is not on the list.
  1258. //
  1259. pendedIrp->Tail.Overlay.ListEntry.Flink = NULL;
  1260. pendedIrp = NULL;
  1261. continue;
  1262. }
  1263. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1264. //
  1265. // Set up the user's IRP for completion.
  1266. //
  1267. (VOID)AfdSetupReceiveDatagramIrp (
  1268. pendedIrp,
  1269. afdBuffer->Buffer,
  1270. afdBuffer->DataLength,
  1271. (PUCHAR)afdBuffer->Buffer+afdBuffer->DataLength,
  1272. afdBuffer->DataOffset,
  1273. afdBuffer->TdiInfo.RemoteAddress,
  1274. afdBuffer->TdiInfo.RemoteAddressLength,
  1275. afdBuffer->DatagramFlags
  1276. );
  1277. //
  1278. // Complete the user's IRP, free the AFD buffer we used for
  1279. // the request, and tell the IO system that we're done
  1280. // processing this request.
  1281. //
  1282. AfdReturnBuffer( &afdBuffer->Header, endpoint->OwningProcess );
  1283. DEREFERENCE_ENDPOINT2 (endpoint,
  1284. "AfdRestartBufferReceiveDatagram, completing IRP with 0x%lX bytes",
  1285. (ULONG)pendedIrp->IoStatus.Information);
  1286. IoCompleteRequest( pendedIrp, AfdPriorityBoost );
  1287. return STATUS_MORE_PROCESSING_REQUIRED;
  1288. }
  1289. //
  1290. // If there are any pended peek IRPs on the endpoint, complete
  1291. // one with this datagram.
  1292. //
  1293. pendedIrp = NULL;
  1294. while ( !IsListEmpty( &endpoint->PeekDatagramIrpListHead ) ) {
  1295. PLIST_ENTRY listEntry;
  1296. //
  1297. // There was a pended peek receive datagram IRP. Remove it from
  1298. // the head of the list.
  1299. //
  1300. listEntry = RemoveHeadList( &endpoint->PeekDatagramIrpListHead );
  1301. //
  1302. // Get a pointer to the IRP and reset the cancel routine in
  1303. // the IRP. The IRP is no longer cancellable.
  1304. //
  1305. pendedIrp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  1306. //
  1307. // Reset the cancel routine in the IRP. The IRP is no
  1308. // longer cancellable, since we're about to complete it.
  1309. //
  1310. if ( IoSetCancelRoutine( pendedIrp, NULL ) == NULL ) {
  1311. //
  1312. // This IRP is about to be canceled. Look for another in the
  1313. // list. Set the Flink to NULL so the cancel routine knows
  1314. // it is not on the list.
  1315. //
  1316. pendedIrp->Tail.Overlay.ListEntry.Flink = NULL;
  1317. pendedIrp = NULL;
  1318. continue;
  1319. }
  1320. //
  1321. // Set up the user's IRP for completion.
  1322. //
  1323. (VOID)AfdSetupReceiveDatagramIrp (
  1324. pendedIrp,
  1325. afdBuffer->Buffer,
  1326. afdBuffer->DataLength,
  1327. (PUCHAR)afdBuffer->Buffer+afdBuffer->DataLength,
  1328. afdBuffer->DataOffset,
  1329. afdBuffer->TdiInfo.RemoteAddress,
  1330. afdBuffer->TdiInfo.RemoteAddressLength,
  1331. afdBuffer->DatagramFlags
  1332. );
  1333. //
  1334. // Don't complete the pended peek IRP yet, since we still hold
  1335. // locks. Wait until it is safe to release the locks.
  1336. //
  1337. break;
  1338. }
  1339. //
  1340. // Store success status do distinguish this from
  1341. // ICMP rejects reported by ErrorEventHandler(Ex).
  1342. //
  1343. afdBuffer->Status = STATUS_SUCCESS;
  1344. //
  1345. // Place the datagram at the end of the endpoint's list of bufferred
  1346. // datagrams, and update counts of datagrams on the endpoint.
  1347. //
  1348. InsertTailList(
  1349. &endpoint->ReceiveDatagramBufferListHead,
  1350. &afdBuffer->BufferListEntry
  1351. );
  1352. endpoint->DgBufferredReceiveCount++;
  1353. endpoint->DgBufferredReceiveBytes += afdBuffer->DataLength;
  1354. //
  1355. // Reenable FAST IO on the endpoint to allow quick
  1356. // copying of buffered data.
  1357. //
  1358. endpoint->DisableFastIoRecv = FALSE;
  1359. //
  1360. // Release locks and indicate that there are bufferred datagrams
  1361. // on the endpoint.
  1362. //
  1363. AfdIndicateEventSelectEvent(
  1364. endpoint,
  1365. AFD_POLL_RECEIVE,
  1366. STATUS_SUCCESS
  1367. );
  1368. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1369. AfdIndicatePollEvent(
  1370. endpoint,
  1371. AFD_POLL_RECEIVE,
  1372. STATUS_SUCCESS
  1373. );
  1374. //
  1375. // If there was a pended peek IRP to complete, complete it now.
  1376. //
  1377. if ( pendedIrp != NULL ) {
  1378. IoCompleteRequest( pendedIrp, 2 );
  1379. }
  1380. //
  1381. // Tell the IO system to stop processing this IRP, since we now own
  1382. // it as part of the AFD buffer.
  1383. //
  1384. DEREFERENCE_ENDPOINT (endpoint,);
  1385. return STATUS_MORE_PROCESSING_REQUIRED;
  1386. } // AfdRestartBufferReceiveDatagram
  1387. VOID
  1388. AfdCancelReceiveDatagram (
  1389. IN PDEVICE_OBJECT DeviceObject,
  1390. IN PIRP Irp
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Cancels a receive datagram IRP that is pended in AFD.
  1395. Arguments:
  1396. DeviceObject - not used.
  1397. Irp - the IRP to cancel.
  1398. Return Value:
  1399. None.
  1400. --*/
  1401. {
  1402. PIO_STACK_LOCATION irpSp;
  1403. PAFD_ENDPOINT endpoint;
  1404. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1405. //
  1406. // Get the endpoint pointer from our IRP stack location.
  1407. //
  1408. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1409. endpoint = irpSp->FileObject->FsContext;
  1410. ASSERT( IS_DGRAM_ENDPOINT(endpoint) );
  1411. //
  1412. // Remove the IRP from the endpoint's IRP list, synchronizing with
  1413. // the endpoint lock which protects the lists. Note that the
  1414. // IRP *must* be on one of the endpoint's lists or the Flink is NULL
  1415. // if we are getting called here--anybody that removes the IRP from
  1416. // the list must reset the cancel routine to NULL and set the
  1417. // Flink to NULL before releasing the endpoint spin lock.
  1418. //
  1419. AfdAcquireSpinLock( &endpoint->SpinLock, &lockHandle );
  1420. if (Irp->Tail.Overlay.ListEntry.Flink != NULL) {
  1421. RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
  1422. }
  1423. AfdReleaseSpinLock( &endpoint->SpinLock, &lockHandle );
  1424. //
  1425. // Free any MDL chains attached to the IRP stack location.
  1426. //
  1427. AfdCleanupReceiveDatagramIrp( Irp );
  1428. //
  1429. // Release the cancel spin lock and complete the IRP with a
  1430. // cancellation status code.
  1431. //
  1432. IoReleaseCancelSpinLock( Irp->CancelIrql );
  1433. Irp->IoStatus.Information = 0;
  1434. Irp->IoStatus.Status = STATUS_CANCELLED;
  1435. IoCompleteRequest( Irp, AfdPriorityBoost );
  1436. return;
  1437. } // AfdCancelReceiveDatagram
  1438. BOOLEAN
  1439. AfdCleanupReceiveDatagramIrp(
  1440. IN PIRP Irp
  1441. )
  1442. /*++
  1443. Routine Description:
  1444. Performs any cleanup specific to receive datagram IRPs.
  1445. Arguments:
  1446. Irp - the IRP to cleanup.
  1447. Return Value:
  1448. TRUE - complete IRP, FALSE - leave alone.
  1449. Notes:
  1450. This routine may be called at raised IRQL from AfdCompleteIrpList().
  1451. --*/
  1452. {
  1453. PIO_STACK_LOCATION irpSp;
  1454. PMDL mdl;
  1455. //
  1456. // Get the endpoint pointer from our IRP stack location.
  1457. //
  1458. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1459. //
  1460. // Free any MDL chains attached to the IRP stack location.
  1461. //
  1462. mdl = (PMDL)irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl;
  1463. if( mdl != NULL ) {
  1464. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl = NULL;
  1465. MmUnlockPages( mdl );
  1466. IoFreeMdl( mdl );
  1467. }
  1468. mdl = (PMDL)irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl;
  1469. if( mdl != NULL ) {
  1470. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl = NULL;
  1471. MmUnlockPages( mdl );
  1472. IoFreeMdl( mdl );
  1473. }
  1474. mdl = (PMDL)irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl;
  1475. if( mdl != NULL ) {
  1476. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl = NULL;
  1477. MmUnlockPages( mdl );
  1478. IoFreeMdl( mdl );
  1479. }
  1480. mdl = (PMDL)irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl;
  1481. if( mdl != NULL ) {
  1482. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl = NULL;
  1483. MmUnlockPages( mdl );
  1484. IoFreeMdl( mdl );
  1485. }
  1486. mdl = (PMDL)Irp->AfdRecvMsgControlMdl;
  1487. if( mdl != NULL ) {
  1488. Irp->AfdRecvMsgControlMdl = NULL;
  1489. MmUnlockPages( mdl );
  1490. IoFreeMdl( mdl );
  1491. }
  1492. return TRUE;
  1493. } // AfdCleanupReceiveDatagramIrp
  1494. NTSTATUS
  1495. AfdSetupReceiveDatagramIrp (
  1496. IN PIRP Irp,
  1497. IN PVOID DatagramBuffer OPTIONAL,
  1498. IN ULONG DatagramLength,
  1499. IN PVOID ControlBuffer OPTIONAL,
  1500. IN ULONG ControlLength,
  1501. IN PVOID SourceAddress OPTIONAL,
  1502. IN ULONG SourceAddressLength,
  1503. IN ULONG TdiReceiveFlags
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. Copies the datagram to the MDL in the IRP and the datagram sender's
  1508. address to the appropriate place in the system buffer.
  1509. Arguments:
  1510. Irp - the IRP to prepare for completion.
  1511. DatagramBuffer - datagram to copy into the IRP. If NULL, then
  1512. there is no need to copy the datagram to the IRP's MDL, the
  1513. datagram has already been copied there.
  1514. DatagramLength - the length of the datagram to copy.
  1515. SourceAddress - address of the sender of the datagram.
  1516. SourceAddressLength - length of the source address.
  1517. Return Value:
  1518. NTSTATUS - The status code placed into the IRP.
  1519. --*/
  1520. {
  1521. NTSTATUS status;
  1522. PIO_STACK_LOCATION irpSp;
  1523. BOOLEAN dataOverflow = FALSE;
  1524. BOOLEAN controlOverflow = FALSE;
  1525. //
  1526. // To determine how to complete setting up the IRP for completion,
  1527. // figure out whether this IRP was for regular datagram information,
  1528. // in which case we need to return an address, or for data only, in
  1529. // which case we will not return the source address. NtReadFile()
  1530. // and recv() on connected datagram sockets will result in the
  1531. // latter type of IRP.
  1532. //
  1533. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1534. //
  1535. // If necessary, copy the datagram in the buffer to the MDL in the
  1536. // user's IRP. If there is no MDL in the buffer, then fail if the
  1537. // datagram is larger than 0 bytes.
  1538. //
  1539. if ( ARGUMENT_PRESENT( DatagramBuffer ) ) {
  1540. ULONG bytesCopied = 0;
  1541. if ( Irp->MdlAddress == NULL ) {
  1542. if ( DatagramLength != 0 ) {
  1543. status = STATUS_BUFFER_OVERFLOW;
  1544. } else {
  1545. status = STATUS_SUCCESS;
  1546. }
  1547. } else {
  1548. status = AfdMapMdlChain (Irp->MdlAddress);
  1549. if (NT_SUCCESS (status)) {
  1550. status = TdiCopyBufferToMdl(
  1551. DatagramBuffer,
  1552. 0,
  1553. DatagramLength,
  1554. Irp->MdlAddress,
  1555. 0,
  1556. &bytesCopied
  1557. );
  1558. }
  1559. }
  1560. Irp->IoStatus.Information = bytesCopied;
  1561. } else {
  1562. //
  1563. // The information was already copied to the MDL chain in the
  1564. // IRP. Just remember the IO status block so we can do the
  1565. // right thing with it later.
  1566. //
  1567. status = Irp->IoStatus.Status;
  1568. if (DatagramLength>PtrToUlong (Irp->AfdRecvLength)) {
  1569. status = STATUS_BUFFER_OVERFLOW;
  1570. }
  1571. }
  1572. if (status==STATUS_BUFFER_OVERFLOW) {
  1573. dataOverflow = TRUE;
  1574. }
  1575. if( irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl != NULL ) {
  1576. PMDL addressMdl = irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl;
  1577. PMDL addressLenMdl = irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl;
  1578. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressMdl = NULL;
  1579. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl = NULL;
  1580. ASSERT( addressMdl->Next == NULL );
  1581. ASSERT( ( addressMdl->MdlFlags & MDL_PAGES_LOCKED ) != 0 );
  1582. ASSERT( MmGetMdlByteCount (addressMdl) > 0 );
  1583. ASSERT( addressLenMdl != NULL );
  1584. ASSERT( addressLenMdl->Next == NULL );
  1585. ASSERT( ( addressLenMdl->MdlFlags & MDL_PAGES_LOCKED ) != 0 );
  1586. ASSERT( MmGetMdlByteCount (addressLenMdl)==sizeof (ULONG) );
  1587. if ((NT_SUCCESS (status) ||
  1588. status==STATUS_BUFFER_OVERFLOW ||
  1589. status==STATUS_PORT_UNREACHABLE) &&
  1590. ARGUMENT_PRESENT (SourceAddress)) {
  1591. PVOID dst;
  1592. PTRANSPORT_ADDRESS tdiAddress;
  1593. //
  1594. // Extract the real SOCKADDR structure from the TDI address.
  1595. // This duplicates MSAFD.DLL's SockBuildSockaddr() function.
  1596. //
  1597. C_ASSERT( sizeof(tdiAddress->Address[0].AddressType) == sizeof(u_short) );
  1598. C_ASSERT( FIELD_OFFSET( TA_ADDRESS, AddressLength ) == 0 );
  1599. C_ASSERT( FIELD_OFFSET( TA_ADDRESS, AddressType ) == sizeof(USHORT) );
  1600. ASSERT( FIELD_OFFSET( TRANSPORT_ADDRESS, Address[0] ) == sizeof(int) );
  1601. tdiAddress = SourceAddress;
  1602. ASSERT( SourceAddressLength >=
  1603. (tdiAddress->Address[0].AddressLength + sizeof(u_short)) );
  1604. SourceAddressLength = tdiAddress->Address[0].AddressLength +
  1605. sizeof(u_short); // sa_family
  1606. SourceAddress = &tdiAddress->Address[0].AddressType;
  1607. //
  1608. // Copy the address to the user's buffer, then unlock and
  1609. // free the MDL describing the user's buffer.
  1610. //
  1611. if (SourceAddressLength>MmGetMdlByteCount (addressMdl)) {
  1612. status = STATUS_BUFFER_TOO_SMALL;
  1613. }
  1614. else {
  1615. dst = MmGetSystemAddressForMdlSafe (addressMdl, LowPagePriority);
  1616. if (dst!=NULL) {
  1617. PULONG dstU;
  1618. RtlMoveMemory (dst, SourceAddress, SourceAddressLength);
  1619. //
  1620. // Copy succeeded, return the length as well.
  1621. //
  1622. dstU = MmGetSystemAddressForMdlSafe (addressLenMdl, LowPagePriority);
  1623. if (dstU!=NULL) {
  1624. *dstU = SourceAddressLength;
  1625. }
  1626. else {
  1627. status = STATUS_INSUFFICIENT_RESOURCES;
  1628. }
  1629. }
  1630. else {
  1631. status = STATUS_INSUFFICIENT_RESOURCES;
  1632. }
  1633. }
  1634. }
  1635. MmUnlockPages( addressMdl );
  1636. IoFreeMdl( addressMdl );
  1637. MmUnlockPages( addressLenMdl );
  1638. IoFreeMdl( addressLenMdl );
  1639. } else {
  1640. ASSERT( irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvAddressLenMdl == NULL );
  1641. }
  1642. if (irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl!=NULL) {
  1643. PMDL controlMdl = Irp->AfdRecvMsgControlMdl;
  1644. PMDL controlLenMdl = irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl;
  1645. Irp->AfdRecvMsgControlMdl = NULL;
  1646. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvControlLenMdl = NULL;
  1647. ASSERT( irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl != NULL );
  1648. ASSERT( ( controlLenMdl->MdlFlags & MDL_PAGES_LOCKED ) != 0 );
  1649. ASSERT( MmGetMdlByteCount (controlLenMdl) == sizeof (ULONG) );
  1650. //
  1651. // We still need to NULL the length even if no control data was delivered.
  1652. //
  1653. if (!NT_ERROR (status)) {
  1654. PULONG dstU;
  1655. dstU = MmGetSystemAddressForMdlSafe (controlLenMdl, LowPagePriority);
  1656. if (dstU!=NULL) {
  1657. if ((TdiReceiveFlags & TDI_RECEIVE_CONTROL_INFO)==0) {
  1658. ControlLength = 0;
  1659. }
  1660. #ifdef _WIN64
  1661. else if (IoIs32bitProcess (Irp)) {
  1662. ControlLength = AfdComputeCMSGLength32 (
  1663. ControlBuffer,
  1664. ControlLength);
  1665. }
  1666. #endif //_WIN64
  1667. *dstU = ControlLength;
  1668. }
  1669. else {
  1670. status = STATUS_INSUFFICIENT_RESOURCES;
  1671. }
  1672. }
  1673. //
  1674. // Ignore control data in case of error or if flag indicating
  1675. // that data is in proper format is not set.
  1676. //
  1677. if (!NT_ERROR (status) && ControlLength!=0) {
  1678. if (controlMdl==NULL) {
  1679. controlOverflow = TRUE;
  1680. status = STATUS_BUFFER_OVERFLOW;
  1681. }
  1682. else {
  1683. PVOID dst;
  1684. //
  1685. // Copy control info if app needs them (WSARecvMsg).
  1686. //
  1687. if (ControlLength>MmGetMdlByteCount (controlMdl)) {
  1688. ControlLength = MmGetMdlByteCount (controlMdl);
  1689. controlOverflow = TRUE;
  1690. status = STATUS_BUFFER_OVERFLOW;
  1691. }
  1692. dst = MmGetSystemAddressForMdlSafe (controlMdl, LowPagePriority);
  1693. if (dst!=NULL) {
  1694. #ifdef _WIN64
  1695. if (IoIs32bitProcess (Irp)) {
  1696. AfdCopyCMSGBuffer32 (dst, ControlBuffer, ControlLength);
  1697. }
  1698. else
  1699. #endif //_WIN64
  1700. {
  1701. RtlMoveMemory (dst, ControlBuffer, ControlLength);
  1702. }
  1703. }
  1704. else {
  1705. status = STATUS_INSUFFICIENT_RESOURCES;
  1706. }
  1707. }
  1708. }
  1709. if (controlMdl!=NULL) {
  1710. ASSERT( controlMdl->Next == NULL );
  1711. ASSERT( ( controlMdl->MdlFlags & MDL_PAGES_LOCKED ) != 0 );
  1712. ASSERT( MmGetMdlByteCount (controlMdl) > 0 );
  1713. MmUnlockPages (controlMdl);
  1714. IoFreeMdl (controlMdl);
  1715. }
  1716. MmUnlockPages (controlLenMdl);
  1717. IoFreeMdl (controlLenMdl);
  1718. }
  1719. else {
  1720. ASSERT (Irp->AfdRecvMsgControlMdl==NULL);
  1721. }
  1722. if (irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl!=NULL) {
  1723. PMDL flagsMdl = irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl;
  1724. irpSp->Parameters.AfdRecvDatagramInfo.AfdRecvFlagsMdl = NULL;
  1725. ASSERT( flagsMdl->Next == NULL );
  1726. ASSERT( ( flagsMdl->MdlFlags & MDL_PAGES_LOCKED ) != 0 );
  1727. ASSERT( MmGetMdlByteCount (flagsMdl)==sizeof (ULONG) );
  1728. if (!NT_ERROR (status)) {
  1729. PULONG dst;
  1730. dst = MmGetSystemAddressForMdlSafe (flagsMdl, LowPagePriority);
  1731. if (dst!=NULL) {
  1732. ULONG flags = 0;
  1733. if (TdiReceiveFlags & TDI_RECEIVE_BROADCAST)
  1734. flags |= MSG_BCAST;
  1735. if (TdiReceiveFlags & TDI_RECEIVE_MULTICAST)
  1736. flags |= MSG_MCAST;
  1737. if (dataOverflow)
  1738. flags |= MSG_TRUNC;
  1739. if (controlOverflow)
  1740. flags |= MSG_CTRUNC;
  1741. *dst = flags;
  1742. }
  1743. else {
  1744. status = STATUS_INSUFFICIENT_RESOURCES;
  1745. }
  1746. }
  1747. MmUnlockPages (flagsMdl);
  1748. IoFreeMdl (flagsMdl);
  1749. }
  1750. //
  1751. // Set up the IRP for completion.
  1752. //
  1753. Irp->IoStatus.Status = status;
  1754. return status;
  1755. } // AfdSetupReceiveDatagramIrp