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.

888 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. tdihdlr.c
  5. Abstract:
  6. This module implements the NT TDI event handler routines.
  7. Revision History:
  8. Balan Sethu Raman [SethuR] 15-Feb-1995
  9. Notes:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "tdikrnl.h"
  14. #include "rxtdip.h"
  15. //
  16. // The debug trace level
  17. //
  18. #define Dbg (DEBUG_TRACE_RXCETDI)
  19. extern
  20. NTSTATUS
  21. ReceiveEventHandler(
  22. IN BOOLEAN fExpedited,
  23. IN PRXCE_ADDRESS pAddress,
  24. IN PRXCE_VC pVc,
  25. IN ULONG ReceiveFlags,
  26. IN ULONG BytesIndicated,
  27. IN ULONG BytesAvailable,
  28. OUT ULONG *BytesTaken,
  29. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  30. OUT PIRP *pIrp // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  31. );
  32. extern NTSTATUS
  33. ReceiveEventPostProcessing(
  34. PRXCE_VC pVc,
  35. PRXCE_CONNECTION pConnection,
  36. PMDL pDataBuffer,
  37. ULONG DataBufferSize,
  38. PIRP *pIrpPointer);
  39. extern VOID
  40. ReceiveDatagramEventPostProcessing(
  41. PRXCE_ADDRESS pAddress,
  42. PMDL pDataBuffer,
  43. ULONG DataBufferSize,
  44. PIRP *pIrpPointer);
  45. NTSTATUS
  46. RxTdiConnectEventHandler(
  47. IN PVOID TdiEventContext,
  48. IN LONG RemoteAddressLength,
  49. IN PVOID RemoteAddress,
  50. IN LONG UserDataLength,
  51. IN PVOID UserData,
  52. IN LONG OptionsLength,
  53. IN PVOID Options,
  54. OUT CONNECTION_CONTEXT *ConnectionContext,
  55. OUT PIRP *AcceptIrp
  56. )
  57. /*++
  58. Routine Description:
  59. This routine is called when a connect request has completed. The connection
  60. is fully functional when the indication occurs.
  61. Arguments:
  62. TdiEventContext - the context value passed in by the user in the Set Event Handler call
  63. RemoteAddressLength,
  64. RemoteAddress,
  65. UserDataLength,
  66. UserData,
  67. OptionsLength,
  68. Options,
  69. ConnectionId
  70. Return Value:
  71. The function value is the final status from the initialization operation.
  72. --*/
  73. {
  74. UNREFERENCED_PARAMETER (TdiEventContext);
  75. UNREFERENCED_PARAMETER (RemoteAddressLength);
  76. UNREFERENCED_PARAMETER (RemoteAddress);
  77. UNREFERENCED_PARAMETER (UserDataLength);
  78. UNREFERENCED_PARAMETER (UserData);
  79. UNREFERENCED_PARAMETER (OptionsLength);
  80. UNREFERENCED_PARAMETER (Options);
  81. UNREFERENCED_PARAMETER (ConnectionContext);
  82. return STATUS_INSUFFICIENT_RESOURCES; // do nothing
  83. }
  84. NTSTATUS
  85. RxTdiDisconnectEventHandler(
  86. IN PVOID EventContext,
  87. IN CONNECTION_CONTEXT ConnectionContext,
  88. IN LONG DisconnectDataLength,
  89. IN PVOID DisconnectData,
  90. IN LONG DisconnectInformationLength,
  91. IN PVOID DisconnectInformation,
  92. IN ULONG DisconnectFlags
  93. )
  94. /*++
  95. Routine Description:
  96. This routine is used as the demultiplexing point for handling any
  97. connection disconnects for any address registered with the RxCe.
  98. Arguments:
  99. EventContext - the hAddress of the associated endpoint.
  100. ConnectionContext - the hVc associated with the connection.
  101. DisconnectIndicators - Value indicating reason for disconnection indication.
  102. Return Value:
  103. NTSTATUS - status of operation.
  104. --*/
  105. {
  106. NTSTATUS Status = STATUS_SUCCESS;
  107. PRXCE_VC pVc = (PRXCE_VC)ConnectionContext;
  108. PRXCE_ADDRESS pAddress = (PRXCE_ADDRESS)EventContext;
  109. PRXCE_TRANSPORT pTransport;
  110. PRXCE_CONNECTION pConnection;
  111. RxProfile(RxTdi,RxTdiDisconnectEventHandler);
  112. try {
  113. if (RxCeIsVcValid(pVc) &&
  114. (pVc->pConnection->pAddress == pAddress)) {
  115. pConnection = pVc->pConnection;
  116. ASSERT(RxCeIsConnectionValid(pConnection));
  117. if (
  118. // There is a event handler associated with this connection
  119. (pConnection->pHandler != NULL) &&
  120. // and the disconnect event handler has been specified
  121. (pConnection->pHandler->RxCeDisconnectEventHandler != NULL)) {
  122. Status = pConnection->pHandler->RxCeDisconnectEventHandler(
  123. pConnection->pContext,
  124. pVc,
  125. DisconnectDataLength,
  126. DisconnectData,
  127. DisconnectInformationLength,
  128. DisconnectInformation,
  129. DisconnectFlags);
  130. if (!NT_SUCCESS(Status)) {
  131. RxDbgTrace(0, Dbg, ("Disconnect event handler notification returned %lx\n",Status));
  132. }
  133. }
  134. // The final action irrespective of the action taken by the handlers specified.
  135. if (DisconnectFlags & TDI_DISCONNECT_RELEASE) {
  136. // The disconnect has to be confirmed.
  137. // Status = RxTdiDisconnect(
  138. // pTransport,
  139. // pAddress,
  140. // pConnection,
  141. // pVc,
  142. // RXCE_DISCONNECT_RELEASE);
  143. }
  144. // Mark the status of the local connection to prevent any subsequent sends
  145. // on this connection.
  146. InterlockedCompareExchange(
  147. &pVc->State,
  148. RXCE_VC_DISCONNECTED,
  149. RXCE_VC_ACTIVE);
  150. }
  151. } except(EXCEPTION_EXECUTE_HANDLER) {
  152. Status = STATUS_INVALID_PARAMETER;
  153. }
  154. return Status;
  155. }
  156. NTSTATUS
  157. RxTdiErrorEventHandler(
  158. IN PVOID TdiEventContext,
  159. IN NTSTATUS Status // status code indicating error type.
  160. )
  161. /*++
  162. Routine Description:
  163. This routine is used as the default error event handler for
  164. the transport endpoint. It is pointed to by a field in the
  165. TP_ENDPOINT structure for an endpoint when the endpoint is
  166. created, and also whenever the TdiSetEventHandler request is
  167. submitted with a NULL EventHandler field.
  168. Arguments:
  169. TransportEndpoint - Pointer to open file object.
  170. Status - Status code indicated by this event.
  171. Return Value:
  172. NTSTATUS - status of operation.
  173. --*/
  174. {
  175. UNREFERENCED_PARAMETER (TdiEventContext);
  176. UNREFERENCED_PARAMETER (Status);
  177. return STATUS_SUCCESS;
  178. }
  179. NTSTATUS
  180. RxTdiReceiveEventHandler(
  181. IN PVOID EventContext,
  182. IN CONNECTION_CONTEXT ConnectionContext,
  183. IN ULONG ReceiveFlags,
  184. IN ULONG BytesIndicated,
  185. IN ULONG BytesAvailable,
  186. OUT ULONG *BytesTaken,
  187. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  188. OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  189. )
  190. /*++
  191. Routine Description:
  192. This routine is used as the receive event handler for
  193. the transport endpoint.
  194. Arguments:
  195. EventContext - hAddresst.
  196. ConnectionContext - The client-supplied context associated with
  197. the connection on which this connection-oriented TSDU was received.
  198. ReceiveIndicators - Bitflags which indicate the circumstances surrounding
  199. this TSDU's reception.
  200. Tsdu - Pointer to an MDL chain that describes the (first) part of the
  201. (partially) received Transport Service Data Unit, less headers.
  202. IoRequestPacket - Pointer to a location where the event handler may
  203. chose to return a pointer to an I/O Request Packet (IRP) to satisfy
  204. the incoming data. If returned, this IRP must be formatted as a
  205. valid TdiReceive request, except that the ConnectionId field of
  206. the TdiRequest is ignored and is automatically filled in by the
  207. transport provider.
  208. Return Value:
  209. NTSTATUS - status of operation.
  210. --*/
  211. {
  212. return ReceiveEventHandler(
  213. FALSE, // regular receive
  214. (PRXCE_ADDRESS)EventContext,
  215. (PRXCE_VC)ConnectionContext,
  216. ReceiveFlags,
  217. BytesIndicated,
  218. BytesAvailable,
  219. BytesTaken,
  220. Tsdu,
  221. IoRequestPacket);
  222. }
  223. NTSTATUS
  224. RxTdiReceiveDatagramEventHandler(
  225. IN PVOID EventContext, // the event context
  226. IN LONG SourceAddressLength, // length of the originator of the datagram
  227. IN PVOID SourceAddress, // string describing the originator of the datagram
  228. IN LONG OptionsLength, // options for the receive
  229. IN PVOID Options, //
  230. IN ULONG ReceiveDatagramFlags, //
  231. IN ULONG BytesIndicated, // number of bytes this indication
  232. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  233. OUT ULONG *BytesTaken, // number of bytes used
  234. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  235. OUT PIRP *pIrp // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  236. )
  237. /*++
  238. Routine Description:
  239. This routine is used as the default receive datagram event
  240. handler for the transport endpoint. It is pointed to by a
  241. field in the TP_ENDPOINT structure for an endpoint when the
  242. endpoint is created, and also whenever the TdiSetEventHandler
  243. request is submitted with a NULL EventHandler field.
  244. Arguments:
  245. EventContext - event context ( hAddress )
  246. SourceAddress - Pointer to the network name of the source from which
  247. the datagram originated.
  248. Return Value:
  249. NTSTATUS - status of operation.
  250. --*/
  251. {
  252. NTSTATUS Status = STATUS_SUCCESS;
  253. PRXCE_ADDRESS pAddress = (PRXCE_ADDRESS)EventContext;
  254. PRXCE_TRANSPORT pTransport;
  255. PMDL pDataBuffer;
  256. ULONG DataBufferSize;
  257. RxProfile(RxTdi,RxCeReceiveDatagramEventHandler);
  258. ASSERT(RxCeIsAddressValid(pAddress));
  259. // Check if we have an event handler associated with this address
  260. if (
  261. // There is a event handler associated with this address
  262. (pAddress->pHandler != NULL)
  263. &&
  264. // and the expedited receive datagram handler has been specified
  265. (pAddress->pHandler->RxCeReceiveDatagramEventHandler != NULL)
  266. ) {
  267. Status = pAddress->pHandler->RxCeReceiveDatagramEventHandler(
  268. pAddress->pContext,
  269. SourceAddressLength,
  270. SourceAddress,
  271. OptionsLength,
  272. Options,
  273. ReceiveDatagramFlags,
  274. BytesIndicated,
  275. BytesAvailable,
  276. BytesTaken,
  277. Tsdu,
  278. &pDataBuffer,
  279. &DataBufferSize);
  280. switch (Status) {
  281. case STATUS_SUCCESS:
  282. case STATUS_DATA_NOT_ACCEPTED:
  283. break;
  284. case STATUS_MORE_PROCESSING_REQUIRED:
  285. ReceiveDatagramEventPostProcessing(
  286. pAddress,
  287. pDataBuffer,
  288. DataBufferSize,
  289. pIrp);
  290. break;
  291. default:
  292. // log the error.
  293. break;
  294. }
  295. } else {
  296. // No handler is associated. Take the default action.
  297. Status = STATUS_DATA_NOT_ACCEPTED;
  298. }
  299. return Status;
  300. }
  301. NTSTATUS
  302. RxTdiReceiveExpeditedEventHandler(
  303. IN PVOID EventContext,
  304. IN CONNECTION_CONTEXT ConnectionContext,
  305. IN ULONG ReceiveFlags, //
  306. IN ULONG BytesIndicated, // number of bytes in this indication
  307. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  308. OUT ULONG *BytesTaken, // number of bytes used by indication routine
  309. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  310. OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  311. )
  312. /*++
  313. Routine Description:
  314. Arguments:
  315. EventContext - the context value passed in by the user in the Set Event Handler call
  316. Return Value:
  317. The function value is the final status from the initialization operation.
  318. --*/
  319. {
  320. return ReceiveEventHandler(
  321. TRUE, // expedited receive
  322. (PRXCE_ADDRESS)EventContext,
  323. (PRXCE_VC)ConnectionContext,
  324. ReceiveFlags,
  325. BytesIndicated,
  326. BytesAvailable,
  327. BytesTaken,
  328. Tsdu,
  329. IoRequestPacket);
  330. }
  331. NTSTATUS
  332. RxTdiSendPossibleEventHandler (
  333. IN PVOID EventContext,
  334. IN PVOID ConnectionContext,
  335. IN ULONG BytesAvailable)
  336. /*++
  337. Routine Description:
  338. Arguments:
  339. EventContext - the context value passed in by the user in the Set Event Handler call
  340. ConnectionContext - connection context of connection which can be sent on
  341. BytesAvailable - number of bytes which can now be sent
  342. Return Value:
  343. ignored by the transport
  344. --*/
  345. {
  346. NTSTATUS Status = STATUS_SUCCESS;
  347. PRXCE_TRANSPORT pTransport;
  348. PRXCE_ADDRESS pAddress;
  349. PRXCE_VC pVc;
  350. PRXCE_CONNECTION pConnection;
  351. RxProfile(RxTdi,RxCeSendPossibleEventHandler);
  352. pVc = (PRXCE_VC)ConnectionContext;
  353. pConnection = pVc->pConnection;
  354. pAddress = pConnection->pAddress;
  355. pTransport = pAddress->pTransport;
  356. if (NT_SUCCESS(Status)) {
  357. // Check if we have an event handler associated with this connection.
  358. if (
  359. // There is a event handler associated with this connection
  360. (pConnection->pHandler != NULL)
  361. &&
  362. // and the expedited send possible event handler has been specified
  363. (pConnection->pHandler->RxCeSendPossibleEventHandler != NULL)
  364. ) {
  365. Status = pConnection->pHandler->RxCeSendPossibleEventHandler(
  366. pConnection->pContext,
  367. pVc,
  368. BytesAvailable);
  369. } else {
  370. // No handler is associated. Take the default action.
  371. Status = STATUS_SUCCESS;
  372. }
  373. }
  374. return Status;
  375. }
  376. NTSTATUS
  377. ReceiveEventHandler(
  378. IN BOOLEAN fExpedited,
  379. IN PRXCE_ADDRESS pAddress,
  380. IN PRXCE_VC pVc,
  381. IN ULONG ReceiveFlags,
  382. IN ULONG BytesIndicated,
  383. IN ULONG BytesAvailable,
  384. OUT ULONG *BytesTaken,
  385. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  386. OUT PIRP *pIrp // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  387. )
  388. /*++
  389. Routine Description:
  390. This routine is used as the receive event handler for
  391. the transport endpoint.
  392. Arguments:
  393. fExpedited - TRUE if it was a TDI_EXPEDITED_RECEIVE event
  394. EventContext - hAddress.
  395. ConnectionContext - The client-supplied context associated with
  396. the connection on which this connection-oriented TSDU was received.
  397. ReceiveIndicators - Bitflags which indicate the circumstances surrounding
  398. this TSDU's reception.
  399. Tsdu - Pointer to an MDL chain that describes the (first) part of the
  400. (partially) received Transport Service Data Unit, less headers.
  401. IoRequestPacket - Pointer to a location where the event handler may
  402. chose to return a pointer to an I/O Request Packet (IRP) to satisfy
  403. the incoming data. If returned, this IRP must be formatted as a
  404. valid TdiReceive request, except that the ConnectionId field of
  405. the TdiRequest is ignored and is automatically filled in by the
  406. transport provider.
  407. Return Value:
  408. NTSTATUS - status of operation.
  409. --*/
  410. {
  411. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  412. PMDL pDataBuffer = NULL;
  413. ULONG DataBufferSize;
  414. PRXCE_CONNECTION pConnection;
  415. RxProfile(RxTdi,ReceiveEventHandler);
  416. ASSERT(RxCeIsVcValid(pVc));
  417. if (ReceiveFlags & TDI_RECEIVE_PARTIAL) {
  418. // Stream mode transports always set this flag. They need to be handled in a
  419. // different way. The clients of RxCe need only be notified when we have
  420. // receieved a complete TSDU.
  421. Status = STATUS_DATA_NOT_ACCEPTED;
  422. } else {
  423. pConnection = pVc->pConnection;
  424. ASSERT(RxCeIsConnectionValid(pConnection));
  425. // Check if we have an event handler associated with this connection.
  426. if (
  427. // There is a event handler associated with this connection
  428. (pConnection->pHandler != NULL)
  429. ) {
  430. if (fExpedited) { // Expedited receive
  431. // and the expedited receive event handler has been specified
  432. if (pConnection->pHandler->RxCeReceiveExpeditedEventHandler != NULL) {
  433. Status = pConnection->pHandler->RxCeReceiveExpeditedEventHandler(
  434. pConnection->pContext,
  435. pVc,
  436. ReceiveFlags,
  437. BytesIndicated,
  438. BytesAvailable,
  439. BytesTaken,
  440. Tsdu,
  441. &pDataBuffer,
  442. &DataBufferSize);
  443. }
  444. } else if (pConnection->pHandler->RxCeReceiveEventHandler != NULL) {
  445. Status = pConnection->pHandler->RxCeReceiveEventHandler(
  446. pConnection->pContext,
  447. pVc,
  448. ReceiveFlags,
  449. BytesIndicated,
  450. BytesAvailable,
  451. BytesTaken,
  452. Tsdu,
  453. &pDataBuffer,
  454. &DataBufferSize);
  455. }
  456. switch (Status) {
  457. case STATUS_SUCCESS:
  458. case STATUS_DATA_NOT_ACCEPTED:
  459. break;
  460. case STATUS_MORE_PROCESSING_REQUIRED:
  461. {
  462. Status = ReceiveEventPostProcessing(
  463. pVc,
  464. pConnection,
  465. pDataBuffer,
  466. DataBufferSize,
  467. pIrp);
  468. }
  469. break;
  470. default:
  471. RxDbgTrace(0, Dbg, ("Receive Event Notification returned %lx\n",Status));
  472. break;
  473. }
  474. }
  475. }
  476. return Status;
  477. }
  478. NTSTATUS
  479. RxTdiReceiveCompletion(
  480. PDEVICE_OBJECT pDeviceObject,
  481. PIRP pIrp,
  482. PVOID pContext)
  483. /*++
  484. Routine Description:
  485. This routine is invoked upon completion of the reception of the desired amount of
  486. data.
  487. Arguments:
  488. pDeviceObject - the device object
  489. pIrp - the IRP
  490. pContext - the connection handle
  491. --*/
  492. {
  493. PRXCE_VC pVc = (PRXCE_VC)pContext;
  494. if (pVc != NULL) {
  495. NTSTATUS Status;
  496. ULONG BytesCopied = (ULONG)pIrp->IoStatus.Information;
  497. PRXCE_CONNECTION pConnection = pVc->pConnection;
  498. ASSERT(
  499. RxCeIsVcValid(pVc) &&
  500. RxCeIsConnectionValid(pConnection));
  501. if (pConnection->pHandler->RxCeDataReadyEventHandler != NULL) {
  502. Status = pConnection->pHandler->RxCeDataReadyEventHandler(
  503. pConnection->pContext,
  504. pVc->pReceiveMdl,
  505. BytesCopied,
  506. pIrp->IoStatus.Status);
  507. }
  508. pVc->pReceiveMdl = NULL;
  509. } else {
  510. ASSERT(!"Valid connection handle for receive completion");
  511. }
  512. RxCeFreeIrp(pIrp);
  513. //
  514. // Return STATUS_MORE_PROCESSING_REQUIRED so that IoCompleteRequest
  515. // will stop working on the IRP.
  516. //
  517. return STATUS_MORE_PROCESSING_REQUIRED;
  518. }
  519. NTSTATUS
  520. ReceiveEventPostProcessing(
  521. PRXCE_VC pVc,
  522. PRXCE_CONNECTION pConnection,
  523. PMDL pDataMdl,
  524. ULONG DataBufferSize,
  525. PIRP *pIrpPointer)
  526. /*++
  527. Routine Description:
  528. This routine is invoked when a recieve event notification to a connection engine client
  529. results in further requests for copying the data out of the transport drivers buffers
  530. Arguments:
  531. pDataBuffer - the buffer into which the data should be copied
  532. DataBufferSize - the size of the data
  533. pIrpPointer - the IRP to the transport driver for processing the copy request.
  534. Return Value:
  535. STATUS_MORE_PROCESSING_REQUIRED -- if successful
  536. otherwise appropriate error code
  537. --*/
  538. {
  539. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  540. PRXCE_ADDRESS pAddress = pConnection->pAddress;
  541. PRXCE_TRANSPORT pTransport = pAddress->pTransport;
  542. PIRP pIrp;
  543. ASSERT(RxCeIsAddressValid(pAddress));
  544. ASSERT(RxCeIsTransportValid(pTransport));
  545. ASSERT(pConnection->pHandler->RxCeDataReadyEventHandler != NULL);
  546. pIrp = RxCeAllocateIrpWithMDL(pTransport->pDeviceObject->StackSize,FALSE,pDataMdl);
  547. *pIrpPointer = pIrp;
  548. if (pIrp != NULL) {
  549. pVc->pReceiveMdl = pDataMdl;
  550. TdiBuildReceive(
  551. pIrp, // the IRP
  552. pTransport->pDeviceObject, // the device object
  553. pVc->pEndpointFileObject, // the connection (VC) file object
  554. RxTdiReceiveCompletion, // Completion routine
  555. pVc, // completion context
  556. pDataMdl, // the data buffer
  557. 0, // receive flags
  558. DataBufferSize); // receive buffer length
  559. //
  560. // Make the next stack location current. Normally IoCallDriver would
  561. // do this, but for this IRP it has been bypassed.
  562. //
  563. IoSetNextIrpStackLocation(pIrp);
  564. } else {
  565. // An IRP for receiving the data was not allocated. Invoke the error handler
  566. // to communicate the status back.
  567. ASSERT(pConnection->pHandler->RxCeDataReadyEventHandler != NULL);
  568. if (pConnection->pHandler->RxCeDataReadyEventHandler != NULL) {
  569. Status = pConnection->pHandler->RxCeDataReadyEventHandler(
  570. pConnection->pContext,
  571. pDataMdl,
  572. 0,
  573. STATUS_INSUFFICIENT_RESOURCES);
  574. }
  575. Status = STATUS_DATA_NOT_ACCEPTED;
  576. }
  577. return Status;
  578. }
  579. NTSTATUS
  580. RxTdiReceiveDatagramCompletion(
  581. PDEVICE_OBJECT pDeviceObject,
  582. PIRP pIrp,
  583. PVOID pContext)
  584. /*++
  585. Routine Description:
  586. This routine is invoked upon completion of the reception of the desired amount of
  587. data.
  588. Arguments:
  589. pDeviceObject - the device object
  590. pIrp - the IRP
  591. pContext - the connection handle
  592. --*/
  593. {
  594. NTSTATUS Status;
  595. PRXCE_ADDRESS pAddress = (PRXCE_ADDRESS)pContext;
  596. ASSERT(RxCeIsAddressValid(pAddress));
  597. if (pAddress != NULL) {
  598. ULONG BytesCopied = (ULONG)pIrp->IoStatus.Information;
  599. if (pAddress->pHandler->RxCeDataReadyEventHandler != NULL) {
  600. Status = pAddress->pHandler->RxCeDataReadyEventHandler(
  601. pAddress->pContext,
  602. pAddress->pReceiveMdl,
  603. BytesCopied,
  604. pIrp->IoStatus.Status);
  605. }
  606. pAddress->pReceiveMdl = NULL;
  607. } else {
  608. ASSERT(!"Valid Address handle for receive datagram completion");
  609. }
  610. RxCeFreeIrp(pIrp);
  611. //
  612. // Return STATUS_MORE_PROCESSING_REQUIRED so that IoCompleteRequest
  613. // will stop working on the IRP.
  614. //
  615. return STATUS_MORE_PROCESSING_REQUIRED;
  616. }
  617. VOID
  618. ReceiveDatagramEventPostProcessing(
  619. PRXCE_ADDRESS pAddress,
  620. PMDL pDataMdl,
  621. ULONG DataBufferSize,
  622. PIRP *pIrpPointer)
  623. /*++
  624. Routine Description:
  625. This routine is invoked when a recieve event notification to a connection engine client
  626. results in further requests for copying the data out of the transport drivers buffers
  627. Arguments:
  628. pDataBuffer - the buffer into which the data should be copied
  629. DataBufferSize - the size of the data
  630. pIrpPointer - the IRP to the transport driver for processing the copy request.
  631. Return Value:
  632. a STATUS_SUCCESS returned from this routine only implies that an IRP for processing
  633. the request was setup correctly.
  634. --*/
  635. {
  636. PIRP pIrp;
  637. PRXCE_TRANSPORT pTransport = pAddress->pTransport;
  638. ASSERT(RxCeIsTransportValid(pTransport));
  639. ASSERT(pAddress->pHandler->RxCeDataReadyEventHandler != NULL);
  640. *pIrpPointer = pIrp = RxCeAllocateIrp(pTransport->pDeviceObject->StackSize,FALSE);
  641. if (pIrp != NULL) {
  642. pAddress->pReceiveMdl = pDataMdl;
  643. TdiBuildReceive(
  644. pIrp, // the IRP
  645. pTransport->pDeviceObject, // the device object
  646. pAddress->pFileObject, // the connection (VC) file object
  647. RxTdiReceiveDatagramCompletion, // Completion routine
  648. pAddress, // completion context
  649. pDataMdl, // the data buffer
  650. 0, // send flags
  651. DataBufferSize); // send buffer length
  652. //
  653. // Make the next stack location current. Normally IoCallDriver would
  654. // do this, but for this IRP it has been bypassed.
  655. //
  656. IoSetNextIrpStackLocation(pIrp);
  657. } else {
  658. // An IRP for receiving the data was not allocated. Invoke the error handler
  659. // to communicate the status back.
  660. if (pAddress->pHandler->RxCeErrorEventHandler != NULL) {
  661. pAddress->pHandler->RxCeErrorEventHandler(
  662. pAddress->pContext,
  663. STATUS_INSUFFICIENT_RESOURCES);
  664. } else {
  665. // No error handler to handle an erroneous situation.
  666. }
  667. }
  668. }