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.

1747 lines
37 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. spxcutil.c
  5. Abstract:
  6. This module contains code which implements the CONNECTION object.
  7. Routines are provided to create, destroy, reference, and dereference,
  8. transport connection objects.
  9. Author:
  10. Nikhil Kamkolkar (nikhilk) 11-November-1993
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. Sanjay Anand (SanjayAn) 5-July-1995
  15. Bug fixes - tagged [SA]
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #ifndef __PREFAST__
  20. #pragma warning(disable:4068)
  21. #endif
  22. #pragma prefast(disable:276, "The assignments are harmless")
  23. // Define module number for event logging entries
  24. #define FILENUM SPXCUTIL
  25. //
  26. // Minor utility routines
  27. //
  28. BOOLEAN
  29. spxConnCheckNegSize(
  30. IN PUSHORT pNegSize
  31. )
  32. /*++
  33. Routine Description:
  34. Arguments:
  35. Return Value:
  36. --*/
  37. {
  38. int i;
  39. // We go thru table and see if this is the minimum size or if it
  40. // can go down further. Return true if it is not the minimum size.
  41. DBGPRINT(CONNECT, INFO,
  42. ("spxConnCheckNegSize: Current %lx Check Val %lx\n",
  43. (ULONG)(*pNegSize - MIN_IPXSPX2_HDRSIZE),
  44. SpxMaxPktSize[0]));
  45. if ((ULONG)(*pNegSize - MIN_IPXSPX2_HDRSIZE) <= SpxMaxPktSize[0])
  46. return(FALSE);
  47. for (i = SpxMaxPktSizeIndex-1; i > 0; i--)
  48. {
  49. DBGPRINT(CONNECT, INFO,
  50. ("spxConnCheckNegSize: Current %lx Check Val %lx\n",
  51. (ULONG)(*pNegSize - MIN_IPXSPX2_HDRSIZE),
  52. SpxMaxPktSize[i]));
  53. if (SpxMaxPktSize[i] < (ULONG)(*pNegSize - MIN_IPXSPX2_HDRSIZE))
  54. break;
  55. }
  56. *pNegSize = (USHORT)(SpxMaxPktSize[i] + MIN_IPXSPX2_HDRSIZE);
  57. DBGPRINT(CONNECT, ERR,
  58. ("spxConnCheckNegSize: Trying Size %lx Min size possible %lx\n",
  59. *pNegSize, SpxMaxPktSize[0] + MIN_IPXSPX2_HDRSIZE));
  60. return(TRUE);
  61. }
  62. VOID
  63. spxConnSetNegSize(
  64. IN OUT PNDIS_PACKET pPkt,
  65. IN ULONG Size
  66. )
  67. /*++
  68. Routine Description:
  69. Arguments:
  70. Return Value:
  71. --*/
  72. {
  73. PNDIS_BUFFER pNdisBuffer;
  74. UINT bufCount;
  75. PSPX_SEND_RESD pSendResd;
  76. PIPXSPX_HDR pIpxSpxHdr;
  77. CTEAssert(Size > 0);
  78. NdisQueryPacket(pPkt, NULL, &bufCount, &pNdisBuffer, NULL);
  79. CTEAssert (bufCount == 3);
  80. NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
  81. NdisQueryBuffer(pNdisBuffer, &pIpxSpxHdr, &bufCount);
  82. NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
  83. NdisAdjustBufferLength(pNdisBuffer, Size);
  84. // Change it in send reserved
  85. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  86. pSendResd->sr_Len = (Size + MIN_IPXSPX2_HDRSIZE);
  87. #if SPX_OWN_PACKETS
  88. // Change in ipx header
  89. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  90. NDIS_PACKET_SIZE +
  91. sizeof(SPX_SEND_RESD) +
  92. IpxInclHdrOffset);
  93. #endif
  94. PUTSHORT2SHORT((PUSHORT)&pIpxSpxHdr->hdr_PktLen, (Size + MIN_IPXSPX2_HDRSIZE));
  95. // Change in the neg packet field of the header.
  96. PUTSHORT2SHORT(
  97. &pIpxSpxHdr->hdr_NegSize,
  98. (Size + MIN_IPXSPX2_HDRSIZE));
  99. DBGPRINT(CONNECT, DBG,
  100. ("spxConnSetNegSize: Setting size to %lx Hdr %lx\n",
  101. Size, (Size + MIN_IPXSPX2_HDRSIZE)));
  102. return;
  103. }
  104. BOOLEAN
  105. SpxConnDequeueSendPktLock(
  106. IN PSPX_CONN_FILE pSpxConnFile,
  107. IN PNDIS_PACKET pPkt
  108. )
  109. /*++
  110. Routine Description:
  111. Arguments:
  112. Return Value:
  113. --*/
  114. {
  115. PSPX_SEND_RESD pSr, pListHead, pListTail;
  116. PSPX_SEND_RESD pSendResd;
  117. BOOLEAN removed = TRUE;
  118. // If we are sequenced or not decides which list we choose.
  119. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  120. if ((pSendResd->sr_State & SPX_SENDPKT_SEQ) != 0)
  121. {
  122. pListHead = pSpxConnFile->scf_SendSeqListHead;
  123. pListTail = pSpxConnFile->scf_SendSeqListTail;
  124. }
  125. else
  126. {
  127. pListHead = pSpxConnFile->scf_SendListHead;
  128. pListTail = pSpxConnFile->scf_SendListTail;
  129. }
  130. // Most often, we will be at the head of the list.
  131. if (pListHead == pSendResd)
  132. {
  133. if ((pListHead = pSendResd->sr_Next) == NULL)
  134. {
  135. DBGPRINT(SEND, INFO,
  136. ("SpxConnDequeuePktLock: %lx first in list\n", pSendResd));
  137. pListTail = NULL;
  138. }
  139. }
  140. else
  141. {
  142. DBGPRINT(SEND, INFO,
  143. ("SpxConnDequeuePktLock: %lx !first in list\n", pSendResd));
  144. pSr = pListHead;
  145. while (pSr != NULL)
  146. {
  147. if (pSr->sr_Next == pSendResd)
  148. {
  149. if ((pSr->sr_Next = pSendResd->sr_Next) == NULL)
  150. {
  151. pListTail = pSr;
  152. }
  153. break;
  154. }
  155. pSr = pSr->sr_Next;
  156. }
  157. if (pSr == NULL)
  158. removed = FALSE;
  159. }
  160. if (removed)
  161. {
  162. if ((pSendResd->sr_State & SPX_SENDPKT_SEQ) != 0)
  163. {
  164. pSpxConnFile->scf_SendSeqListHead = pListHead;
  165. pSpxConnFile->scf_SendSeqListTail = pListTail;
  166. }
  167. else
  168. {
  169. pSpxConnFile->scf_SendListHead = pListHead;
  170. pSpxConnFile->scf_SendListTail = pListTail;
  171. }
  172. }
  173. return(removed);
  174. }
  175. BOOLEAN
  176. SpxConnDequeueRecvPktLock(
  177. IN PSPX_CONN_FILE pSpxConnFile,
  178. IN PNDIS_PACKET pPkt
  179. )
  180. /*++
  181. Routine Description:
  182. Arguments:
  183. Return Value:
  184. --*/
  185. {
  186. PSPX_RECV_RESD pSr, pListHead, pListTail;
  187. PSPX_RECV_RESD pRecvResd;
  188. BOOLEAN removed = TRUE;
  189. pRecvResd = (PSPX_RECV_RESD)(pPkt->ProtocolReserved);
  190. pListHead = pSpxConnFile->scf_RecvListHead;
  191. pListTail = pSpxConnFile->scf_RecvListTail;
  192. // Most often, we will be at the head of the list.
  193. if (pListHead == pRecvResd)
  194. {
  195. DBGPRINT(RECEIVE, INFO,
  196. ("SpxConnDequeuePktLock: %lx first in list\n", pRecvResd));
  197. if ((pListHead = pRecvResd->rr_Next) == NULL)
  198. {
  199. pListTail = NULL;
  200. }
  201. }
  202. else
  203. {
  204. DBGPRINT(RECEIVE, INFO,
  205. ("SpxConnDequeuePktLock: %lx !first in list\n", pRecvResd));
  206. pSr = pListHead;
  207. while (pSr != NULL)
  208. {
  209. if (pSr->rr_Next == pRecvResd)
  210. {
  211. if ((pSr->rr_Next = pRecvResd->rr_Next) == NULL)
  212. {
  213. pListTail = pSr;
  214. }
  215. break;
  216. }
  217. pSr = pSr->rr_Next;
  218. }
  219. if (pSr == NULL)
  220. removed = FALSE;
  221. }
  222. if (removed)
  223. {
  224. pSpxConnFile->scf_RecvListHead = pListHead;
  225. pSpxConnFile->scf_RecvListTail = pListTail;
  226. }
  227. return(removed);
  228. }
  229. BOOLEAN
  230. spxConnGetPktByType(
  231. IN PSPX_CONN_FILE pSpxConnFile,
  232. IN ULONG PktType,
  233. IN BOOLEAN fSeqList,
  234. IN PNDIS_PACKET * ppPkt
  235. )
  236. /*++
  237. Routine Description:
  238. Arguments:
  239. Return Value:
  240. --*/
  241. {
  242. PSPX_SEND_RESD pSr, *ppSr;
  243. // Most often, we will be at the head of the list.
  244. ppSr = (fSeqList ?
  245. &pSpxConnFile->scf_SendSeqListHead :
  246. &pSpxConnFile->scf_SendListHead);
  247. for (; (pSr = *ppSr) != NULL; )
  248. {
  249. if (pSr->sr_Type == PktType)
  250. {
  251. *ppPkt = (PNDIS_PACKET)CONTAINING_RECORD(
  252. pSr, NDIS_PACKET, ProtocolReserved);
  253. DBGPRINT(SEND, INFO,
  254. ("SpxConnFindByType: %lx.%lx.%d\n", pSr,*ppPkt, fSeqList));
  255. break;
  256. }
  257. ppSr = &pSr->sr_Next;
  258. }
  259. return(pSr != NULL);
  260. }
  261. BOOLEAN
  262. spxConnGetPktBySeqNum(
  263. IN PSPX_CONN_FILE pSpxConnFile,
  264. IN USHORT SeqNum,
  265. IN PNDIS_PACKET * ppPkt
  266. )
  267. /*++
  268. Routine Description:
  269. Arguments:
  270. Return Value:
  271. --*/
  272. {
  273. PSPX_SEND_RESD pSr, *ppSr;
  274. // Most often, we will be at the head of the list.
  275. ppSr = &pSpxConnFile->scf_SendSeqListHead;
  276. for (; (pSr = *ppSr) != NULL; )
  277. {
  278. if (pSr->sr_SeqNum == SeqNum)
  279. {
  280. *ppPkt = (PNDIS_PACKET)CONTAINING_RECORD(
  281. pSr, NDIS_PACKET, ProtocolReserved);
  282. DBGPRINT(SEND, DBG,
  283. ("SpxConnFindBySeq: %lx.%lx.%d\n", pSr,*ppPkt, SeqNum));
  284. break;
  285. }
  286. ppSr = &pSr->sr_Next;
  287. }
  288. return(pSr != NULL);
  289. }
  290. USHORT
  291. spxConnGetId(
  292. VOID
  293. )
  294. /*++
  295. Routine Description:
  296. This must be called with the device lock held.
  297. Arguments:
  298. Return Value:
  299. --*/
  300. {
  301. PSPX_CONN_FILE pSpxConnFile;
  302. BOOLEAN wrapped = FALSE;
  303. USHORT startConnId, retConnId;
  304. startConnId = SpxDevice->dev_NextConnId;
  305. // Search the global active list.
  306. do
  307. {
  308. if ((SpxDevice->dev_NextConnId >= startConnId) && wrapped)
  309. {
  310. retConnId = 0;
  311. break;
  312. }
  313. if (SpxDevice->dev_NextConnId == 0xFFFF)
  314. {
  315. wrapped = TRUE;
  316. SpxDevice->dev_NextConnId = 1;
  317. continue;
  318. }
  319. // Later this be a tree.
  320. for (pSpxConnFile = SpxDevice->dev_GlobalActiveConnList[
  321. SpxDevice->dev_NextConnId & NUM_SPXCONN_HASH_MASK];
  322. pSpxConnFile != NULL;
  323. pSpxConnFile = pSpxConnFile->scf_GlobalActiveNext)
  324. {
  325. if (pSpxConnFile->scf_LocalConnId == SpxDevice->dev_NextConnId)
  326. {
  327. break;
  328. }
  329. }
  330. // Increment for next time.
  331. retConnId = SpxDevice->dev_NextConnId++;
  332. // Ensure we are still legal. We could return if connfile is null.
  333. if (SpxDevice->dev_NextConnId == 0xFFFF)
  334. {
  335. wrapped = TRUE;
  336. SpxDevice->dev_NextConnId = 1;
  337. }
  338. if (pSpxConnFile != NULL)
  339. {
  340. continue;
  341. }
  342. break;
  343. } while (TRUE);
  344. return(retConnId);
  345. }
  346. NTSTATUS
  347. spxConnRemoveFromList(
  348. IN PSPX_CONN_FILE * ppConnListHead,
  349. IN PSPX_CONN_FILE pConnRemove
  350. )
  351. /*++
  352. Routine Description:
  353. This routine must be called with the address lock (and the lock of the remove
  354. connection will usually also be, but is not needed) held.
  355. Arguments:
  356. Return Value:
  357. --*/
  358. {
  359. PSPX_CONN_FILE pRemConn, *ppRemConn;
  360. NTSTATUS status = STATUS_SUCCESS;
  361. // Dequeue the connection file from the address list. It must be
  362. // in the inactive list.
  363. for (ppRemConn = ppConnListHead;
  364. (pRemConn = *ppRemConn) != NULL;)
  365. {
  366. if (pRemConn == pConnRemove)
  367. {
  368. *ppRemConn = pRemConn->scf_Next;
  369. break;
  370. }
  371. ppRemConn = &pRemConn->scf_Next;
  372. }
  373. if (pRemConn == NULL)
  374. {
  375. DBGBRK(FATAL);
  376. CTEAssert(0);
  377. status = STATUS_INVALID_CONNECTION;
  378. }
  379. return(status);
  380. }
  381. NTSTATUS
  382. spxConnRemoveFromAssocList(
  383. IN PSPX_CONN_FILE * ppConnListHead,
  384. IN PSPX_CONN_FILE pConnRemove
  385. )
  386. /*++
  387. Routine Description:
  388. This routine must be called with the address lock (and the lock of the remove
  389. connection will usually also be, but is not needed) held.
  390. Arguments:
  391. Return Value:
  392. --*/
  393. {
  394. PSPX_CONN_FILE pRemConn, *ppRemConn;
  395. NTSTATUS status = STATUS_SUCCESS;
  396. // Dequeue the connection file from the address list. It must be
  397. // in the inactive list.
  398. for (ppRemConn = ppConnListHead;
  399. (pRemConn = *ppRemConn) != NULL;)
  400. {
  401. if (pRemConn == pConnRemove)
  402. {
  403. *ppRemConn = pRemConn->scf_AssocNext;
  404. break;
  405. }
  406. ppRemConn = &pRemConn->scf_AssocNext;
  407. }
  408. if (pRemConn == NULL)
  409. {
  410. CTEAssert(0);
  411. status = STATUS_INVALID_CONNECTION;
  412. }
  413. return(status);
  414. }
  415. VOID
  416. spxConnInsertIntoGlobalActiveList(
  417. IN PSPX_CONN_FILE pSpxConnFile
  418. )
  419. /*++
  420. Routine Description:
  421. This routine must be called with the device lock held.
  422. Arguments:
  423. Return Value:
  424. --*/
  425. {
  426. int index = (int)(pSpxConnFile->scf_LocalConnId &
  427. NUM_SPXCONN_HASH_MASK);
  428. // For now, its just a linear list.
  429. pSpxConnFile->scf_GlobalActiveNext =
  430. SpxDevice->dev_GlobalActiveConnList[index];
  431. SpxDevice->dev_GlobalActiveConnList[index] =
  432. pSpxConnFile;
  433. return;
  434. }
  435. NTSTATUS
  436. spxConnRemoveFromGlobalActiveList(
  437. IN PSPX_CONN_FILE pSpxConnFile
  438. )
  439. /*++
  440. Routine Description:
  441. This routine must be called with the device lock held.
  442. Arguments:
  443. Return Value:
  444. --*/
  445. {
  446. PSPX_CONN_FILE pC, *ppC;
  447. int index = (int)(pSpxConnFile->scf_LocalConnId &
  448. NUM_SPXCONN_HASH_MASK);
  449. NTSTATUS status = STATUS_SUCCESS;
  450. // For now, its just a linear list.
  451. for (ppC = &SpxDevice->dev_GlobalActiveConnList[index];
  452. (pC = *ppC) != NULL;)
  453. {
  454. if (pC == pSpxConnFile)
  455. {
  456. DBGPRINT(SEND, INFO,
  457. ("SpxConnRemoveFromGlobal: %lx\n", pSpxConnFile));
  458. // Remove from list
  459. *ppC = pC->scf_GlobalActiveNext;
  460. break;
  461. }
  462. ppC = &pC->scf_GlobalActiveNext;
  463. }
  464. if (pC == NULL)
  465. status = STATUS_INVALID_CONNECTION;
  466. return(status);
  467. }
  468. VOID
  469. spxConnInsertIntoGlobalList(
  470. IN PSPX_CONN_FILE pSpxConnFile
  471. )
  472. /*++
  473. Routine Description:
  474. Arguments:
  475. Return Value:
  476. --*/
  477. {
  478. CTELockHandle lockHandle;
  479. // Get the global q lock
  480. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  481. pSpxConnFile->scf_GlobalNext = SpxGlobalConnList;
  482. SpxGlobalConnList = pSpxConnFile;
  483. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  484. return;
  485. }
  486. NTSTATUS
  487. spxConnRemoveFromGlobalList(
  488. IN PSPX_CONN_FILE pSpxConnFile
  489. )
  490. /*++
  491. Routine Description:
  492. Arguments:
  493. Return Value:
  494. --*/
  495. {
  496. CTELockHandle lockHandle;
  497. PSPX_CONN_FILE pC, *ppC;
  498. NTSTATUS status = STATUS_SUCCESS;
  499. // Get the global q lock
  500. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  501. for (ppC = &SpxGlobalConnList;
  502. (pC = *ppC) != NULL;)
  503. {
  504. if (pC == pSpxConnFile)
  505. {
  506. DBGPRINT(SEND, DBG,
  507. ("SpxConnRemoveFromGlobal: %lx\n", pSpxConnFile));
  508. // Remove from list
  509. *ppC = pC->scf_GlobalNext;
  510. break;
  511. }
  512. ppC = &pC->scf_GlobalNext;
  513. }
  514. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  515. if (pC == NULL)
  516. status = STATUS_INVALID_CONNECTION;
  517. return(status);
  518. }
  519. #if 0
  520. VOID
  521. spxConnPushIntoPktList(
  522. IN PSPX_CONN_FILE pSpxConnFile
  523. )
  524. /*++
  525. Routine Description:
  526. !!!MACROIZE!!!
  527. Arguments:
  528. Return Value:
  529. --*/
  530. {
  531. CTELockHandle lockHandle;
  532. // Get the global q lock
  533. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  534. pSpxConnFile->scf_PktNext = SpxPktConnList;
  535. SpxPktConnList = pSpxConnFile;
  536. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  537. return;
  538. }
  539. VOID
  540. spxConnPopFromPktList(
  541. IN PSPX_CONN_FILE * ppSpxConnFile
  542. )
  543. /*++
  544. Routine Description:
  545. !!!MACROIZE!!!
  546. Arguments:
  547. Return Value:
  548. --*/
  549. {
  550. CTELockHandle lockHandle;
  551. // Get the global q lock
  552. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  553. if ((*ppSpxConnFile = SpxPktConnList) != NULL)
  554. {
  555. SpxPktConnList = SpxPktConnList->scf_PktNext;
  556. DBGPRINT(SEND, DBG,
  557. ("SpxConnRemoveFromPkt: %lx\n", *ppSpxConnFile));
  558. }
  559. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  560. return;
  561. }
  562. VOID
  563. spxConnPushIntoRecvList(
  564. IN PSPX_CONN_FILE pSpxConnFile
  565. )
  566. /*++
  567. Routine Description:
  568. !!!MACROIZE!!!
  569. Arguments:
  570. Return Value:
  571. --*/
  572. {
  573. CTELockHandle lockHandle;
  574. // Get the global q lock
  575. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  576. pSpxConnFile->scf_ProcessRecvNext = SpxRecvConnList;
  577. SpxRecvConnList = pSpxConnFile;
  578. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  579. return;
  580. }
  581. VOID
  582. spxConnPopFromRecvList(
  583. IN PSPX_CONN_FILE * ppSpxConnFile
  584. )
  585. /*++
  586. Routine Description:
  587. !!!MACROIZE!!!
  588. Arguments:
  589. Return Value:
  590. --*/
  591. {
  592. CTELockHandle lockHandle;
  593. // Get the global q lock
  594. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  595. if ((*ppSpxConnFile = SpxRecvConnList) != NULL)
  596. {
  597. SpxRecvConnList = SpxRecvConnList->scf_ProcessRecvNext;
  598. DBGPRINT(SEND, INFO,
  599. ("SpxConnRemoveFromRecv: %lx\n", *ppSpxConnFile));
  600. }
  601. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  602. return;
  603. }
  604. #endif
  605. //
  606. // Reference/Dereference routines
  607. //
  608. #if DBG
  609. VOID
  610. SpxConnFileRef(
  611. IN PSPX_CONN_FILE pSpxConnFile
  612. )
  613. /*++
  614. Routine Description:
  615. This routine increments the reference count on an address file.
  616. Arguments:
  617. pSpxConnFile - Pointer to a transport address file object.
  618. Return Value:
  619. none.
  620. --*/
  621. {
  622. CTEAssert ((LONG)pSpxConnFile->scf_RefCount >= 0); // not perfect, but...
  623. (VOID)SPX_ADD_ULONG (
  624. &pSpxConnFile->scf_RefCount,
  625. 1,
  626. &pSpxConnFile->scf_Lock);
  627. } // SpxRefConnectionFile
  628. VOID
  629. SpxConnFileLockRef(
  630. IN PSPX_CONN_FILE pSpxConnFile
  631. )
  632. /*++
  633. Routine Description:
  634. This routine increments the reference count on an address file.
  635. IT IS CALLED WITH THE CONNECTION LOCK HELD.
  636. Arguments:
  637. pSpxConnFile - Pointer to a transport address file object.
  638. Return Value:
  639. none.
  640. --*/
  641. {
  642. CTEAssert ((LONG)pSpxConnFile->scf_RefCount >= 0); // not perfect, but...
  643. (VOID)SPX_ADD_ULONG (
  644. &pSpxConnFile->scf_RefCount,
  645. 1,
  646. &pSpxConnFile->scf_Lock);
  647. } // SpxRefConnectionFileLock
  648. #endif
  649. VOID
  650. SpxConnFileRefByIdLock (
  651. IN USHORT ConnId,
  652. OUT PSPX_CONN_FILE * ppSpxConnFile,
  653. OUT PNTSTATUS pStatus
  654. )
  655. /*++
  656. Routine Description:
  657. !!!MUST BE CALLED WITH THE DEVICE LOCK HELD!!!
  658. All active connections should be on the device active list. Later,
  659. this data structure will be a tree, caching the last accessed
  660. connection.
  661. Arguments:
  662. Return Value:
  663. STATUS_SUCCESS if all is well; STATUS_INVALID_CONNECTION otherwise
  664. --*/
  665. {
  666. PSPX_CONN_FILE pSpxChkConn;
  667. *pStatus = STATUS_SUCCESS;
  668. for (pSpxChkConn =
  669. SpxDevice->dev_GlobalActiveConnList[ConnId & NUM_SPXCONN_HASH_MASK];
  670. pSpxChkConn != NULL;
  671. pSpxChkConn = pSpxChkConn->scf_GlobalActiveNext)
  672. {
  673. if (pSpxChkConn->scf_LocalConnId == ConnId)
  674. {
  675. SpxConnFileReference(pSpxChkConn, CFREF_BYID);
  676. *ppSpxConnFile = pSpxChkConn;
  677. break;
  678. }
  679. }
  680. if (pSpxChkConn == NULL)
  681. {
  682. *pStatus = STATUS_INVALID_CONNECTION;
  683. }
  684. return;
  685. }
  686. VOID
  687. SpxConnFileRefByCtxLock(
  688. IN PSPX_ADDR_FILE pSpxAddrFile,
  689. IN CONNECTION_CONTEXT Ctx,
  690. OUT PSPX_CONN_FILE * ppSpxConnFile,
  691. OUT PNTSTATUS pStatus
  692. )
  693. /*++
  694. Routine Description:
  695. !!!MUST BE CALLED WITH THE ADDRESS LOCK HELD!!!
  696. Returns a referenced connection file with the associated context and
  697. address file desired.
  698. Arguments:
  699. Return Value:
  700. --*/
  701. {
  702. PSPX_CONN_FILE pSpxChkConn = NULL;
  703. BOOLEAN Found = FALSE;
  704. *pStatus = STATUS_SUCCESS;
  705. for (pSpxChkConn = pSpxAddrFile->saf_Addr->sa_InactiveConnList;
  706. pSpxChkConn != NULL;
  707. pSpxChkConn = pSpxChkConn->scf_Next)
  708. {
  709. if ((pSpxChkConn->scf_ConnCtx == Ctx) &&
  710. (pSpxChkConn->scf_AddrFile == pSpxAddrFile))
  711. {
  712. SpxConnFileReference(pSpxChkConn, CFREF_BYCTX);
  713. *ppSpxConnFile = pSpxChkConn;
  714. Found = TRUE;
  715. break;
  716. }
  717. }
  718. if (!Found)
  719. {
  720. *pStatus = STATUS_INVALID_CONNECTION;
  721. }
  722. return;
  723. }
  724. NTSTATUS
  725. SpxConnFileVerify (
  726. IN PSPX_CONN_FILE pConnFile
  727. )
  728. /*++
  729. Routine Description:
  730. This routine is called to verify that the pointer given us in a file
  731. object is in fact a valid address file object. We also verify that the
  732. address object pointed to by it is a valid address object, and reference
  733. it to keep it from disappearing while we use it.
  734. Arguments:
  735. Return Value:
  736. STATUS_SUCCESS if all is well; STATUS_INVALID_CONNECTION otherwise
  737. --*/
  738. {
  739. CTELockHandle LockHandle;
  740. NTSTATUS status = STATUS_SUCCESS;
  741. try
  742. {
  743. if ((pConnFile->scf_Size == sizeof (SPX_CONN_FILE)) &&
  744. (pConnFile->scf_Type == SPX_CONNFILE_SIGNATURE))
  745. {
  746. CTEGetLock (&pConnFile->scf_Lock, &LockHandle);
  747. if (!SPX_CONN_FLAG(pConnFile, SPX_CONNFILE_CLOSING))
  748. {
  749. SpxConnFileLockReference(pConnFile, CFREF_VERIFY);
  750. }
  751. else
  752. {
  753. DBGPRINT(TDI, ERR,
  754. ("StVerifyConnFile: A %lx closing\n", pConnFile));
  755. status = STATUS_INVALID_CONNECTION;
  756. }
  757. CTEFreeLock (&pConnFile->scf_Lock, LockHandle);
  758. }
  759. else
  760. {
  761. DBGPRINT(TDI, ERR,
  762. ("StVerifyAddressFile: AF %lx bad signature\n", pConnFile));
  763. status = STATUS_INVALID_CONNECTION;
  764. }
  765. } except(EXCEPTION_EXECUTE_HANDLER) {
  766. DBGPRINT(TDI, ERR,
  767. ("SpxVerifyConnFile: AF %lx exception\n", pConnFile));
  768. return GetExceptionCode();
  769. }
  770. return status;
  771. } // SpxVerifyConnFile
  772. VOID
  773. SpxConnFileDeref(
  774. IN PSPX_CONN_FILE pSpxConnFile
  775. )
  776. /*++
  777. Routine Description:
  778. This routine dereferences an address file by decrementing the
  779. reference count contained in the structure. If, after being
  780. decremented, the reference count is zero, then this routine calls
  781. SpxDestroyConnectionFile to remove it from the system.
  782. Arguments:
  783. pSpxConnFile - Pointer to a transport address file object.
  784. Return Value:
  785. none.
  786. --*/
  787. {
  788. ULONG oldvalue;
  789. BOOLEAN fDiscNotIndicated = FALSE;
  790. BOOLEAN fIDiscFlag = FALSE;
  791. BOOLEAN fSpx2;
  792. CTEAssert(pSpxConnFile->scf_RefCount > 0);
  793. oldvalue = SPX_ADD_ULONG (
  794. &pSpxConnFile->scf_RefCount,
  795. (ULONG)-1,
  796. &pSpxConnFile->scf_Lock);
  797. CTEAssert (oldvalue > 0);
  798. if (oldvalue == 1)
  799. {
  800. CTELockHandle lockHandleConn, lockHandleAddr, lockHandleDev;
  801. LIST_ENTRY discReqList, *p;
  802. PREQUEST pDiscReq;
  803. PSPX_ADDR_FILE pSpxAddrFile = NULL;
  804. PREQUEST pCloseReq = NULL,
  805. pCleanupReq = NULL,
  806. pConnectReq = NULL;
  807. BOOLEAN fDisassoc = FALSE;
  808. InitializeListHead(&discReqList);
  809. // We may not be associated at this point. Note: When we are active we
  810. // always have a reference. So its not like we execute this code very often.
  811. CTEGetLock(&pSpxConnFile->scf_Lock, &lockHandleConn);
  812. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_ASSOC))
  813. {
  814. pSpxAddrFile = pSpxConnFile->scf_AddrFile;
  815. }
  816. else
  817. {
  818. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_STOPPING))
  819. {
  820. DBGPRINT(TDI, DBG,
  821. ("SpxDerefConnectionFile: Conn cleanup %lx.%lx\n",
  822. pSpxConnFile,
  823. pSpxConnFile->scf_CleanupReq));
  824. // Save this for later completion.
  825. pCleanupReq = pSpxConnFile->scf_CleanupReq;
  826. pSpxConnFile->scf_CleanupReq = NULL;
  827. }
  828. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_CLOSING))
  829. {
  830. DBGPRINT(TDI, DBG,
  831. ("SpxDerefConnectionFile: Conn closing %lx\n",
  832. pSpxConnFile));
  833. // Save this for later completion.
  834. pCloseReq = pSpxConnFile->scf_CloseReq;
  835. //
  836. // Null this out so on a re-entrant case, we dont try to complete this again.
  837. //
  838. pSpxConnFile->scf_CloseReq = NULL;
  839. CTEAssert(pCloseReq != NULL);
  840. }
  841. }
  842. CTEFreeLock (&pSpxConnFile->scf_Lock, lockHandleConn);
  843. if (pSpxAddrFile)
  844. {
  845. CTEGetLock(&SpxDevice->dev_Lock, &lockHandleDev);
  846. CTEGetLock(pSpxAddrFile->saf_AddrLock, &lockHandleAddr);
  847. CTEGetLock(&pSpxConnFile->scf_Lock, &lockHandleConn);
  848. //if (pSpxConnFile->scf_RefCount == 0)
  849. //
  850. // ** The lock passed here is a dummy - it is pre-compiled out.
  851. //
  852. if (SPX_ADD_ULONG(&pSpxConnFile->scf_RefCount, 0, &pSpxConnFile->scf_Lock) == 0)
  853. {
  854. DBGPRINT(TDI, INFO,
  855. ("SpxDerefConnectionFile: Conn is 0 %lx.%lx\n",
  856. pSpxConnFile, pSpxConnFile->scf_Flags));
  857. // All pending requests on this connection are done. See if we
  858. // need to complete the disconnect phase etc.
  859. switch (SPX_MAIN_STATE(pSpxConnFile))
  860. {
  861. case SPX_CONNFILE_DISCONN:
  862. // Disconnect is done. Move connection out of all the lists
  863. // it is on, reset states etc.
  864. DBGPRINT(TDI, INFO,
  865. ("SpxDerefConnectionFile: Conn being inactivated %lx\n",
  866. pSpxConnFile));
  867. // Time to complete disc requests if present.
  868. // There could be multiple of them.
  869. p = pSpxConnFile->scf_DiscLinkage.Flink;
  870. while (p != &pSpxConnFile->scf_DiscLinkage)
  871. {
  872. pDiscReq = LIST_ENTRY_TO_REQUEST(p);
  873. p = p->Flink;
  874. DBGPRINT(TDI, DBG,
  875. ("SpxDerefConnectionFile: Disc on %lx.%lx\n",
  876. pSpxConnFile, pDiscReq));
  877. RemoveEntryList(REQUEST_LINKAGE(pDiscReq));
  878. if (REQUEST_STATUS(pDiscReq) == STATUS_PENDING)
  879. {
  880. REQUEST_STATUS(pDiscReq) = STATUS_SUCCESS;
  881. }
  882. InsertTailList(
  883. &discReqList,
  884. REQUEST_LINKAGE(pDiscReq));
  885. }
  886. //
  887. // Note the state here, and check after the conn has been inactivated.
  888. //
  889. //
  890. // Bug #14354 - odisc and idisc cross each other, leading to double disc to AFD
  891. //
  892. if (!SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_IND_IDISC) &&
  893. !SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_IND_ODISC)) {
  894. fDiscNotIndicated = TRUE;
  895. }
  896. if (SPX_CONN_FLAG2(pSpxConnFile, SPX_CONNFILE2_IDISC)) {
  897. fIDiscFlag = TRUE;
  898. }
  899. fSpx2 = (SPX2_CONN(pSpxConnFile)) ? TRUE : FALSE;
  900. //
  901. // [SA] Bug #14655
  902. // Do not try to inactivate an already inactivated connection
  903. //
  904. if (!(SPX_DISC_STATE(pSpxConnFile) == SPX_DISC_INACTIVATED)) {
  905. spxConnInactivate(pSpxConnFile);
  906. } else {
  907. //
  908. // This is an SPXI connection which has got the local disconnect.
  909. // Reset the flags now.
  910. //
  911. CTEAssert(!fDiscNotIndicated);
  912. SPX_MAIN_SETSTATE(pSpxConnFile, 0);
  913. SPX_DISC_SETSTATE(pSpxConnFile, 0);
  914. SPX_CONN_RESETFLAG(pSpxConnFile, SPX_CONNFILE_IND_IDISC);
  915. }
  916. //
  917. // [SA] If we were waiting for sends to be aborted and did not indicate this
  918. // disconnect to AFD; and AFD did not call a disconnect on this connection,
  919. // then call the disonnect handler now.
  920. //
  921. if (fDiscNotIndicated) {
  922. PVOID pDiscHandlerCtx;
  923. PTDI_IND_DISCONNECT pDiscHandler = NULL;
  924. ULONG discCode = 0;
  925. pDiscHandler = pSpxConnFile->scf_AddrFile->saf_DiscHandler;
  926. pDiscHandlerCtx = pSpxConnFile->scf_AddrFile->saf_DiscHandlerCtx;
  927. // Indicate disconnect to afd.
  928. if (pDiscHandler != NULL) {
  929. //
  930. // If this was an SPXI connection, the disconnect state is still
  931. // DISCONN, so if this routine is re-entered, we need to prevent
  932. // a re-indicate to AFD.
  933. // Also, we need to wait for a local disconnect from AFD since
  934. // we indicated a TDI_DISCONNECT_RELEASE. We bump up the ref count
  935. // in this case.
  936. //
  937. if (!fSpx2) {
  938. CTEAssert( (SPX_MAIN_STATE(pSpxConnFile) == SPX_CONNFILE_DISCONN) &&
  939. (SPX_DISC_STATE(pSpxConnFile) == SPX_DISC_INACTIVATED) );
  940. SPX_CONN_SETFLAG(pSpxConnFile, SPX_CONNFILE_IND_IDISC);
  941. if (fIDiscFlag) {
  942. SpxConnFileLockReference(pSpxConnFile, CFREF_DISCWAITSPX);
  943. SPX_CONN_SETFLAG2(pSpxConnFile, SPX_CONNFILE2_DISC_WAIT);
  944. }
  945. }
  946. CTEFreeLock (&pSpxConnFile->scf_Lock, lockHandleConn);
  947. CTEFreeLock (pSpxAddrFile->saf_AddrLock, lockHandleAddr);
  948. CTEFreeLock (&SpxDevice->dev_Lock, lockHandleDev);
  949. DBGPRINT(CONNECT, INFO,
  950. ("spxDerefConnectionFile: Indicating to afd On %lx when %lx\n",
  951. pSpxConnFile, SPX_MAIN_STATE(pSpxConnFile)));
  952. // First complete all requests waiting for receive completion on
  953. // this conn before indicating disconnect.
  954. spxConnCompletePended(pSpxConnFile);
  955. if (fIDiscFlag) {
  956. //
  957. // Indicate DISCONNECT_RELEASE to AFD so it allows receive of packets
  958. // it has buffered before the remote disconnect took place.
  959. //
  960. discCode = TDI_DISCONNECT_RELEASE;
  961. } else {
  962. //
  963. // [SA] bug #15249
  964. // If not Informed disconnect, indicate DISCONNECT_ABORT to AFD
  965. //
  966. discCode = TDI_DISCONNECT_ABORT;
  967. }
  968. (*pDiscHandler)(
  969. pDiscHandlerCtx,
  970. pSpxConnFile->scf_ConnCtx,
  971. 0, // Disc data
  972. NULL,
  973. 0, // Disc info
  974. NULL,
  975. discCode);
  976. CTEGetLock(&SpxDevice->dev_Lock, &lockHandleDev);
  977. CTEGetLock(pSpxAddrFile->saf_AddrLock, &lockHandleAddr);
  978. CTEGetLock(&pSpxConnFile->scf_Lock, &lockHandleConn);
  979. }
  980. }
  981. --SpxDevice->dev_Stat.OpenConnections;
  982. break;
  983. case SPX_CONNFILE_CONNECTING:
  984. case SPX_CONNFILE_LISTENING:
  985. // Get connect/accept request if present.
  986. pConnectReq = pSpxConnFile->scf_ConnectReq;
  987. pSpxConnFile->scf_ConnectReq = NULL;
  988. spxConnInactivate(pSpxConnFile);
  989. break;
  990. case SPX_CONNFILE_ACTIVE:
  991. KeBugCheck(0);
  992. default:
  993. CTEAssert(SPX_MAIN_STATE(pSpxConnFile) == 0);
  994. break;
  995. }
  996. // If stopping, disassociate from the address file. Complete
  997. // cleanup request.
  998. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_STOPPING))
  999. {
  1000. DBGPRINT(TDI, DBG,
  1001. ("SpxDerefConnectionFile: Conn cleanup %lx.%lx\n",
  1002. pSpxConnFile,
  1003. pSpxConnFile->scf_CleanupReq));
  1004. // Save this for later completion.
  1005. pCleanupReq = pSpxConnFile->scf_CleanupReq;
  1006. pSpxConnFile->scf_CleanupReq = NULL;
  1007. SPX_CONN_RESETFLAG(pSpxConnFile, SPX_CONNFILE_STOPPING);
  1008. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_ASSOC))
  1009. {
  1010. DBGPRINT(TDI, INFO,
  1011. ("SpxDerefConnectionFile: Conn stopping %lx\n",
  1012. pSpxConnFile));
  1013. pSpxAddrFile = pSpxConnFile->scf_AddrFile;
  1014. SPX_CONN_RESETFLAG(pSpxConnFile,SPX_CONNFILE_ASSOC);
  1015. // Dequeue the connection from the address file
  1016. spxConnRemoveFromAssocList(
  1017. &pSpxAddrFile->saf_AssocConnList,
  1018. pSpxConnFile);
  1019. // Dequeue the connection file from the address list. It must
  1020. // be in the inactive list.
  1021. spxConnRemoveFromList(
  1022. &pSpxAddrFile->saf_Addr->sa_InactiveConnList,
  1023. pSpxConnFile);
  1024. DBGPRINT(CREATE, INFO,
  1025. ("SpxConnDerefDisAssociate: %lx from addr file %lx\n",
  1026. pSpxConnFile, pSpxAddrFile));
  1027. fDisassoc = TRUE;
  1028. }
  1029. }
  1030. if (SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_CLOSING))
  1031. {
  1032. DBGPRINT(TDI, DBG,
  1033. ("SpxDerefConnectionFile: Conn closing %lx\n",
  1034. pSpxConnFile));
  1035. // Save this for later completion.
  1036. pCloseReq = pSpxConnFile->scf_CloseReq;
  1037. //
  1038. // Null this out so on a re-entrant case, we dont try to complete this again.
  1039. //
  1040. pSpxConnFile->scf_CloseReq = NULL;
  1041. CTEAssert(pCloseReq != NULL);
  1042. }
  1043. CTEAssert(IsListEmpty(&pSpxConnFile->scf_ReqLinkage));
  1044. CTEAssert(IsListEmpty(&pSpxConnFile->scf_RecvLinkage));
  1045. CTEAssert(IsListEmpty(&pSpxConnFile->scf_DiscLinkage));
  1046. }
  1047. CTEFreeLock (&pSpxConnFile->scf_Lock, lockHandleConn);
  1048. CTEFreeLock (pSpxAddrFile->saf_AddrLock, lockHandleAddr);
  1049. CTEFreeLock (&SpxDevice->dev_Lock, lockHandleDev);
  1050. }
  1051. if (fDisassoc)
  1052. {
  1053. // Remove reference on address for this association.
  1054. SpxAddrFileDereference(pSpxAddrFile, AFREF_CONN_ASSOC);
  1055. }
  1056. if (pConnectReq != (PREQUEST)NULL)
  1057. {
  1058. DBGPRINT(TDI, DBG,
  1059. ("SpxDerefConnectionFile: Connect on %lx req %lx\n",
  1060. pSpxConnFile, pConnectReq));
  1061. // Status will already be set in here. We should be here only if
  1062. // connect is being aborted.
  1063. SpxCompleteRequest(pConnectReq);
  1064. }
  1065. while (!IsListEmpty(&discReqList))
  1066. {
  1067. p = RemoveHeadList(&discReqList);
  1068. pDiscReq = LIST_ENTRY_TO_REQUEST(p);
  1069. DBGPRINT(CONNECT, DBG,
  1070. ("SpxConnFileDeref: DISC REQ %lx.%lx Completing\n",
  1071. pSpxConnFile, pDiscReq));
  1072. SpxCompleteRequest(pDiscReq);
  1073. }
  1074. if (pCleanupReq != (PREQUEST)NULL)
  1075. {
  1076. DBGPRINT(TDI, DBG,
  1077. ("SpxDerefConnectionFile: Cleanup complete %lx req %lx\n",
  1078. pSpxConnFile, pCleanupReq));
  1079. REQUEST_INFORMATION(pCleanupReq) = 0;
  1080. REQUEST_STATUS(pCleanupReq) = STATUS_SUCCESS;
  1081. SpxCompleteRequest (pCleanupReq);
  1082. }
  1083. if (pCloseReq != (PREQUEST)NULL)
  1084. {
  1085. DBGPRINT(TDI, DBG,
  1086. ("SpxDerefConnectionFile: Freed %lx close req %lx\n",
  1087. pSpxConnFile, pCloseReq));
  1088. CTEAssert(pSpxConnFile->scf_RefCount == 0);
  1089. // Remove from the global list
  1090. if (!NT_SUCCESS(spxConnRemoveFromGlobalList(pSpxConnFile)))
  1091. {
  1092. KeBugCheck(0);
  1093. }
  1094. // Free it up.
  1095. SpxFreeMemory (pSpxConnFile);
  1096. REQUEST_INFORMATION(pCloseReq) = 0;
  1097. REQUEST_STATUS(pCloseReq) = STATUS_SUCCESS;
  1098. SpxCompleteRequest (pCloseReq);
  1099. }
  1100. }
  1101. return;
  1102. } // SpxDerefConnectionFile
  1103. VOID
  1104. spxConnReInit(
  1105. IN PSPX_CONN_FILE pSpxConnFile
  1106. )
  1107. /*++
  1108. Routine Description:
  1109. Arguments:
  1110. Return Value:
  1111. --*/
  1112. {
  1113. // Reinit all variables.
  1114. pSpxConnFile->scf_Flags2 = 0;
  1115. pSpxConnFile->scf_GlobalActiveNext = NULL;
  1116. pSpxConnFile->scf_PktNext = NULL;
  1117. pSpxConnFile->scf_CRetryCount = 0;
  1118. pSpxConnFile->scf_WRetryCount = 0;
  1119. pSpxConnFile->scf_RRetryCount = 0;
  1120. pSpxConnFile->scf_RRetrySeqNum = 0;
  1121. pSpxConnFile->scf_CTimerId =
  1122. pSpxConnFile->scf_RTimerId =
  1123. pSpxConnFile->scf_WTimerId =
  1124. pSpxConnFile->scf_TTimerId =
  1125. pSpxConnFile->scf_ATimerId = 0;
  1126. pSpxConnFile->scf_LocalConnId =
  1127. pSpxConnFile->scf_SendSeqNum =
  1128. pSpxConnFile->scf_SentAllocNum =
  1129. pSpxConnFile->scf_RecvSeqNum =
  1130. pSpxConnFile->scf_RetrySeqNum =
  1131. pSpxConnFile->scf_RecdAckNum =
  1132. pSpxConnFile->scf_RemConnId =
  1133. pSpxConnFile->scf_RecdAllocNum = 0;
  1134. #if DBG
  1135. // Initialize so we dont hit breakpoint on seq 0
  1136. pSpxConnFile->scf_PktSeqNum = 0xFFFF;
  1137. #endif
  1138. pSpxConnFile->scf_DataType = 0;
  1139. CTEAssert(IsListEmpty(&pSpxConnFile->scf_ReqLinkage));
  1140. CTEAssert(IsListEmpty(&pSpxConnFile->scf_DiscLinkage));
  1141. CTEAssert(IsListEmpty(&pSpxConnFile->scf_RecvLinkage));
  1142. CTEAssert(pSpxConnFile->scf_RecvListHead == NULL);
  1143. CTEAssert(pSpxConnFile->scf_RecvListTail == NULL);
  1144. CTEAssert(pSpxConnFile->scf_SendListHead == NULL);
  1145. CTEAssert(pSpxConnFile->scf_SendListTail == NULL);
  1146. CTEAssert(pSpxConnFile->scf_SendSeqListHead == NULL);
  1147. CTEAssert(pSpxConnFile->scf_SendSeqListTail == NULL);
  1148. pSpxConnFile->scf_CurRecvReq = NULL;
  1149. pSpxConnFile->scf_CurRecvOffset = 0;
  1150. pSpxConnFile->scf_CurRecvSize = 0;
  1151. pSpxConnFile->scf_ReqPkt = NULL;
  1152. return;
  1153. }
  1154. VOID
  1155. spxConnInactivate(
  1156. IN PSPX_CONN_FILE pSpxConnFile
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. !!! Called with dev/addr/connection lock held !!!
  1161. Arguments:
  1162. This gets us back to associate SAVING the state of the STOPPING and
  1163. CLOSING flags so that dereference can go ahead and finish those.
  1164. Return Value:
  1165. --*/
  1166. {
  1167. BOOLEAN fStopping, fClosing, fAborting;
  1168. fStopping = SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_STOPPING);
  1169. fClosing = SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_CLOSING);
  1170. //
  1171. // [SA] Bug #14655
  1172. // Save the disconnect states so that a proper error can be given in the case of
  1173. // a send after a remote disconnection.
  1174. //
  1175. //
  1176. // Bug #17729
  1177. // Dont retain these flags if a local disconnect has already occured.
  1178. //
  1179. fAborting = (!SPX2_CONN(pSpxConnFile) &&
  1180. !SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_IND_IDISC) &&
  1181. (SPX_MAIN_STATE(pSpxConnFile) == SPX_CONNFILE_DISCONN) &&
  1182. (SPX_DISC_STATE(pSpxConnFile) == SPX_DISC_ABORT));
  1183. #if DBG
  1184. pSpxConnFile->scf_GhostFlags = pSpxConnFile->scf_Flags;
  1185. pSpxConnFile->scf_GhostFlags2 = pSpxConnFile->scf_Flags2;
  1186. pSpxConnFile->scf_GhostRefCount = pSpxConnFile->scf_RefCount;
  1187. #endif
  1188. // Clear all flags, go back to the assoc state. Restore stop/close
  1189. pSpxConnFile->scf_Flags = SPX_CONNFILE_ASSOC;
  1190. SPX_CONN_SETFLAG(pSpxConnFile,
  1191. ((fStopping ? SPX_CONNFILE_STOPPING : 0) |
  1192. (fClosing ? SPX_CONNFILE_CLOSING : 0)));
  1193. //
  1194. // [SA] bug #14655
  1195. // In order to avoid a re-entry, mark connection as SPX_DISC_INACTIVATED
  1196. //
  1197. if (fAborting)
  1198. {
  1199. SPX_MAIN_SETSTATE(pSpxConnFile, SPX_CONNFILE_DISCONN);
  1200. SPX_DISC_SETSTATE(pSpxConnFile, SPX_DISC_INACTIVATED);
  1201. }
  1202. // Remove connection from global list on device
  1203. if (!NT_SUCCESS(spxConnRemoveFromGlobalActiveList(
  1204. pSpxConnFile)))
  1205. {
  1206. KeBugCheck(0);
  1207. }
  1208. // Remove connection from active list on address
  1209. if (!NT_SUCCESS(spxConnRemoveFromList(
  1210. &pSpxConnFile->scf_AddrFile->saf_Addr->sa_ActiveConnList,
  1211. pSpxConnFile)))
  1212. {
  1213. KeBugCheck(0);
  1214. }
  1215. // Put connection in inactive list on address
  1216. SPX_INSERT_ADDR_INACTIVE(
  1217. pSpxConnFile->scf_AddrFile->saf_Addr,
  1218. pSpxConnFile);
  1219. spxConnReInit(pSpxConnFile);
  1220. return;
  1221. }