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.

2528 lines
52 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. D:\nt\private\ntos\tdi\rawwan\core\ndisconn.c
  5. Abstract:
  6. NDIS Entry points and support routines for Connection setup and
  7. release.
  8. Revision History:
  9. Who When What
  10. -------- -------- ----------------------------------------------
  11. arvindm 05-06-97 Created
  12. Notes:
  13. Code under ifndef NO_POST_DISCON: Nov 17, 98
  14. Added code to send a TDI DisconInd to AFD before completing
  15. a TDI Disconnect Request that AFD had sent to us. Without this,
  16. if an app calls shutdown(SD_SEND) -> TDI Disconnect Request,
  17. a subsequent call by the app to recv() blocks forever, because
  18. AFD expects the TDI transport to send up a TDI DisconInd!
  19. --*/
  20. #include <precomp.h>
  21. #define _FILENUMBER 'NCDN'
  22. NDIS_STATUS
  23. RWanNdisCreateVc(
  24. IN NDIS_HANDLE ProtocolAfContext,
  25. IN NDIS_HANDLE NdisVcHandle,
  26. OUT PNDIS_HANDLE pProtocolVcContext
  27. )
  28. /*++
  29. Routine Description:
  30. This is the NDIS entry point for creating a new endpoint (VC).
  31. We allocate a new NDIS_VC structure and return a pointer to it
  32. as our context for the VC.
  33. Arguments:
  34. ProtocolAfContext - Pointer to our NDIS AF block
  35. NdisVcHandle - Handle for the newly created VC
  36. pProtocolVcContext - Place where we return our context for the VC
  37. Return Value:
  38. NDIS_STATUS_SUCCESS if we could allocate a VC,
  39. NDIS_STATUS_RESOURCES otherwise.
  40. --*/
  41. {
  42. PRWAN_NDIS_AF pAf;
  43. PRWAN_NDIS_VC pVc;
  44. NDIS_STATUS Status;
  45. pAf = (PRWAN_NDIS_AF)ProtocolAfContext;
  46. RWAN_STRUCT_ASSERT(pAf, naf);
  47. do
  48. {
  49. pVc = RWanAllocateVc(pAf, FALSE);
  50. if (pVc == NULL_PRWAN_NDIS_VC)
  51. {
  52. Status = NDIS_STATUS_RESOURCES;
  53. break;
  54. }
  55. pVc->NdisVcHandle = NdisVcHandle;
  56. RWANDEBUGP(DL_EXTRA_LOUD, DC_CONNECT,
  57. ("CreateVc: pVc x%x, pAf x%x\n", pVc, pAf));
  58. Status = NDIS_STATUS_SUCCESS;
  59. break;
  60. }
  61. while (FALSE);
  62. *pProtocolVcContext = (NDIS_HANDLE)pVc;
  63. return (Status);
  64. }
  65. NDIS_STATUS
  66. RWanNdisDeleteVc(
  67. IN NDIS_HANDLE ProtocolVcContext
  68. )
  69. /*++
  70. Routine Description:
  71. This entry point is called by NDIS to delete a VC context
  72. used for an incoming call. At this time, there should be
  73. no call on the VC. All we need to do is unlink the VC from
  74. the list it belongs to, and free it.
  75. Arguments:
  76. ProtocolVcContext - Points to our VC context.
  77. Return Value:
  78. NDIS_STATUS_SUCCESS always.
  79. --*/
  80. {
  81. PRWAN_NDIS_VC pVc;
  82. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  83. RWAN_STRUCT_ASSERT(pVc, nvc);
  84. RWAN_ASSERT(pVc->pConnObject == NULL_PRWAN_TDI_CONNECTION);
  85. RWANDEBUGP(DL_EXTRA_LOUD, DC_DISCON,
  86. ("DeleteVc: pVc x%x, pAf x%x\n", pVc, pVc->pNdisAf));
  87. //
  88. // Unlink the VC from the list of VCs on the AF block
  89. //
  90. RWanUnlinkVcFromAf(pVc);
  91. RWanFreeVc(pVc);
  92. return (NDIS_STATUS_SUCCESS);
  93. }
  94. VOID
  95. RWanNdisMakeCallComplete(
  96. IN NDIS_STATUS Status,
  97. IN NDIS_HANDLE ProtocolVcContext,
  98. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  99. IN PCO_CALL_PARAMETERS pCallParameters
  100. )
  101. /*++
  102. Routine Description:
  103. This is the NDIS entry point that is called when a previous
  104. call we made to NdisClMakeCall has completed.
  105. We locate the TDI Connection Object for this call. If the
  106. user hasn't aborted the Connect/JoinLeaf, we complete the
  107. pended request. Otherwise, we initiate a CloseCall.
  108. This primitive can happen only when the endpoint is in
  109. the "Out call initiated" state.
  110. Arguments:
  111. Status - Final status of the MakeCall
  112. ProtocolVcContext - Actually a pointer to our NDIS VC structure
  113. NdisPartyHandle - If this is a PMP call, this is the handle to the
  114. first party
  115. pCallParameters - Final call parameters.
  116. Return Value:
  117. None
  118. --*/
  119. {
  120. PRWAN_TDI_CONNECTION pRootConnObject;
  121. PRWAN_TDI_CONNECTION pConnObject;
  122. PRWAN_TDI_ADDRESS pAddrObject;
  123. NDIS_HANDLE NdisVcHandle;
  124. TDI_STATUS TdiStatus;
  125. PRWAN_CONN_REQUEST pConnReq; // Saved context about the TdiConnect
  126. BOOLEAN bIsConnClosing; // Have we seen a TdiCloseConnection?
  127. PRWAN_NDIS_AF pAf;
  128. PRWAN_NDIS_VC pVc;
  129. PRWAN_NDIS_PARTY pParty;
  130. PCO_CALL_PARAMETERS pOriginalParams;// What we used in the MakeCall
  131. RWAN_HANDLE AfSpConnContext;
  132. #if DBG
  133. RWAN_IRQL EntryIrq, ExitIrq;
  134. #endif // DBG
  135. RWAN_GET_ENTRY_IRQL(EntryIrq);
  136. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  137. RWAN_STRUCT_ASSERT(pVc, nvc);
  138. //
  139. // Check if this is a point-to-multipoint call.
  140. //
  141. if (!RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_PMP))
  142. {
  143. //
  144. // Point-to-point call.
  145. //
  146. pConnObject = pVc->pConnObject;
  147. pRootConnObject = pConnObject; // for consistency.
  148. pParty = NULL;
  149. pOriginalParams = pVc->pCallParameters;
  150. }
  151. else
  152. {
  153. //
  154. // PMP Call. Get at the Party structure.
  155. //
  156. pParty = pVc->pPartyMakeCall;
  157. RWAN_STRUCT_ASSERT(pParty, npy);
  158. pConnObject = pParty->pConnObject;
  159. pRootConnObject = pVc->pConnObject;
  160. pOriginalParams = pParty->pCallParameters;
  161. }
  162. RWAN_ASSERT(pOriginalParams != NULL);
  163. pAf = pVc->pNdisAf;
  164. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  165. ("MakeCallComplete: pConn x%x, State/Flags/Ref x%x/x%x/%d, pAddr %x, pVc x%x, Status x%x\n",
  166. pConnObject, pConnObject->State, pConnObject->Flags, pConnObject->RefCount, pConnObject->pAddrObject, pVc, Status));
  167. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  168. RWAN_ASSERT(pConnObject->State == RWANS_CO_OUT_CALL_INITIATED ||
  169. pConnObject->State == RWANS_CO_DISCON_REQUESTED);
  170. //
  171. // Has the user initiated a TdiCloseConnection() or a TdiDisconnect()
  172. // while this outgoing call was in progress?
  173. //
  174. bIsConnClosing = RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING) ||
  175. (pConnObject->State == RWANS_CO_DISCON_REQUESTED);
  176. //
  177. // We would have saved context about the TdiConnect(). Get it.
  178. //
  179. pConnReq = pConnObject->pConnReq;
  180. pConnObject->pConnReq = NULL;
  181. if (pParty)
  182. {
  183. pVc->AddingPartyCount --;
  184. pParty->pCallParameters = NULL;
  185. pParty->NdisPartyHandle = NdisPartyHandle;
  186. }
  187. else
  188. {
  189. pVc->pCallParameters = NULL;
  190. }
  191. if (Status == NDIS_STATUS_SUCCESS)
  192. {
  193. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_MAKECALL_OK);
  194. if (!bIsConnClosing)
  195. {
  196. //
  197. // Outgoing connection successfully set up.
  198. //
  199. pConnObject->State = RWANS_CO_CONNECTED;
  200. //
  201. // Update PMP information.
  202. //
  203. if (pParty)
  204. {
  205. pVc->ActivePartyCount ++; // MakeCall PMP complete
  206. pRootConnObject->State = RWANS_CO_CONNECTED;
  207. }
  208. AfSpConnContext = pConnObject->AfSpConnContext;
  209. RWAN_RELEASE_CONN_LOCK(pConnObject);
  210. RWanCompleteConnReq( // MakeCall OK
  211. pAf,
  212. pConnReq,
  213. TRUE,
  214. pCallParameters,
  215. AfSpConnContext,
  216. TDI_SUCCESS
  217. );
  218. }
  219. else
  220. {
  221. //
  222. // Abort this call.
  223. //
  224. pConnObject->State = RWANS_CO_ABORTING;
  225. RWanStartCloseCall(pConnObject, pVc);
  226. }
  227. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  228. }
  229. else
  230. {
  231. //
  232. // MakeCall failed.
  233. //
  234. INT rc;
  235. //
  236. // XXX TBD : how about trying this call on another NDIS AF?
  237. //
  238. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_MAKECALL_FAIL);
  239. if (pParty == NULL)
  240. {
  241. //
  242. // Point-to-Point call.
  243. //
  244. //
  245. // Unlink the NDIS VC from this Conn Object.
  246. //
  247. RWAN_UNLINK_CONNECTION_AND_VC(pConnObject, pVc); // MakeCall fail
  248. }
  249. else
  250. {
  251. //
  252. // PMP Call. The VC would be attached to the Root
  253. // Connection Object. Unlink the VC and the Root Connection.
  254. //
  255. RWAN_ACQUIRE_CONN_LOCK(pRootConnObject);
  256. RWAN_UNLINK_CONNECTION_AND_VC(pRootConnObject, pVc); // MakeCallPMP fail
  257. rc = RWanDereferenceConnObject(pRootConnObject); // VC deref: MakeCallPMP fail
  258. if (rc > 0)
  259. {
  260. RWAN_RELEASE_CONN_LOCK(pRootConnObject);
  261. }
  262. //
  263. // Unlink the Party from the Connection and VC.
  264. //
  265. RWAN_DELETE_FROM_LIST(&(pParty->PartyLink));
  266. pParty->pVc = NULL;
  267. pParty->pConnObject = NULL;
  268. pConnObject->NdisConnection.pNdisParty = NULL;
  269. }
  270. rc = RWanDereferenceConnObject(pConnObject); // VC/Pty deref: MakeCall fail
  271. //
  272. // Continue with the Connection Object for this MakeCall,
  273. // if it is still alive.
  274. //
  275. if (rc > 0)
  276. {
  277. if (pConnObject->pAddrObject != NULL)
  278. {
  279. //
  280. // Move the Connection Object to the Idle list.
  281. //
  282. pAddrObject = pConnObject->pAddrObject;
  283. //
  284. // Reacquire some locks in the right order.
  285. //
  286. RWAN_RELEASE_CONN_LOCK(pConnObject);
  287. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  288. RWAN_ACQUIRE_CONN_LOCK_DPC(pConnObject);
  289. //
  290. // Move this Connection to the Idle list.
  291. //
  292. RWAN_DELETE_FROM_LIST(&(pConnObject->ConnLink));
  293. RWAN_INSERT_TAIL_LIST(&(pAddrObject->IdleConnList),
  294. &(pConnObject->ConnLink));
  295. //
  296. // Send this back to the state it was in before the TdiConnect.
  297. //
  298. pConnObject->State = RWANS_CO_ASSOCIATED;
  299. AfSpConnContext = pConnObject->AfSpConnContext;
  300. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  301. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  302. //
  303. // Complete the TdiConnect() with a failure status.
  304. //
  305. TdiStatus = RWanNdisToTdiStatus(Status);
  306. if (TdiStatus == TDI_NOT_ACCEPTED)
  307. {
  308. TdiStatus = TDI_CONN_REFUSED;
  309. }
  310. RWanCompleteConnReq( // MakeCall Fail
  311. pAf,
  312. pConnReq,
  313. TRUE,
  314. NULL,
  315. AfSpConnContext,
  316. TdiStatus
  317. );
  318. }
  319. else
  320. {
  321. RWAN_RELEASE_CONN_LOCK(pConnObject);
  322. }
  323. }
  324. //
  325. // else the Conn Object is gone. A TdiCloseConnection might be
  326. // (must be?) in progress.
  327. //
  328. #if 1
  329. // XXX: Remove this after debugging.
  330. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  331. RWAN_STRUCT_ASSERT(pVc, nvc);
  332. #endif // 1
  333. NdisVcHandle = pVc->NdisVcHandle;
  334. //
  335. // Unlink the VC from the AF it is attached to.
  336. //
  337. RWanUnlinkVcFromAf(pVc);
  338. //
  339. // Get rid of the VC.
  340. //
  341. Status = NdisCoDeleteVc(NdisVcHandle);
  342. RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
  343. RWanFreeVc(pVc); // MakeCall complete fail
  344. if (pParty != NULL)
  345. {
  346. RWAN_FREE_MEM(pParty); // MakeCall complete fail
  347. }
  348. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  349. }
  350. //
  351. // Return the Call Parameters structure to the AF-specific module.
  352. //
  353. (*pAf->pAfInfo->AfChars.pAfSpReturnNdisOptions)(
  354. pAf->AfSpAFContext,
  355. pOriginalParams
  356. );
  357. return;
  358. }
  359. VOID
  360. RWanNdisAddPartyComplete(
  361. IN NDIS_STATUS Status,
  362. IN NDIS_HANDLE ProtocolPartyContext,
  363. IN NDIS_HANDLE NdisPartyHandle,
  364. IN PCO_CALL_PARAMETERS pCallParameters
  365. )
  366. /*++
  367. Routine Description:
  368. This is the NDIS entry indicating completion of a call to NdisClAddParty
  369. that had pended.
  370. Arguments:
  371. Status - Final status of the AddParty
  372. ProtocolPartyContext- Actually a pointer to our NDIS PARTY structure
  373. NdisPartyHandle - If the AddParty was successful, an NDIS handle for it
  374. pCallParameters - Final parameters after the AddParty
  375. Return Value:
  376. None
  377. --*/
  378. {
  379. PRWAN_NDIS_PARTY pParty;
  380. PRWAN_TDI_CONNECTION pConnObject;
  381. PRWAN_TDI_ADDRESS pAddrObject;
  382. PRWAN_CONN_REQUEST pConnReq;
  383. PRWAN_NDIS_AF pAf;
  384. PRWAN_NDIS_VC pVc;
  385. PCO_CALL_PARAMETERS pOriginalParams; // what was used in the AddParty
  386. TDI_STATUS TdiStatus;
  387. BOOLEAN bIsConnClosing;
  388. RWAN_HANDLE AfSpConnContext;
  389. #if DBG
  390. RWAN_IRQL EntryIrq, ExitIrq;
  391. #endif // DBG
  392. RWAN_GET_ENTRY_IRQL(EntryIrq);
  393. pParty = (PRWAN_NDIS_PARTY)ProtocolPartyContext;
  394. RWAN_STRUCT_ASSERT(pParty, npy);
  395. pVc = pParty->pVc;
  396. RWAN_STRUCT_ASSERT(pVc, nvc);
  397. pAf = pVc->pNdisAf;
  398. pConnObject = pParty->pConnObject;
  399. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  400. pOriginalParams = pParty->pCallParameters;
  401. RWAN_ASSERT(pOriginalParams != NULL);
  402. pParty->pCallParameters = NULL;
  403. RWAN_ASSERT(pConnObject->State == RWANS_CO_OUT_CALL_INITIATED ||
  404. pConnObject->State == RWANS_CO_DISCON_REQUESTED);
  405. //
  406. // Has the user initiated a TdiCloseConnection() or a TdiDisconnect()
  407. // while this outgoing call was in progress?
  408. //
  409. bIsConnClosing = RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING) ||
  410. (pConnObject->State == RWANS_CO_DISCON_REQUESTED);
  411. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  412. ("AddPartyComplete: pConn x%x, State/Flags x%x/x%x, pVc x%x, Pty x%x, Status x%x\n",
  413. pConnObject, pConnObject->State, pConnObject->Flags, pVc, pParty, Status));
  414. //
  415. // We would have saved context about the TdiConnect(). Get it.
  416. //
  417. pConnReq = pConnObject->pConnReq;
  418. pConnObject->pConnReq = NULL;
  419. pVc->AddingPartyCount --;
  420. if (Status == NDIS_STATUS_SUCCESS)
  421. {
  422. pParty->NdisPartyHandle = NdisPartyHandle;
  423. pConnObject->State = RWANS_CO_CONNECTED;
  424. //
  425. // Outgoing party successfully set up.
  426. //
  427. pVc->ActivePartyCount ++; // AddParty OK
  428. if (!bIsConnClosing)
  429. {
  430. AfSpConnContext = pConnObject->AfSpConnContext;
  431. RWAN_RELEASE_CONN_LOCK(pConnObject);
  432. RWanCompleteConnReq( // AddParty OK
  433. pAf,
  434. pConnReq,
  435. TRUE,
  436. pCallParameters,
  437. AfSpConnContext,
  438. TDI_SUCCESS
  439. );
  440. }
  441. else
  442. {
  443. //
  444. // Abort this Party.
  445. //
  446. RWanDoTdiDisconnect(
  447. pConnObject,
  448. NULL, // pTdiRequest
  449. NULL, // pTimeout
  450. 0, // Flags
  451. NULL, // pDisconnInfo
  452. NULL // pReturnInfo
  453. );
  454. //
  455. // Conn Object lock is released above.
  456. //
  457. }
  458. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  459. }
  460. else
  461. {
  462. //
  463. // AddParty failed.
  464. //
  465. INT rc;
  466. //
  467. // Unlink the Party from the VC.
  468. //
  469. RWAN_DELETE_FROM_LIST(&(pParty->PartyLink));
  470. pAddrObject = pConnObject->pAddrObject;
  471. rc = RWanDereferenceConnObject(pConnObject); // Party deref: AddParty fail
  472. if (rc > 0)
  473. {
  474. //
  475. // Reacquire some locks in the right order.
  476. //
  477. RWAN_RELEASE_CONN_LOCK(pConnObject);
  478. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  479. RWAN_ACQUIRE_CONN_LOCK_DPC(pConnObject);
  480. //
  481. // Move this Connection to the Idle list.
  482. //
  483. RWAN_DELETE_FROM_LIST(&(pConnObject->ConnLink));
  484. RWAN_INSERT_TAIL_LIST(&(pAddrObject->IdleConnList),
  485. &(pConnObject->ConnLink));
  486. //
  487. // Send this back to the state it was in before the TdiConnect.
  488. //
  489. pConnObject->State = RWANS_CO_ASSOCIATED;
  490. AfSpConnContext = pConnObject->AfSpConnContext;
  491. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  492. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  493. //
  494. // Complete the TdiConnect() with a failure status.
  495. //
  496. TdiStatus = RWanNdisToTdiStatus(Status);
  497. if (TdiStatus == TDI_NOT_ACCEPTED)
  498. {
  499. TdiStatus = TDI_CONN_REFUSED;
  500. }
  501. RWanCompleteConnReq( // JoinLeaf Fail
  502. pAf,
  503. pConnReq,
  504. TRUE,
  505. NULL,
  506. AfSpConnContext,
  507. TdiStatus
  508. );
  509. }
  510. //
  511. // else the ConnObject is gone.
  512. //
  513. RWAN_FREE_MEM(pParty); // AddParty fail
  514. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  515. }
  516. //
  517. // Return the Call Parameters structure to the AF-specific module.
  518. //
  519. (*pAf->pAfInfo->AfChars.pAfSpReturnNdisOptions)(
  520. pAf->AfSpAFContext,
  521. pOriginalParams
  522. );
  523. return;
  524. }
  525. NDIS_STATUS
  526. RWanNdisIncomingCall(
  527. IN NDIS_HANDLE ProtocolSapContext,
  528. IN NDIS_HANDLE ProtocolVcContext,
  529. IN OUT PCO_CALL_PARAMETERS pCallParameters
  530. )
  531. /*++
  532. Routine Description:
  533. This is the NDIS entry point announcing a new Incoming call request,
  534. on the specified SAP.
  535. The SAP corresponds to an Address Object. If there are no Listens posted
  536. on the Address object, we reject this call. Otherwise, we pick up an
  537. arbitrary listening connection object and indicate this call on that.
  538. TBD: support selection of listening conn object based on specified
  539. remote criteria.
  540. Arguments:
  541. ProtocolSapContext - Our SAP context is a pointer to an NDIS SAP structure
  542. ProtocolVcContext - Actually a pointer to our NDIS VC structure
  543. pCallParameters - Points to Incoming call parameters.
  544. Return Value:
  545. None
  546. --*/
  547. {
  548. PRWAN_NDIS_SAP pSap;
  549. PRWAN_NDIS_VC pVc;
  550. PRWAN_NDIS_AF pAf;
  551. PRWAN_TDI_ADDRESS pAddrObject;
  552. BOOLEAN IsAddrLockAcquired;
  553. PRWAN_TDI_CONNECTION pConnObject;
  554. PLIST_ENTRY pConnEntry;
  555. NDIS_STATUS Status;
  556. TDI_STATUS TdiStatus;
  557. RWAN_STATUS RWanStatus;
  558. PRWAN_CONN_REQUEST pConnReq;
  559. PConnectEvent pConnInd;
  560. PTDI_CONNECTION_INFORMATION pTdiInfo;
  561. RWAN_HANDLE AfSpTdiOptionsContext;
  562. PVOID pTdiQoS;
  563. ULONG TdiQoSLength;
  564. PVOID ConnIndContext;
  565. PVOID AcceptConnContext;
  566. RWAN_HANDLE AfSpConnContext;
  567. #ifdef NT
  568. PIO_STACK_LOCATION pIrpSp;
  569. PTDI_REQUEST_KERNEL_ACCEPT pAcceptReq;
  570. ConnectEventInfo *EventInfo;
  571. #else
  572. ConnectEventInfo EventInfo;
  573. #endif // NT
  574. pSap = (PRWAN_NDIS_SAP)ProtocolSapContext;
  575. RWAN_STRUCT_ASSERT(pSap, nsp);
  576. pAddrObject = pSap->pAddrObject;
  577. RWAN_ASSERT(pAddrObject != NULL);
  578. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  579. RWAN_STRUCT_ASSERT(pVc, nvc);
  580. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_INCALL);
  581. pAf = pVc->pNdisAf;
  582. RWANDEBUGP(DL_INFO, DC_CONNECT,
  583. ("IncomingCall: pVc x%x, pAddrObj x%x/x%x, pConnInd x%x\n",
  584. pVc, pAddrObject, pAddrObject->Flags, pAddrObject->pConnInd));
  585. //
  586. // Initialize.
  587. //
  588. pTdiInfo = NULL;
  589. AfSpTdiOptionsContext = NULL;
  590. pConnReq = NULL;
  591. IsAddrLockAcquired = TRUE;
  592. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  593. do
  594. {
  595. if (RWAN_IS_BIT_SET(pAddrObject->Flags, RWANF_AO_CLOSING))
  596. {
  597. Status = NDIS_STATUS_FAILURE;
  598. break;
  599. }
  600. if (pVc->pConnObject != NULL)
  601. {
  602. RWAN_ASSERT(FALSE);
  603. Status = NDIS_STATUS_FAILURE;
  604. break;
  605. }
  606. //
  607. // Convert from NDIS Call Parameters to TDI Options.
  608. //
  609. RWanStatus = (*pAf->pAfInfo->AfChars.pAfSpNdis2TdiOptions)(
  610. pAf->AfSpAFContext,
  611. RWAN_CALLF_INCOMING_CALL|RWAN_CALLF_POINT_TO_POINT,
  612. pCallParameters,
  613. &pTdiInfo,
  614. &pTdiQoS,
  615. &TdiQoSLength,
  616. &AfSpTdiOptionsContext
  617. );
  618. if (RWanStatus != RWAN_STATUS_SUCCESS)
  619. {
  620. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  621. ("IncomingCall: conversion from NDIS to TDI failed, status x%x\n",
  622. RWanStatus));
  623. Status = NDIS_STATUS_FAILURE;
  624. break;
  625. }
  626. RWAN_ASSERT(pTdiInfo != NULL);
  627. RWAN_ASSERT(AfSpTdiOptionsContext != NULL);
  628. //
  629. // It has been decided to pass QOS and any provider-specific info
  630. // as part of TDI options.
  631. //
  632. pTdiInfo->Options = pTdiQoS;
  633. pTdiInfo->OptionsLength = TdiQoSLength;
  634. pVc->pCallParameters = pCallParameters;
  635. RWAN_SET_VC_CALL_PARAMS(pVc, pCallParameters);
  636. //
  637. // Find a listening connection.
  638. //
  639. for (pConnEntry = pAddrObject->ListenConnList.Flink;
  640. pConnEntry != &pAddrObject->ListenConnList;
  641. pConnEntry = pConnEntry->Flink)
  642. {
  643. pConnObject = CONTAINING_RECORD(pConnEntry, RWAN_TDI_CONNECTION, ConnLink);
  644. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  645. RWANDEBUGP(DL_EXTRA_LOUD, DC_CONNECT,
  646. ("Incoming Call: looking at pConnObj x%x, state %d\n",
  647. pConnObject, pConnObject->State));
  648. if (pConnObject->State == RWANS_CO_LISTENING)
  649. {
  650. break;
  651. }
  652. }
  653. if (pConnEntry != &pAddrObject->ListenConnList)
  654. {
  655. //
  656. // Found a listening connection.
  657. //
  658. RWAN_ACQUIRE_CONN_LOCK_DPC(pConnObject);
  659. //
  660. // Move the Connection from the Idle list to the Active list.
  661. //
  662. RWAN_DELETE_FROM_LIST(&pConnObject->ConnLink);
  663. RWAN_INSERT_TAIL_LIST(&pAddrObject->ActiveConnList,
  664. &pConnObject->ConnLink);
  665. RWAN_LINK_CONNECTION_TO_VC(pConnObject, pVc);
  666. RWanReferenceConnObject(pConnObject); // VC ref - InCall, Listening conn
  667. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  668. ("IncomingCall: pVc x%x, pConnObj x%x is listening, ConnReqFlags x%x\n",
  669. pVc, pConnObject, pConnObject->pConnReq->Flags));
  670. if (pConnObject->pConnReq->pConnInfo)
  671. {
  672. *pConnObject->pConnReq->pConnInfo = *pTdiInfo;
  673. }
  674. //
  675. // Check if it is pre-accepted. If so, tell NDIS that we have
  676. // accepted the call.
  677. //
  678. if (!(pConnObject->pConnReq->Flags & TDI_QUERY_ACCEPT))
  679. {
  680. pConnObject->State = RWANS_CO_IN_CALL_ACCEPTING;
  681. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  682. //
  683. // Request the media-specific module to update NDIS call parameters.
  684. //
  685. if (pAf->pAfInfo->AfChars.pAfSpUpdateNdisOptions)
  686. {
  687. (VOID)(*pAf->pAfInfo->AfChars.pAfSpUpdateNdisOptions)(
  688. pAf->AfSpAFContext,
  689. pConnObject->AfSpConnContext,
  690. RWAN_CALLF_INCOMING_CALL|RWAN_CALLF_POINT_TO_POINT,
  691. pTdiInfo,
  692. pTdiQoS,
  693. TdiQoSLength,
  694. &pCallParameters
  695. );
  696. }
  697. Status = NDIS_STATUS_SUCCESS;
  698. break;
  699. }
  700. //
  701. // It isn't pre-accepted. Complete the pended listen.
  702. //
  703. pConnReq = pConnObject->pConnReq;
  704. pConnObject->pConnReq = NULL;
  705. pConnObject->State = RWANS_CO_IN_CALL_INDICATED;
  706. AfSpConnContext = pConnObject->AfSpConnContext;
  707. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  708. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  709. IsAddrLockAcquired = FALSE;
  710. RWanCompleteConnReq( // InCall: Listen OK
  711. pSap->pNdisAf,
  712. pConnReq,
  713. FALSE,
  714. NULL,
  715. AfSpConnContext,
  716. TDI_SUCCESS
  717. );
  718. pConnReq = NULL;
  719. Status = NDIS_STATUS_PENDING;
  720. break;
  721. }
  722. //
  723. // There wasn't a listening connection available.
  724. // See if there is a Connect Indication event handler on this
  725. // Address Object.
  726. //
  727. if (pAddrObject->pConnInd == NULL)
  728. {
  729. //
  730. // No event handler. Reject this call.
  731. //
  732. Status = NDIS_STATUS_FAILURE;
  733. break;
  734. }
  735. //
  736. // Get some resources.
  737. //
  738. pConnReq = RWanAllocateConnReq();
  739. if (pConnReq == NULL)
  740. {
  741. Status = NDIS_STATUS_RESOURCES;
  742. break;
  743. }
  744. pConnInd = pAddrObject->pConnInd;
  745. ConnIndContext = pAddrObject->ConnIndContext;
  746. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  747. IsAddrLockAcquired = FALSE;
  748. RWANDEBUGP(DL_VERY_LOUD, DC_CONNECT,
  749. ("IncomingCall: Will Indicate: pVc x%x, RemAddr x%x/%d, Options x%x/%d\n",
  750. pVc,
  751. pTdiInfo->RemoteAddress,
  752. pTdiInfo->RemoteAddressLength,
  753. pTdiInfo->Options,
  754. pTdiInfo->OptionsLength));
  755. //
  756. // Indicate the call to the user.
  757. //
  758. TdiStatus = (*pConnInd)(
  759. ConnIndContext,
  760. pTdiInfo->RemoteAddressLength,
  761. pTdiInfo->RemoteAddress,
  762. pTdiInfo->UserDataLength,
  763. pTdiInfo->UserData,
  764. pTdiInfo->OptionsLength,
  765. pTdiInfo->Options,
  766. &AcceptConnContext,
  767. &EventInfo
  768. );
  769. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  770. ("IncomingCall: pVc x%x, pAddrObj x%x, Connect Ind returned x%x\n",
  771. pVc, pAddrObject, TdiStatus));
  772. if (TdiStatus != TDI_MORE_PROCESSING)
  773. {
  774. //
  775. // Connection rejected.
  776. //
  777. Status = NDIS_STATUS_FAILURE;
  778. break;
  779. }
  780. //
  781. // This connection has been accepted. Collect all information
  782. // about this implicit TdiAccept Request.
  783. //
  784. #ifdef NT
  785. pIrpSp = IoGetCurrentIrpStackLocation(EventInfo);
  786. Status = RWanPrepareIrpForCancel(
  787. (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext,
  788. EventInfo,
  789. RWanCancelRequest
  790. );
  791. if (!NT_SUCCESS(Status))
  792. {
  793. //
  794. // Reject this incoming call.
  795. //
  796. break;
  797. }
  798. pAcceptReq = (PTDI_REQUEST_KERNEL_ACCEPT) &(pIrpSp->Parameters);
  799. pConnReq->Request.pReqComplete = (PVOID)RWanRequestComplete;
  800. pConnReq->Request.ReqContext = EventInfo;
  801. pConnReq->pConnInfo = pAcceptReq->ReturnConnectionInformation;
  802. #else
  803. pConnReq->Request.pReqComplete = EventInfo.cei_rtn;
  804. pConnReq->Request.ReqContext = EventInfo.cei_context;
  805. pConnReq->pConnInfo = EventInfo.cei_conninfo;
  806. #endif // NT
  807. //
  808. // Find the connection object on which it has been accepted.
  809. //
  810. IsAddrLockAcquired = TRUE;
  811. RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
  812. for (pConnEntry = pAddrObject->IdleConnList.Flink;
  813. pConnEntry != &pAddrObject->IdleConnList;
  814. pConnEntry = pConnEntry->Flink)
  815. {
  816. pConnObject = CONTAINING_RECORD(pConnEntry, RWAN_TDI_CONNECTION, ConnLink);
  817. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  818. if ((pConnObject->ConnectionHandle == AcceptConnContext) &&
  819. !(RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING)))
  820. {
  821. break;
  822. }
  823. }
  824. if (pConnEntry == &pAddrObject->IdleConnList)
  825. {
  826. //
  827. // Invalid connection context!
  828. //
  829. TdiStatus = TDI_INVALID_CONNECTION;
  830. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  831. IsAddrLockAcquired = FALSE;
  832. //
  833. // Fail the Accept req
  834. //
  835. RWanCompleteConnReq( // InCall: Accept is bad
  836. pAf,
  837. pConnReq,
  838. FALSE,
  839. NULL,
  840. NULL,
  841. TdiStatus
  842. );
  843. pConnReq = NULL;
  844. //
  845. // Reject the incoming call
  846. //
  847. Status = NDIS_STATUS_FAILURE;
  848. break;
  849. }
  850. //
  851. // Request the media-specific module to update NDIS call parameters.
  852. //
  853. if (pAf->pAfInfo->AfChars.pAfSpUpdateNdisOptions)
  854. {
  855. (VOID)(*pAf->pAfInfo->AfChars.pAfSpUpdateNdisOptions)(
  856. pAf->AfSpAFContext,
  857. pConnObject->AfSpConnContext,
  858. RWAN_CALLF_INCOMING_CALL|RWAN_CALLF_POINT_TO_POINT,
  859. pTdiInfo,
  860. pTdiQoS,
  861. TdiQoSLength,
  862. &pCallParameters
  863. );
  864. }
  865. //
  866. // Set up the Connection Object for accepting this call.
  867. //
  868. RWAN_ACQUIRE_CONN_LOCK_DPC(pConnObject);
  869. pConnObject->State = RWANS_CO_IN_CALL_ACCEPTING;
  870. //
  871. // Save info to help us complete the Accept Req when
  872. // we get a CallConnected from NDIS.
  873. //
  874. RWAN_ASSERT(pConnObject->pConnReq == NULL);
  875. pConnObject->pConnReq = pConnReq;
  876. //
  877. // Move the Connection from the Idle list to the Active list.
  878. //
  879. RWAN_DELETE_FROM_LIST(&pConnObject->ConnLink);
  880. RWAN_INSERT_TAIL_LIST(&pAddrObject->ActiveConnList,
  881. &pConnObject->ConnLink);
  882. RWAN_LINK_CONNECTION_TO_VC(pConnObject, pVc);
  883. RWanReferenceConnObject(pConnObject); // VC ref
  884. RWAN_RELEASE_CONN_LOCK_DPC(pConnObject);
  885. //
  886. // Accept the call.
  887. //
  888. Status = NDIS_STATUS_SUCCESS;
  889. break;
  890. }
  891. while (FALSE);
  892. if (IsAddrLockAcquired)
  893. {
  894. RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
  895. }
  896. //
  897. // If we are rejecting this call, clean up.
  898. //
  899. if ((Status != NDIS_STATUS_SUCCESS) &&
  900. (Status != NDIS_STATUS_PENDING))
  901. {
  902. if (pConnReq != NULL)
  903. {
  904. RWanFreeConnReq(pConnReq);
  905. }
  906. }
  907. //
  908. // Return TDI options space to the media-specific module.
  909. //
  910. if (pTdiInfo != NULL)
  911. {
  912. RWAN_ASSERT(pAf);
  913. RWAN_ASSERT(AfSpTdiOptionsContext);
  914. (*pAf->pAfInfo->AfChars.pAfSpReturnTdiOptions)(
  915. pAf->AfSpAFContext,
  916. AfSpTdiOptionsContext
  917. );
  918. }
  919. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  920. ("IncomingCall: pVc x%x, returning status x%x\n", pVc, Status));
  921. return (Status);
  922. }
  923. VOID
  924. RWanNdisCallConnected(
  925. IN NDIS_HANDLE ProtocolVcContext
  926. )
  927. /*++
  928. Routine Description:
  929. This is the NDIS entry point signifying successful setup of an
  930. incoming call. If required, we complete the TDI user's Accept Request
  931. here.
  932. This primitive can happen only when the call is in the "Accepting" state.
  933. Arguments:
  934. ProtocolVcContext - Actually a pointer to our NDIS VC structure
  935. Return Value:
  936. None
  937. --*/
  938. {
  939. PRWAN_NDIS_VC pVc;
  940. PRWAN_TDI_CONNECTION pConnObject;
  941. PRWAN_TDI_ADDRESS pAddrObject;
  942. NDIS_HANDLE NdisVcHandle;
  943. NDIS_STATUS Status;
  944. PRWAN_CONN_REQUEST pConnReq;
  945. RWAN_HANDLE AfSpConnContext;
  946. ULONG rc;
  947. BOOLEAN IsAborting = FALSE;
  948. pVc = (PRWAN_NDIS_VC) ProtocolVcContext;
  949. RWAN_STRUCT_ASSERT(pVc, nvc);
  950. RWAN_ASSERT(pVc->pConnObject != NULL_PRWAN_TDI_CONNECTION);
  951. pConnObject = pVc->pConnObject;
  952. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  953. pAddrObject = pConnObject->pAddrObject;
  954. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  955. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_CALLCONN);
  956. IsAborting = ((pConnObject->State != RWANS_CO_IN_CALL_ACCEPTING) ||
  957. RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING));
  958. //
  959. // Incoming Connection setup successfully.
  960. //
  961. if (!IsAborting)
  962. {
  963. pConnObject->State = RWANS_CO_CONNECTED;
  964. }
  965. //
  966. // Add a temp ref to keep the conn object from going away.
  967. //
  968. RWanReferenceConnObject(pConnObject); // Temp ref, CallConn
  969. //
  970. // If we have an Accept Request to complete, complete it
  971. // now. Note that we might not have one pending in case
  972. // we had a pre-accepted listen.
  973. //
  974. pConnReq = pConnObject->pConnReq;
  975. pConnObject->pConnReq = NULL;
  976. AfSpConnContext = pConnObject->AfSpConnContext;
  977. RWAN_RELEASE_CONN_LOCK(pConnObject);
  978. if (pConnReq != NULL)
  979. {
  980. //
  981. // Complete the Accept request.
  982. //
  983. RWanCompleteConnReq( // CallConnected: Accept OK
  984. pVc->pNdisAf,
  985. pConnReq,
  986. FALSE,
  987. NULL,
  988. AfSpConnContext,
  989. TDI_SUCCESS
  990. );
  991. }
  992. //
  993. // Trigger off data indications for any packets that were received and queued
  994. // while we were in the process of accepting the call.
  995. //
  996. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  997. rc = RWanDereferenceConnObject(pConnObject); // Temp ref - CallConn
  998. //
  999. // But first make sure that the connection still exists and is in a good
  1000. // state.
  1001. //
  1002. if (rc != 0)
  1003. {
  1004. if (!IsAborting)
  1005. {
  1006. RWanIndicateData(pConnObject);
  1007. }
  1008. else
  1009. {
  1010. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1011. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  1012. ("CallConn: ConnObj %x/%x, State %d, aborting\n",
  1013. pConnObject, pConnObject->Flags, pConnObject->State));
  1014. RWanDoAbortConnection(pConnObject);
  1015. }
  1016. }
  1017. //
  1018. // else the Connection is gone!
  1019. //
  1020. return;
  1021. }
  1022. VOID
  1023. RWanNdisIncomingCloseCall(
  1024. IN NDIS_STATUS CloseStatus,
  1025. IN NDIS_HANDLE ProtocolVcContext,
  1026. IN PVOID pCloseData,
  1027. IN UINT CloseDataLength
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. This is the NDIS entry point called when a connection is torn
  1032. down by the remote peer or network. We mark the affected endpoint,
  1033. and if possible, indicate a Disconnect Event to the user. If we
  1034. do indicate to the user, call teardown is continued when the
  1035. user calls TdiDisconnect.
  1036. This primitive can happen while the endpoint is in one of these
  1037. states:
  1038. (1) Connected
  1039. (2) Accepting incoming call (TdiAccept pending)
  1040. Arguments:
  1041. CloseStatus - Status for the incoming close
  1042. ProtocolVcContext - Actually a pointer to our NDIS VC structure
  1043. pCloseData - Data/options associated with the close - NOT USED
  1044. CloseDataLength - Length of the above - NOT USED
  1045. Return Value:
  1046. None
  1047. --*/
  1048. {
  1049. PRWAN_NDIS_VC pVc;
  1050. PRWAN_NDIS_PARTY pParty;
  1051. PRWAN_NDIS_AF pAf;
  1052. PRWAN_TDI_CONNECTION pConnObject;
  1053. PRWAN_CONN_REQUEST pConnReq;
  1054. NDIS_HANDLE NdisVcHandle;
  1055. BOOLEAN bIsConnClosing; // TdiCloseConnection?
  1056. BOOLEAN bScheduleDisconnect;
  1057. RWAN_HANDLE AfSpConnContext;
  1058. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  1059. RWAN_STRUCT_ASSERT(pVc, nvc);
  1060. if (!RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_PMP))
  1061. {
  1062. pConnObject = pVc->pConnObject;
  1063. pParty = NULL;
  1064. }
  1065. else
  1066. {
  1067. //
  1068. // Locate the connection object for the last leaf.
  1069. //
  1070. pParty = CONTAINING_RECORD(pVc->NdisPartyList.Flink, RWAN_NDIS_PARTY, PartyLink);
  1071. RWAN_STRUCT_ASSERT(pParty, npy);
  1072. pConnObject = pParty->pConnObject;
  1073. }
  1074. RWAN_ASSERT(pConnObject != NULL_PRWAN_TDI_CONNECTION);
  1075. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  1076. RWANDEBUGP(DL_INFO, DC_DISCON,
  1077. ("IncomingClose: pVc x%x, pConnObj x%x/x%x, pParty x%x\n",
  1078. pVc, pConnObject, pConnObject->Flags, pParty));
  1079. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  1080. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_INCLOSE);
  1081. NdisVcHandle = pVc->NdisVcHandle;
  1082. bIsConnClosing = RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING);
  1083. if (bIsConnClosing)
  1084. {
  1085. //
  1086. // The user has initiated a TdiCloseConnection.
  1087. // Continue NDIS call teardown. When this completes,
  1088. // we'll complete the CloseConnection.
  1089. //
  1090. RWanStartCloseCall(pConnObject, pVc);
  1091. return;
  1092. }
  1093. pAf = pVc->pNdisAf;
  1094. switch (pConnObject->State)
  1095. {
  1096. case RWANS_CO_IN_CALL_ACCEPTING:
  1097. //
  1098. // If we have a pended Accept Request, fail it now.
  1099. // Otherwise, we must have had a pre-accepted listen,
  1100. // so we fall through and indicate a Disconnect.
  1101. //
  1102. pConnReq = pConnObject->pConnReq;
  1103. pConnObject->pConnReq = NULL;
  1104. if (pConnReq != NULL)
  1105. {
  1106. //
  1107. // Fix the state so that TdiDisconnect does the right thing
  1108. //
  1109. pConnObject->State = RWANS_CO_DISCON_INDICATED;
  1110. AfSpConnContext = pConnObject->AfSpConnContext;
  1111. RWanScheduleDisconnect(pConnObject);
  1112. //
  1113. // Conn Lock is released within the above.
  1114. //
  1115. RWanCompleteConnReq( // Incoming Close during IN_CALL_ACCEPT
  1116. pAf,
  1117. pConnReq,
  1118. FALSE,
  1119. NULL,
  1120. AfSpConnContext,
  1121. TDI_CONNECTION_ABORTED
  1122. );
  1123. break;
  1124. }
  1125. //
  1126. // else this must be a pre-accepted listen.
  1127. //
  1128. // FALLTHRU on "else" to RWANS_CO_CONNECTED
  1129. //
  1130. case RWANS_CO_CONNECTED:
  1131. //
  1132. // If there is a Disconnect Event handler, call it.
  1133. // Otherwise, simply mark this endpoint as having
  1134. // seen a Disconnect.
  1135. //
  1136. bScheduleDisconnect = TRUE;
  1137. if (pConnObject->pAddrObject != NULL_PRWAN_TDI_ADDRESS)
  1138. {
  1139. PDisconnectEvent pDisconInd;
  1140. PVOID IndContext;
  1141. PVOID ConnectionHandle;
  1142. pDisconInd = pConnObject->pAddrObject->pDisconInd;
  1143. IndContext = pConnObject->pAddrObject->DisconIndContext;
  1144. //
  1145. // Don't send up a Disconnect Indication if we are in the
  1146. // middle of indicating data.
  1147. //
  1148. if ((pDisconInd != NULL) &&
  1149. !(RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_INDICATING_DATA)))
  1150. {
  1151. RWANDEBUGP(DL_INFO, DC_WILDCARD,
  1152. ("IncomingClose: pConnObj %x/%x, st %x, will discon ind\n",
  1153. pConnObject, pConnObject->Flags, pConnObject->State));
  1154. pConnObject->State = RWANS_CO_DISCON_INDICATED;
  1155. ConnectionHandle = pConnObject->ConnectionHandle;
  1156. //
  1157. // Schedule a work item to continue Disconnect
  1158. // first. This is because the call to DiscInd can
  1159. // lead to a call to CloseConnection and block there.
  1160. //
  1161. bScheduleDisconnect = FALSE;
  1162. RWanScheduleDisconnect(pConnObject);
  1163. (*pDisconInd)(
  1164. IndContext,
  1165. ConnectionHandle,
  1166. 0, // Disconnect Data Length
  1167. NULL, // Disconnect Data
  1168. 0, // Disconnect Info Length
  1169. NULL, // Disconnect Info
  1170. TDI_DISCONNECT_RELEASE
  1171. );
  1172. }
  1173. else
  1174. {
  1175. RWANDEBUGP(DL_FATAL, DC_DISCON,
  1176. ("IncomingClose: pConnObj %x/%x, pending discon\n",
  1177. pConnObject, pConnObject->Flags));
  1178. pConnObject->State = RWANS_CO_DISCON_HELD;
  1179. RWAN_SET_BIT(pConnObject->Flags, RWANF_CO_PENDED_DISCON);
  1180. }
  1181. }
  1182. else
  1183. {
  1184. pConnObject->State = RWANS_CO_DISCON_HELD;
  1185. }
  1186. if (bScheduleDisconnect)
  1187. {
  1188. RWanScheduleDisconnect(pConnObject);
  1189. //
  1190. // Conn Object lock is released within the above.
  1191. //
  1192. }
  1193. break;
  1194. case RWANS_CO_ABORTING:
  1195. case RWANS_CO_DISCON_REQUESTED:
  1196. //
  1197. // Ignore this.
  1198. //
  1199. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1200. break;
  1201. default:
  1202. RWAN_ASSERT(FALSE);
  1203. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1204. break;
  1205. }
  1206. return;
  1207. }
  1208. VOID
  1209. RWanNdisCloseCallComplete(
  1210. IN NDIS_STATUS Status,
  1211. IN NDIS_HANDLE ProtocolVcContext,
  1212. IN NDIS_HANDLE ProtocolPartyContext
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. The NDIS entry point that is called when a previous pended call
  1217. we made to NdisClCloseCall has completed.
  1218. Arguments:
  1219. Status - Final status of CloseCall
  1220. ProtocolVcContext - Actually a pointer to our NDIS VC structure
  1221. ProtocolPartyContext- Last party context, points to NDIS PARTY structure
  1222. if this is a point-to-multipoint call.
  1223. Return Value:
  1224. None
  1225. --*/
  1226. {
  1227. PRWAN_NDIS_VC pVc;
  1228. PRWAN_NDIS_PARTY pParty;
  1229. PRWAN_NDIS_AF pAf;
  1230. PRWAN_TDI_CONNECTION pConnObject;
  1231. PRWAN_TDI_CONNECTION pRootConnObject;
  1232. INT rc;
  1233. PRWAN_CONN_REQUEST pConnReq;
  1234. BOOLEAN IsOutgoingCall;
  1235. RWAN_HANDLE AfSpConnContext;
  1236. #ifndef NO_POST_DISCON
  1237. PDisconnectEvent pDisconInd;
  1238. PVOID IndContext;
  1239. PVOID ConnectionHandle;
  1240. #endif // !NO_POST_DISCON
  1241. RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
  1242. pVc = (PRWAN_NDIS_VC)ProtocolVcContext;
  1243. RWAN_STRUCT_ASSERT(pVc, nvc);
  1244. RWAN_SET_VC_EVENT(pVc, RWANF_VC_EVT_CLOSECOMP);
  1245. //
  1246. // Check if this is a point-to-multipoint call.
  1247. //
  1248. pParty = (PRWAN_NDIS_PARTY)ProtocolPartyContext;
  1249. if (ProtocolPartyContext == NULL)
  1250. {
  1251. //
  1252. // Point to point call.
  1253. //
  1254. pConnObject = pVc->pConnObject;
  1255. pRootConnObject = NULL;
  1256. }
  1257. else
  1258. {
  1259. //
  1260. // PMP Call.
  1261. //
  1262. RWAN_STRUCT_ASSERT(pParty, npy);
  1263. pConnObject = pParty->pConnObject;
  1264. pRootConnObject = pConnObject->pRootConnObject;
  1265. }
  1266. RWANDEBUGP(DL_INFO, DC_DISCON,
  1267. ("CloseCallComplete: pVc x%x, pPty x%x, pConnObj x%x, pRoot x%x\n",
  1268. pVc, pParty, pVc->pConnObject, pRootConnObject));
  1269. if (pConnObject != NULL)
  1270. {
  1271. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  1272. //
  1273. // A pended Disconnect Request may be around.
  1274. //
  1275. pConnReq = pConnObject->pConnReq;
  1276. pConnObject->pConnReq = NULL;
  1277. pAf = pVc->pNdisAf;
  1278. IsOutgoingCall = RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_OUTGOING);
  1279. //
  1280. // State change:
  1281. //
  1282. if (pConnObject->State != RWANS_CO_ABORTING)
  1283. {
  1284. pConnObject->State = ((pConnObject->pAddrObject != NULL) ?
  1285. RWANS_CO_ASSOCIATED:
  1286. RWANS_CO_CREATED);
  1287. }
  1288. if (pParty == NULL)
  1289. {
  1290. //
  1291. // Unlink the VC from the Connection Object.
  1292. //
  1293. RWAN_UNLINK_CONNECTION_AND_VC(pConnObject, pVc); // CloseCallComplete
  1294. }
  1295. else
  1296. {
  1297. //
  1298. // PMP Call. The VC is linked to the root Conn Object.
  1299. //
  1300. RWAN_STRUCT_ASSERT(pRootConnObject, ntc);
  1301. RWAN_ACQUIRE_CONN_LOCK(pRootConnObject);
  1302. pRootConnObject->State = ((pRootConnObject->pAddrObject != NULL) ?
  1303. RWANS_CO_ASSOCIATED:
  1304. RWANS_CO_CREATED);
  1305. pVc->DroppingPartyCount --; // CloseCallComplete (PMP)
  1306. RWAN_UNLINK_CONNECTION_AND_VC(pRootConnObject, pVc); // CloseCallCompletePMP
  1307. rc = RWanDereferenceConnObject(pRootConnObject); // VC deref in CloseCallCompletePMP
  1308. if (rc > 0)
  1309. {
  1310. RWAN_RELEASE_CONN_LOCK(pRootConnObject);
  1311. }
  1312. //
  1313. // Unlink the Party from the VC and Leaf Conn Object.
  1314. //
  1315. pParty->pVc = NULL;
  1316. RWAN_DELETE_FROM_LIST(&(pParty->PartyLink));
  1317. pParty->pConnObject = NULL;
  1318. pConnObject->NdisConnection.pNdisParty = NULL;
  1319. }
  1320. AfSpConnContext = pConnObject->AfSpConnContext;
  1321. #ifndef NO_POST_DISCON
  1322. if (pConnObject->pAddrObject != NULL_PRWAN_TDI_ADDRESS)
  1323. {
  1324. pDisconInd = pConnObject->pAddrObject->pDisconInd;
  1325. IndContext = pConnObject->pAddrObject->DisconIndContext;
  1326. ConnectionHandle = pConnObject->ConnectionHandle;
  1327. }
  1328. else
  1329. {
  1330. pDisconInd = NULL;
  1331. }
  1332. #endif // NO_POST_DISCON
  1333. rc = RWanDereferenceConnObject(pConnObject); // VC/Pty deref in CloseCallComplete
  1334. if (rc > 0)
  1335. {
  1336. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1337. }
  1338. if (pConnReq != NULL)
  1339. {
  1340. #ifndef NO_POST_DISCON
  1341. if (pDisconInd != NULL)
  1342. {
  1343. (*pDisconInd)(
  1344. IndContext,
  1345. ConnectionHandle,
  1346. 0, // Disconnect Data Length
  1347. NULL, // Disconnect Data
  1348. 0, // Disconnect Info Length
  1349. NULL, // Disconnect Info
  1350. TDI_DISCONNECT_ABORT
  1351. );
  1352. }
  1353. #endif // !NO_POST_DISCON
  1354. RWanCompleteConnReq( // CloseCallComplete - completing discon req
  1355. pAf,
  1356. pConnReq,
  1357. IsOutgoingCall,
  1358. NULL,
  1359. AfSpConnContext,
  1360. TDI_SUCCESS
  1361. );
  1362. }
  1363. }
  1364. //
  1365. // See if the VC was created by us. If so, call NDIS to delete it,
  1366. // and free it.
  1367. //
  1368. if (RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_OUTGOING))
  1369. {
  1370. NDIS_HANDLE NdisVcHandle;
  1371. NdisVcHandle = pVc->NdisVcHandle;
  1372. //
  1373. // Unlink the VC from the list of VCs on the AF block
  1374. //
  1375. RWanUnlinkVcFromAf(pVc);
  1376. Status = NdisCoDeleteVc(NdisVcHandle);
  1377. RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
  1378. RWanFreeVc(pVc);
  1379. }
  1380. //
  1381. // Otherwise this VC was created by the Call Manager.
  1382. // Leave it as it is.
  1383. //
  1384. if (pParty != NULL)
  1385. {
  1386. RWAN_FREE_MEM(pParty); // CloseCallComplete PMP
  1387. }
  1388. return;
  1389. }
  1390. VOID
  1391. RWanNdisDropPartyComplete(
  1392. IN NDIS_STATUS Status,
  1393. IN NDIS_HANDLE ProtocolPartyContext
  1394. )
  1395. /*++
  1396. Routine Description:
  1397. This is the NDIS entry point signifying completion of a previous
  1398. call to NdisClDropParty that had pended.
  1399. We locate and complete the TDI Disconnect, if any, that lead to this.
  1400. Arguments:
  1401. Status - Final status of the Drop party request
  1402. ProtocolPartyContext- Actually a pointer to our NDIS PARTY structure
  1403. Return Value:
  1404. None
  1405. --*/
  1406. {
  1407. PRWAN_NDIS_PARTY pParty;
  1408. PRWAN_NDIS_VC pVc;
  1409. PRWAN_NDIS_AF pAf;
  1410. PRWAN_TDI_CONNECTION pConnObject;
  1411. PRWAN_TDI_CONNECTION pRootConnObject;
  1412. PRWAN_CONN_REQUEST pConnReq;
  1413. ULONG rc;
  1414. BOOLEAN IsOutgoingCall = TRUE;
  1415. BOOLEAN bVcNeedsClose;
  1416. RWAN_HANDLE AfSpConnContext;
  1417. #ifndef NO_POST_DISCON
  1418. PDisconnectEvent pDisconInd;
  1419. PVOID IndContext;
  1420. PVOID ConnectionHandle;
  1421. #endif // !NO_POST_DISCON
  1422. RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
  1423. pParty = (PRWAN_NDIS_PARTY)ProtocolPartyContext;
  1424. RWAN_STRUCT_ASSERT(pParty, npy);
  1425. pVc = pParty->pVc;
  1426. pConnObject = pParty->pConnObject;
  1427. if (pConnObject != NULL)
  1428. {
  1429. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  1430. //
  1431. // A pended Disconnect Request may be around.
  1432. //
  1433. pConnReq = pConnObject->pConnReq;
  1434. pConnObject->pConnReq = NULL;
  1435. pAf = pVc->pNdisAf;
  1436. //
  1437. // State change:
  1438. //
  1439. if (pConnObject->State != RWANS_CO_ABORTING)
  1440. {
  1441. pConnObject->State = ((pConnObject->pAddrObject != NULL) ?
  1442. RWANS_CO_ASSOCIATED:
  1443. RWANS_CO_CREATED);
  1444. }
  1445. AfSpConnContext = pConnObject->AfSpConnContext;
  1446. pRootConnObject = pVc->pConnObject;
  1447. RWAN_STRUCT_ASSERT(pRootConnObject, ntc);
  1448. #if DBG
  1449. if (pConnObject->pAddrObject != NULL)
  1450. {
  1451. RWAN_ASSERT(pRootConnObject == pConnObject->pAddrObject->pRootConnObject);
  1452. }
  1453. #endif // DBG
  1454. #ifndef NO_POST_DISCON
  1455. if (pConnObject->pAddrObject != NULL_PRWAN_TDI_ADDRESS)
  1456. {
  1457. pDisconInd = pConnObject->pAddrObject->pDisconInd;
  1458. IndContext = pConnObject->pAddrObject->DisconIndContext;
  1459. ConnectionHandle = pConnObject->ConnectionHandle;
  1460. }
  1461. else
  1462. {
  1463. pDisconInd = NULL;
  1464. }
  1465. #endif // NO_POST_DISCON
  1466. pConnObject->NdisConnection.pNdisParty = NULL;
  1467. rc = RWanDereferenceConnObject(pConnObject); // Pty deref in DropPartyComplete
  1468. if (rc > 0)
  1469. {
  1470. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1471. }
  1472. if (pConnReq != NULL)
  1473. {
  1474. #ifndef NO_POST_DISCON
  1475. if (pDisconInd != NULL)
  1476. {
  1477. (*pDisconInd)(
  1478. IndContext,
  1479. ConnectionHandle,
  1480. 0, // Disconnect Data Length
  1481. NULL, // Disconnect Data
  1482. 0, // Disconnect Info Length
  1483. NULL, // Disconnect Info
  1484. TDI_DISCONNECT_ABORT
  1485. );
  1486. }
  1487. #endif // NO_POST_DISCON
  1488. RWanCompleteConnReq( // DropPartyComplete - completing discon req
  1489. pAf,
  1490. pConnReq,
  1491. IsOutgoingCall,
  1492. NULL,
  1493. AfSpConnContext,
  1494. TDI_SUCCESS
  1495. );
  1496. }
  1497. //
  1498. // The Root Connection object lock controls access to
  1499. // the VC structure.
  1500. //
  1501. RWAN_ACQUIRE_CONN_LOCK(pRootConnObject);
  1502. //
  1503. // Unlink the Party from the VC.
  1504. //
  1505. RWAN_DELETE_FROM_LIST(&(pParty->PartyLink));
  1506. pVc->DroppingPartyCount --; // DropPartyComplete
  1507. //
  1508. // We may be in the process of shutting down this connection.
  1509. // This may be the penultimate Party going away. If so,
  1510. // continue the call close.
  1511. //
  1512. if (RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_NEEDS_CLOSE))
  1513. {
  1514. RWanStartCloseCall(pRootConnObject, pVc);
  1515. //
  1516. // Root Conn lock is released within the above.
  1517. //
  1518. }
  1519. else
  1520. {
  1521. RWAN_RELEASE_CONN_LOCK(pRootConnObject);
  1522. }
  1523. }
  1524. else
  1525. {
  1526. //
  1527. // Not sure if we can be here.
  1528. //
  1529. RWAN_ASSERT(FALSE);
  1530. }
  1531. //
  1532. // End of the road for this Party structure.
  1533. //
  1534. RWAN_FREE_MEM(pParty); // DropParty Complete
  1535. }
  1536. VOID
  1537. RWanNdisIncomingDropParty(
  1538. IN NDIS_STATUS Status,
  1539. IN NDIS_HANDLE OurPartyContext,
  1540. IN PVOID pBuffer,
  1541. IN UINT BufferLength
  1542. )
  1543. /*++
  1544. Routine Description:
  1545. This is the NDIS entry point notifying us that a leaf of a PMP call is
  1546. being dropped, either because the remote station terminated its session
  1547. or because of network conditions.
  1548. We simply inform the TDI client of a Disconnect on the Connection Object
  1549. representing this leaf, similar to an incoming Close on a VC.
  1550. Arguments:
  1551. Status - Status code for the Drop party
  1552. OurPartyContext - Pointer to our Party structure
  1553. pBuffer - Optional accompanying info (ignored)
  1554. BufferLength - Length of above (ignored)
  1555. Return Value:
  1556. None
  1557. --*/
  1558. {
  1559. PRWAN_NDIS_PARTY pParty;
  1560. PRWAN_NDIS_VC pVc;
  1561. PRWAN_TDI_CONNECTION pConnObject;
  1562. PRWAN_CONN_REQUEST pConnReq;
  1563. NDIS_HANDLE NdisPartyHandle;
  1564. BOOLEAN bIsConnClosing; // TdiCloseConnection?
  1565. BOOLEAN bIsLastLeaf;
  1566. BOOLEAN bScheduleDisconnect;
  1567. pParty = (PRWAN_NDIS_PARTY)OurPartyContext;
  1568. RWAN_STRUCT_ASSERT(pParty, npy);
  1569. pVc = pParty->pVc;
  1570. RWAN_STRUCT_ASSERT(pVc, nvc);
  1571. RWANDEBUGP(DL_INFO, DC_DISCON,
  1572. ("IncomingDrop: pPty x%x, pVc x%x, pConnObj x%x, AddingCnt %d, ActiveCnt %d\n",
  1573. pParty, pVc, pParty->pConnObject, pVc->AddingPartyCount, pVc->ActivePartyCount));
  1574. pConnObject = pParty->pConnObject;
  1575. RWAN_ASSERT(pConnObject != NULL_PRWAN_TDI_CONNECTION);
  1576. RWAN_STRUCT_ASSERT(pConnObject, ntc);
  1577. RWAN_ACQUIRE_CONN_LOCK(pConnObject);
  1578. bIsLastLeaf = (pVc->AddingPartyCount + pVc->ActivePartyCount == 0);
  1579. bIsConnClosing = RWAN_IS_BIT_SET(pConnObject->Flags, RWANF_CO_CLOSING);
  1580. if (bIsConnClosing)
  1581. {
  1582. //
  1583. // The user has initiated a TdiCloseConnection.
  1584. // Continue NDIS call teardown. When this completes,
  1585. // we'll complete the CloseConnection.
  1586. //
  1587. if (bIsLastLeaf)
  1588. {
  1589. RWanStartCloseCall(pConnObject, pVc);
  1590. //
  1591. // Conn Lock is released within the above.
  1592. //
  1593. }
  1594. else
  1595. {
  1596. NdisPartyHandle = pParty->NdisPartyHandle;
  1597. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1598. Status = NdisClDropParty(
  1599. NdisPartyHandle,
  1600. NULL, // No Drop Data
  1601. 0 // Length of above
  1602. );
  1603. if (Status != NDIS_STATUS_PENDING)
  1604. {
  1605. RWanNdisDropPartyComplete(
  1606. Status,
  1607. (NDIS_HANDLE)pParty
  1608. );
  1609. }
  1610. }
  1611. return;
  1612. }
  1613. switch (pConnObject->State)
  1614. {
  1615. case RWANS_CO_IN_CALL_ACCEPTING:
  1616. RWAN_ASSERT(FALSE);
  1617. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1618. break;
  1619. case RWANS_CO_CONNECTED:
  1620. //
  1621. // If there is a Disconnect Event handler, call it.
  1622. // Otherwise, simply mark this endpoint as having
  1623. // seen a Disconnect.
  1624. //
  1625. bScheduleDisconnect = TRUE;
  1626. if (pConnObject->pAddrObject != NULL_PRWAN_TDI_ADDRESS)
  1627. {
  1628. PDisconnectEvent pDisconInd;
  1629. PVOID IndContext;
  1630. PVOID ConnectionHandle;
  1631. pDisconInd = pConnObject->pAddrObject->pDisconInd;
  1632. IndContext = pConnObject->pAddrObject->DisconIndContext;
  1633. if (pDisconInd != NULL)
  1634. {
  1635. pConnObject->State = RWANS_CO_DISCON_INDICATED;
  1636. ConnectionHandle = pConnObject->ConnectionHandle;
  1637. bScheduleDisconnect = FALSE;
  1638. RWanScheduleDisconnect(pConnObject);
  1639. //
  1640. // Conn Object lock is released within the above.
  1641. //
  1642. RWANDEBUGP(DL_EXTRA_LOUD, DC_DISCON,
  1643. ("IncomingDrop: will indicate Discon, pConnObj x%x, pAddrObj x%x\n",
  1644. pConnObject, pConnObject->pAddrObject));
  1645. (*pDisconInd)(
  1646. IndContext,
  1647. ConnectionHandle,
  1648. 0, // Disconnect Data Length
  1649. NULL, // Disconnect Data
  1650. 0, // Disconnect Info Length
  1651. NULL, // Disconnect Info
  1652. TDI_DISCONNECT_ABORT
  1653. );
  1654. }
  1655. else
  1656. {
  1657. pConnObject->State = RWANS_CO_DISCON_HELD;
  1658. }
  1659. }
  1660. else
  1661. {
  1662. pConnObject->State = RWANS_CO_DISCON_HELD;
  1663. }
  1664. if (bScheduleDisconnect)
  1665. {
  1666. RWanScheduleDisconnect(pConnObject);
  1667. //
  1668. // Conn Object lock is released within the above.
  1669. //
  1670. }
  1671. break;
  1672. case RWANS_CO_ABORTING:
  1673. case RWANS_CO_DISCON_REQUESTED:
  1674. //
  1675. // Ignore this.
  1676. //
  1677. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1678. break;
  1679. default:
  1680. RWAN_ASSERT(FALSE);
  1681. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1682. break;
  1683. }
  1684. return;
  1685. }
  1686. VOID
  1687. RWanNdisModifyQoSComplete(
  1688. IN NDIS_STATUS Status,
  1689. IN NDIS_HANDLE OurVcContext,
  1690. IN PCO_CALL_PARAMETERS pCallParameters
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. Arguments:
  1695. Return Value:
  1696. None
  1697. --*/
  1698. {
  1699. //
  1700. // Not expected, since we don't call NdisClModifyCallQoS
  1701. //
  1702. RWAN_ASSERT(FALSE);
  1703. }
  1704. VOID
  1705. RWanNdisRejectIncomingCall(
  1706. IN PRWAN_TDI_CONNECTION pConnObject,
  1707. IN NDIS_STATUS RejectStatus
  1708. )
  1709. /*++
  1710. Routine Description:
  1711. Reject the incoming call present on the specified Connection Object.
  1712. Arguments:
  1713. pConnObject - Points to the TDI Connection
  1714. RejectStatus - Reason for rejecting the call
  1715. Locks on Entry:
  1716. pConnObject
  1717. Locks on Exit:
  1718. None
  1719. Return Value:
  1720. None
  1721. --*/
  1722. {
  1723. PRWAN_NDIS_VC pVc;
  1724. NDIS_HANDLE NdisVcHandle;
  1725. PCO_CALL_PARAMETERS pCallParameters;
  1726. INT rc;
  1727. PRWAN_CONN_REQUEST pConnReq;
  1728. PRWAN_NDIS_AF pAf;
  1729. RWAN_HANDLE AfSpConnContext;
  1730. pVc = pConnObject->NdisConnection.pNdisVc;
  1731. NdisVcHandle = pVc->NdisVcHandle;
  1732. pCallParameters = pVc->pCallParameters;
  1733. pVc->pCallParameters = NULL;
  1734. pAf = pVc->pNdisAf;
  1735. //
  1736. // Unlink the VC from the Conn Object.
  1737. //
  1738. RWAN_UNLINK_CONNECTION_AND_VC(pConnObject, pVc); // Reject incoming call
  1739. RWAN_SET_BIT(pVc->Flags, RWANF_VC_CLOSING_CALL);
  1740. pConnReq = pConnObject->pConnReq;
  1741. pConnObject->pConnReq = NULL;
  1742. //
  1743. // State change.
  1744. //
  1745. if (pConnObject->State != RWANS_CO_ABORTING)
  1746. {
  1747. pConnObject->State = ((pConnObject->pAddrObject != NULL) ?
  1748. RWANS_CO_ASSOCIATED:
  1749. RWANS_CO_CREATED);
  1750. }
  1751. AfSpConnContext = pConnObject->AfSpConnContext;
  1752. rc = RWanDereferenceConnObject(pConnObject); // Unlinking VC in reject in-call
  1753. if (rc > 0)
  1754. {
  1755. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1756. }
  1757. NdisClIncomingCallComplete(
  1758. RejectStatus,
  1759. NdisVcHandle,
  1760. pCallParameters
  1761. );
  1762. if (pConnReq != NULL)
  1763. {
  1764. RWanCompleteConnReq( // Discon Req for rejecting in call
  1765. pAf,
  1766. pConnReq,
  1767. FALSE,
  1768. NULL, // No Call Parameters
  1769. AfSpConnContext,
  1770. TDI_SUCCESS
  1771. );
  1772. }
  1773. return;
  1774. }
  1775. VOID
  1776. RWanStartCloseCall(
  1777. IN PRWAN_TDI_CONNECTION pConnObject,
  1778. IN PRWAN_NDIS_VC pVc
  1779. )
  1780. /*++
  1781. Routine Description:
  1782. Start NDIS call teardown on the VC associated with the given
  1783. connection object, if all pre-conditions are met:
  1784. 0. An NDIS CloseCall isn't already going on
  1785. 1. No outstanding sends
  1786. Arguments:
  1787. pConnObject - Points to TDI Connection object
  1788. pVc - Points to corresponding VC
  1789. Locks on Entry:
  1790. pConnObject
  1791. Locks on Exit:
  1792. None
  1793. Return Value:
  1794. None
  1795. --*/
  1796. {
  1797. PRWAN_NDIS_PARTY pParty;
  1798. NDIS_HANDLE NdisVcHandle;
  1799. NDIS_HANDLE NdisPartyHandle;
  1800. NDIS_STATUS Status;
  1801. PRWAN_RECEIVE_INDICATION pRcvIndHead;
  1802. PRWAN_RECEIVE_INDICATION pRcvInd;
  1803. RWANDEBUGP(DL_INFO, DC_DISCON,
  1804. ("StartCloseCall: pVc x%x/x%x, PendingCount %d, pConnObj x%x\n",
  1805. pVc,
  1806. pVc->Flags,
  1807. pVc->PendingPacketCount,
  1808. pConnObject));
  1809. //
  1810. // Free up any pending receives.
  1811. //
  1812. pRcvIndHead = pVc->pRcvIndHead;
  1813. if (pRcvIndHead != NULL)
  1814. {
  1815. pVc->pRcvIndHead = NULL;
  1816. pVc->pRcvIndTail = NULL;
  1817. //
  1818. // Update the count of pending packets on this VC.
  1819. //
  1820. for (pRcvInd = pRcvIndHead; pRcvInd != NULL; pRcvInd = pRcvInd->pNextRcvInd)
  1821. {
  1822. pVc->PendingPacketCount--;
  1823. }
  1824. //
  1825. // We will free this list below.
  1826. //
  1827. }
  1828. if ((pVc != NULL) &&
  1829. (pVc->PendingPacketCount == 0) &&
  1830. (pVc->DroppingPartyCount == 0) &&
  1831. (!RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_CLOSING_CALL)))
  1832. {
  1833. NdisVcHandle = pVc->NdisVcHandle;
  1834. RWAN_SET_BIT(pVc->Flags, RWANF_VC_CLOSING_CALL);
  1835. RWAN_RESET_BIT(pVc->Flags, RWANF_VC_NEEDS_CLOSE);
  1836. if (RWAN_IS_LIST_EMPTY(&(pVc->NdisPartyList)))
  1837. {
  1838. pParty = NULL_PRWAN_NDIS_PARTY;
  1839. NdisPartyHandle = NULL;
  1840. RWAN_ASSERT(!RWAN_IS_BIT_SET(pVc->Flags, RWANF_VC_PMP));
  1841. }
  1842. else
  1843. {
  1844. pParty = CONTAINING_RECORD(pVc->NdisPartyList.Flink, RWAN_NDIS_PARTY, PartyLink);
  1845. NdisPartyHandle = pParty->NdisPartyHandle;
  1846. RWAN_SET_BIT(pParty->Flags, RWANF_PARTY_DROPPING);
  1847. pVc->DroppingPartyCount ++; // StartCloseCall PMP
  1848. pVc->ActivePartyCount --; // StartCloseCall PMP
  1849. }
  1850. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1851. Status = NdisClCloseCall(
  1852. NdisVcHandle,
  1853. NdisPartyHandle,
  1854. NULL, // No CloseData
  1855. 0
  1856. );
  1857. if (Status != NDIS_STATUS_PENDING)
  1858. {
  1859. RWanNdisCloseCallComplete(
  1860. Status,
  1861. (NDIS_HANDLE)pVc, // ProtocolVcContext
  1862. (NDIS_HANDLE)pParty // ProtocolPartyContext
  1863. );
  1864. }
  1865. }
  1866. else
  1867. {
  1868. if (pVc != NULL)
  1869. {
  1870. RWAN_SET_BIT(pVc->Flags, RWANF_VC_NEEDS_CLOSE);
  1871. }
  1872. RWAN_RELEASE_CONN_LOCK(pConnObject);
  1873. }
  1874. if (pRcvIndHead != NULL)
  1875. {
  1876. RWANDEBUGP(DL_INFO, DC_DISCON,
  1877. ("RWanStartCloseCall: will free rcv ind list x%x on VC x%x\n",
  1878. pRcvIndHead, pVc));
  1879. RWanFreeReceiveIndList(pRcvIndHead);
  1880. }
  1881. }
  1882. VOID
  1883. RWanUnlinkVcFromAf(
  1884. IN PRWAN_NDIS_VC pVc
  1885. )
  1886. /*++
  1887. Routine Description:
  1888. Unlink a VC from the AF it belongs to.
  1889. Arguments:
  1890. pVc - Points to VC to be unlinked
  1891. Return Value:
  1892. None
  1893. --*/
  1894. {
  1895. PRWAN_NDIS_AF pAf;
  1896. INT rc;
  1897. pAf = pVc->pNdisAf;
  1898. RWAN_STRUCT_ASSERT(pAf, naf);
  1899. RWAN_ACQUIRE_AF_LOCK(pAf);
  1900. RWAN_DELETE_FROM_LIST(&(pVc->VcLink));
  1901. rc = RWanDereferenceAf(pAf); // VC unlink deref
  1902. if (rc != 0)
  1903. {
  1904. RWAN_RELEASE_AF_LOCK(pAf);
  1905. }
  1906. return;
  1907. }
  1908. VOID
  1909. RWanCompleteConnReq(
  1910. IN PRWAN_NDIS_AF pAf,
  1911. IN PRWAN_CONN_REQUEST pConnReq,
  1912. IN BOOLEAN IsOutgoingCall,
  1913. IN PCO_CALL_PARAMETERS pCallParameters OPTIONAL,
  1914. IN RWAN_HANDLE AfSpConnContext,
  1915. IN TDI_STATUS TdiStatus
  1916. )
  1917. /*++
  1918. Routine Description:
  1919. Call the completion routine for a pended TDI request on a connection.
  1920. Set up the options and completion status based on what's given to us.
  1921. Arguments:
  1922. pAf - The AF block on which the request was made
  1923. pConnReq - the pended request to be completed
  1924. IsOutgoingCall - Is this an outgoing call?
  1925. pCallParameters - if applicable, this should be mapped to connection info
  1926. AfSpConnContext - Connection context, if applicable, for the media-specific
  1927. module.
  1928. TdiStatus - completion status for the request
  1929. Return Value:
  1930. None
  1931. --*/
  1932. {
  1933. RWAN_STATUS RWanStatus;
  1934. ULONG TdiQoSLength = 0;
  1935. if (pConnReq == NULL)
  1936. {
  1937. return;
  1938. }
  1939. RWAN_STRUCT_ASSERT(pConnReq, nrc);
  1940. //
  1941. // Update Connection Information if we need to.
  1942. //
  1943. if ((pConnReq->pConnInfo != NULL) &&
  1944. (pCallParameters != NULL))
  1945. {
  1946. RWanStatus = (*pAf->pAfInfo->AfChars.pAfSpUpdateTdiOptions)(
  1947. pAf->AfSpAFContext,
  1948. AfSpConnContext,
  1949. IsOutgoingCall,
  1950. pCallParameters,
  1951. &pConnReq->pConnInfo,
  1952. pConnReq->pConnInfo->Options,
  1953. &pConnReq->pConnInfo->OptionsLength
  1954. );
  1955. }
  1956. //
  1957. // Call the completion routine.
  1958. //
  1959. (*pConnReq->Request.pReqComplete)(
  1960. pConnReq->Request.ReqContext,
  1961. TdiStatus,
  1962. 0
  1963. );
  1964. RWanFreeConnReq(pConnReq);
  1965. }