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.

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