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.

1682 lines
30 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. assoc.c
  5. Abstract:
  6. THis module contains the functions that deal with associations and
  7. dialogues
  8. Functions:
  9. CommAssocSetUpAssoc
  10. CommAssocFrmStartAssocReq
  11. CommAssocUfmStartAssocReq
  12. CommAssocFrmStopAssocReq
  13. CommAssocUfmStopAssocReq
  14. CommAssocFrmStartAssocRsp
  15. CommAssocUfmStartAssocRsp
  16. CommAssocAllocAssoc
  17. CommAssocAllocDlg
  18. AllocEnt
  19. DeallocEnt
  20. CommAssocDeallocAssoc
  21. CommAssocDeallocDlg
  22. CommAssocInit
  23. CommAssocInsertUdpDlgInTbl
  24. CommAssocDeleteUdpDlgInTbl
  25. CommAssocCreateAssocInTbl
  26. CommAssocDeleteAssocInTbl
  27. CommAssocLookupAssoc
  28. CommAssocInsertAssocInTbl
  29. Portability:
  30. This module is portable
  31. Author:
  32. Pradeep Bahl (PradeepB) 7-Dec-1992
  33. Revision History:
  34. Modification date Person Description of modification
  35. ----------------- ------- ----------------------------
  36. --*/
  37. /*
  38. * Includes
  39. */
  40. #include "wins.h"
  41. #include "nms.h"
  42. #include "comm.h"
  43. #include "assoc.h"
  44. #include "winsque.h"
  45. #include "winsmsc.h"
  46. #include "winsevt.h"
  47. /*
  48. * Local Macro Declarations
  49. */
  50. /*
  51. * Local Typedef Declarations
  52. */
  53. #if PRSCONN
  54. STATIC DWORD sAssocSeqNo = 0;
  55. #else
  56. STATIC DWORD sAssocSeqNo = 1;
  57. #endif
  58. STATIC QUE_HD_T sAssocQueHd;
  59. STATIC CRITICAL_SECTION sAssocListCrtSec;
  60. #if PRSCONN
  61. STATIC DWORD sDlgSeqNo = 0;
  62. #else
  63. STATIC DWORD sDlgSeqNo = 1;
  64. #endif
  65. STATIC QUE_HD_T sDlgQueHd;
  66. STATIC DWORD sNoOfDlgCrtSec; //no of crt. secs in dlgs
  67. STATIC DWORD sNoOfAssocCrtSec; //no of crt. secs in assocs.
  68. STATIC CRITICAL_SECTION sDlgListCrtSec;
  69. STATIC LIST_ENTRY sUdpDlgHead;
  70. COMMASSOC_TAG_POOL_T sTagAssoc; //32bit ULONG -> LPVOID mapping
  71. /*
  72. * Global Variable Definitions
  73. */
  74. /*
  75. Handles to the heaps to be used for assoc. and dlg. allocation
  76. */
  77. HANDLE CommAssocAssocHeapHdl;
  78. HANDLE CommAssocDlgHeapHdl;
  79. HANDLE CommAssocTcpMsgHeapHdl;
  80. /*
  81. Size of the memory for one assoc.
  82. */
  83. DWORD CommAssocAssocSize = 0;
  84. /*
  85. Size of
  86. DWORD CommAssocMaxAssoc = 0;
  87. /*
  88. * Local Variable Definitions
  89. */
  90. STATIC CRITICAL_SECTION sUdpDlgTblCrtSec;
  91. //
  92. // This is the start of the Responder Assoc Table. This table holds the list of
  93. // active Responder associations. Currently, the table is implemented
  94. // as a linked list using the Rtl Linked list functions.
  95. //
  96. QUE_HD_T sRspAssocQueHd;
  97. /*
  98. * Local Function Prototype Declarations
  99. */
  100. /* prototypes for functions local to this module go here */
  101. STATIC
  102. LPVOID
  103. AllocEnt(
  104. HANDLE HeapHdl,
  105. PQUE_HD_T pQueHd,
  106. LPCRITICAL_SECTION pCrtSec,
  107. LPDWORD pSeqNoCntr,
  108. DWORD Size,
  109. LPDWORD pCntCrtSec
  110. );
  111. STATIC
  112. VOID
  113. DeallocEnt(
  114. HANDLE HeapHdl,
  115. PQUE_HD_T pQueHd,
  116. LPCRITICAL_SECTION pCrtSec,
  117. LPDWORD pSeqNoCntr,
  118. LPVOID pHdl,
  119. LPDWORD pCntCrtSec
  120. );
  121. //
  122. // Function definitions start here
  123. //
  124. VOID
  125. CommAssocSetUpAssoc(
  126. IN PCOMM_HDL_T pDlgHdl,
  127. IN PCOMM_ADD_T pAdd,
  128. IN COMM_TYP_E CommTyp_e,
  129. OUT PCOMMASSOC_ASSOC_CTX_T *ppAssocCtx
  130. )
  131. /*++
  132. Routine Description:
  133. This function sets up an association
  134. Arguments:
  135. pDlghdl - Handle to dlg under which an association has to be set up
  136. pAdd - Address of node with which the association has to be set up
  137. CommTyp_e - TYpe of association
  138. ppAssocCtx - Association Context block allocated by the function
  139. Externals Used:
  140. None
  141. Called by:
  142. ECommStartDlg
  143. Comments:
  144. None
  145. Return Value:
  146. Success status codes -- WINS_SUCCESS
  147. Error status codes --
  148. --*/
  149. {
  150. SOCKET SockNo = INVALID_SOCKET;
  151. PCOMMASSOC_ASSOC_CTX_T pAssocCtx = NULL; //v. imp to init this to NULL
  152. INT BytesRead = -1;
  153. MSG_T pTcpMsg;
  154. STATUS RetStat;
  155. WINS_MEM_T WinsMem[2];
  156. PWINS_MEM_T pWinsMem = WinsMem;
  157. #if SUPPORT612WINS > 0
  158. BYTE AssocMsg[COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE];
  159. DWORD MsgLen = COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE;
  160. #else
  161. BYTE AssocMsg[COMMASSOC_ASSOC_MSG_SIZE];
  162. DWORD MsgLen = COMMASSOC_ASSOC_MSG_SIZE;
  163. #endif
  164. PCOMMASSOC_DLG_CTX_T pDlgCtx = pDlgHdl->pEnt;
  165. pWinsMem->pMem = NULL;
  166. try {
  167. /*
  168. * Create a TCP connection to the WINS at the other node
  169. */
  170. CommConnect(
  171. pAdd,
  172. CommWinsTcpPortNo, // WINS_TCP_PORT,
  173. &SockNo
  174. );
  175. /*
  176. * Allocate the assoc context block
  177. */
  178. pAssocCtx = CommAssocAllocAssoc();
  179. pAssocCtx->SockNo = SockNo;
  180. pAssocCtx->uRemAssocCtx = 0;
  181. pAssocCtx->State_e = COMMASSOC_ASSOC_E_NON_EXISTENT;
  182. pAssocCtx->Role_e = COMMASSOC_ASSOC_E_INITIATOR;
  183. pAssocCtx->Typ_e = CommTyp_e;
  184. pAssocCtx->DlgHdl = *pDlgHdl;
  185. pAssocCtx->RemoteAdd.sin_addr.s_addr = pAdd->Add.IPAdd;
  186. pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
  187. /*
  188. Format the start association message.
  189. The address passed to the formatting function is offset
  190. from the address of the buffer by a LONG so that CommSendAssoc
  191. can store the length of the message in it.
  192. */
  193. CommAssocFrmStartAssocReq(
  194. pAssocCtx,
  195. AssocMsg + sizeof(LONG),
  196. MsgLen - sizeof(LONG)
  197. );
  198. pDlgCtx->AssocHdl.pEnt = pAssocCtx;
  199. pDlgCtx->AssocHdl.SeqNo = pAssocCtx->Top.SeqNo;
  200. /*
  201. * send the message on the TCP connection
  202. */
  203. CommSendAssoc(
  204. pAssocCtx->SockNo,
  205. AssocMsg + sizeof(LONG),
  206. MsgLen - sizeof(LONG)
  207. );
  208. /*
  209. Read in the response message
  210. */
  211. RetStat = CommReadStream(
  212. pAssocCtx->SockNo,
  213. TRUE, // do timed wait
  214. &pTcpMsg,
  215. &BytesRead
  216. );
  217. /*
  218. If the return status is not WINS_SUCCESS or bytes read are 0, then
  219. either it is a disconnect or the read timed out. Raise an exception.
  220. (We should have gotten either a start or a stop assoc. message.
  221. */
  222. if ((BytesRead != 0) && (RetStat == WINS_SUCCESS))
  223. {
  224. DWORD Opc;
  225. DWORD MsgTyp;
  226. ULONG uNoNeed;
  227. pWinsMem->pMem = pTcpMsg - sizeof(LONG) - COMM_BUFF_HEADER_SIZE;
  228. (++pWinsMem)->pMem = NULL;
  229. /*
  230. * unformat the response
  231. */
  232. COMM_GET_HEADER_M(pTcpMsg, Opc, uNoNeed, MsgTyp);
  233. /*
  234. * if MsgTyp indicates that it is a start assoc. response
  235. * message, change state of association to Active; return
  236. * success
  237. */
  238. if (MsgTyp == COMM_START_RSP_ASSOC_MSG)
  239. {
  240. CommAssocUfmStartAssocRsp(
  241. pTcpMsg,
  242. &pAssocCtx->MajVersNo,
  243. &pAssocCtx->MinVersNo,
  244. &pAssocCtx->uRemAssocCtx
  245. );
  246. pAssocCtx->State_e = COMMASSOC_ASSOC_E_ACTIVE;
  247. #if SUPPORT612WINS > 0
  248. //
  249. // If bytes read are less than what a post-beta1
  250. // WINS sends us, it means that it must be a beta1 WINS.
  251. //
  252. if (BytesRead >= (COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE - sizeof(LONG)))
  253. {
  254. #if 0
  255. pAssocCtx->MajVersNo = WINS_BETA2_MAJOR_VERS_NO;
  256. pAssocCtx->MinVersNo = 1; //not used currently
  257. #endif
  258. }
  259. else
  260. {
  261. pAssocCtx->MajVersNo = WINS_BETA1_MAJOR_VERS_NO;
  262. pAssocCtx->MinVersNo = 1; //not used currently
  263. }
  264. #endif
  265. }
  266. //
  267. // Let us free the message that we received
  268. //
  269. ECommFreeBuff(pTcpMsg);
  270. /*
  271. * if opcode indicates that it is a stop assoc. message, do
  272. * cleanup; return failure
  273. */
  274. if (MsgTyp == COMM_STOP_REQ_ASSOC_MSG)
  275. {
  276. //
  277. // Decrement conn. count
  278. //
  279. CommDecConnCount();
  280. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  281. }
  282. }
  283. else // Either Bytes Read are 0 or select timed out or some other error
  284. // occurred
  285. {
  286. WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
  287. }
  288. }
  289. except (EXCEPTION_EXECUTE_HANDLER) {
  290. DWORD ExcCode = GetExceptionCode();
  291. DBGPRINTEXC("CommAssocSetUpAssoc");
  292. //
  293. // If the exception occurred after the socket was opened, close it
  294. //
  295. if (SockNo != INVALID_SOCKET)
  296. {
  297. CommDisc(SockNo, TRUE); // close the socket
  298. }
  299. //
  300. // if an assoc. ctx block was allocated, free it now
  301. //
  302. if (pAssocCtx != NULL)
  303. {
  304. CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
  305. CommAssocDeallocAssoc(pAssocCtx);
  306. }
  307. //
  308. // reraise the exception
  309. //
  310. WINS_HDL_EXC_N_RERAISE_M(WinsMem);
  311. } //end of except {..}
  312. *ppAssocCtx = pAssocCtx;
  313. return;
  314. } //CommAssocSetUpAssoc()
  315. VOID
  316. CommAssocFrmStartAssocReq(
  317. IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
  318. IN MSG_T pMsg,
  319. IN MSG_LEN_T MsgLen
  320. )
  321. /*++
  322. Routine Description:
  323. This function is called to format a start association message
  324. Arguments:
  325. pAssocCtx - Association Context block
  326. pMsg - Buffer containing the formatted start assoc. req. msg.
  327. MsgLen - Size of the above buffer
  328. Externals Used:
  329. None
  330. Return Value:
  331. None
  332. Error Handling:
  333. Called by:
  334. CommAssocSetUpAssoc
  335. Side Effects:
  336. Comments:
  337. None
  338. --*/
  339. {
  340. ULONG *pLong = NULL;
  341. /*
  342. The start assoc. message contains the following fields
  343. the assoc handle (ptr field)
  344. Version Number (major and minor) both are 16 bits
  345. Authentication Info (currently nothing)
  346. Association Type (an integer)
  347. */
  348. pLong = (LPLONG)pMsg;
  349. COMM_SET_HEADER_M(
  350. pLong,
  351. WINS_IS_NOT_NBT, //opcode
  352. 0, /*We don't have the remote guy's assoc. ptr yet*/
  353. COMM_START_REQ_ASSOC_MSG //msg type
  354. );
  355. *pLong++ = htonl(pAssocCtx->nTag);
  356. *pLong++ = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
  357. *pLong = htonl(pAssocCtx->Typ_e); //assoc type
  358. return;
  359. }
  360. VOID
  361. CommAssocUfmStartAssocReq(
  362. IN MSG_T pMsg,
  363. OUT PCOMM_TYP_E pAssocTyp_e,
  364. OUT LPDWORD pMajorVer,
  365. OUT LPDWORD pMinorVer,
  366. OUT ULONG *puRemAssocCtx
  367. )
  368. /*++
  369. Routine Description:
  370. This function parses the start association message that arrives on
  371. a TCP connection and returns with the relevant information
  372. Arguments:
  373. pMsg -- Message to be unformatted
  374. pAssocTyp_e -- Type of assoc (i.e from who -- replicator, COMSYS, etc)
  375. pMajorVer -- Major version no.
  376. pMinorVer -- Minor version no.
  377. puRemAssocCtx -- ptr to assoc. ctx block of remote WINS
  378. Externals Used:
  379. None
  380. Return Value:
  381. None
  382. Error Handling:
  383. Called by:
  384. ProcTcpMsg
  385. Side Effects:
  386. Comments:
  387. None
  388. --*/
  389. {
  390. /*
  391. Increment pLong past the comm header
  392. */
  393. LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
  394. LONG lTmp;
  395. *puRemAssocCtx = ntohl(*pLong++);
  396. //ptr to assoc. ctx at remote WINS
  397. /*
  398. * Get the long that contains the major and minor version numbers
  399. */
  400. lTmp = ntohl(*pLong++);
  401. *pMajorVer = lTmp >> 16; //Major vers. no.
  402. *pMinorVer = lTmp & 0x0ff; //Minor vers. no.
  403. *pAssocTyp_e = ntohl(*pLong); /*Msg type (from who -- COMSYS,
  404. Replicator
  405. */
  406. return;
  407. }
  408. VOID
  409. CommAssocFrmStopAssocReq(
  410. IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
  411. IN MSG_T pMsg,
  412. IN MSG_LEN_T MsgLen,
  413. IN COMMASSOC_STP_RSN_E StopRsn_e
  414. )
  415. /*++
  416. Routine Description:
  417. This function formats a stop association message
  418. Arguments:
  419. pAssocCtx -- Assoc. Ctx block.
  420. pMsg -- Buffer containing the formatted stop assoc. req. msg.
  421. MsgLen -- Length of above buffer
  422. StopRsn_e -- Reason why the association is being stopped
  423. Externals Used:
  424. None
  425. Return Value:
  426. None
  427. Error Handling:
  428. Called by:
  429. CommAssocSetUpAssoc
  430. Side Effects:
  431. Comments:
  432. None
  433. --*/
  434. {
  435. unsigned long *pLong = NULL;
  436. /*
  437. The stop assoc. message contains the following fields
  438. the reason for the stop/abort.
  439. */
  440. pLong = (LPLONG)pMsg;
  441. COMM_SET_HEADER_M(
  442. pLong,
  443. WINS_IS_NOT_NBT,
  444. pAssocCtx->uRemAssocCtx,
  445. COMM_STOP_REQ_ASSOC_MSG
  446. );
  447. *pLong = htonl(StopRsn_e);
  448. return;
  449. }
  450. VOID
  451. CommUfmStopAssocReq(
  452. IN MSG_T pMsg,
  453. OUT PCOMMASSOC_STP_RSN_E pStopRsn_e
  454. )
  455. /*++
  456. Routine Description:
  457. This function formats a stop association message
  458. Arguments:
  459. pMsg - Message containing the stop assoc. req.
  460. pStopRsn_e - reason why the association was stopped
  461. Externals Used:
  462. None
  463. Return Value:
  464. None
  465. Error Handling:
  466. Called by:
  467. ProcTcpMsg
  468. Side Effects:
  469. Comments:
  470. None
  471. --*/
  472. {
  473. /*
  474. Increment pLong past the comm header
  475. */
  476. LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
  477. *pStopRsn_e = ntohl(*pLong);
  478. return;
  479. }
  480. VOID
  481. CommAssocFrmStartAssocRsp(
  482. IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
  483. IN MSG_T pMsg,
  484. IN MSG_LEN_T MsgLen
  485. )
  486. /*++
  487. Routine Description:
  488. This function is called to format a start association response message
  489. Arguments:
  490. pAssocCtx -- Assoc. ctx block
  491. pMsg -- Buffer containing the formatted start assoc. rsp. msg.
  492. MsgLen -- Length of above buffer
  493. Externals Used:
  494. None
  495. Return Value:
  496. None
  497. Error Handling:
  498. Called by:
  499. ProcTcpMsg
  500. Side Effects:
  501. Comments:
  502. None
  503. --*/
  504. {
  505. LPLONG pLong = NULL;
  506. /*
  507. The start assoc. message contains the following fields
  508. the assoc handle (ptr field)
  509. Authentication Info (currently nothing)
  510. */
  511. pLong = (unsigned long *)pMsg;
  512. COMM_SET_HEADER_M(
  513. pLong,
  514. WINS_IS_NOT_NBT,
  515. pAssocCtx->uRemAssocCtx,
  516. COMM_START_RSP_ASSOC_MSG
  517. );
  518. *pLong++ = htonl(pAssocCtx->nTag);
  519. *pLong = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
  520. return;
  521. }
  522. VOID
  523. CommAssocUfmStartAssocRsp(
  524. IN MSG_T pMsg,
  525. OUT LPDWORD pMajorVer,
  526. OUT LPDWORD pMinorVer,
  527. OUT ULONG *puRemAssocCtx
  528. )
  529. /*++
  530. Routine Description:
  531. This function formats a stop association message
  532. Arguments:
  533. pMsg - Buffer containing the Start Assoc. rsp. message
  534. puRemAssocCtx - ptr to remote assoc. ctx block.
  535. Externals Used:
  536. None
  537. Return Value:
  538. None
  539. Error Handling:
  540. Called by:
  541. CommAssocSetUpAssoc
  542. Side Effects:
  543. Comments:
  544. None
  545. --*/
  546. {
  547. /*
  548. Increment pLong past the comm header
  549. */
  550. LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
  551. LONG lTmp;
  552. *puRemAssocCtx = ntohl(*pLong++);
  553. /*
  554. * Get the long that contains the major and minor version numbers
  555. */
  556. lTmp = ntohl(*pLong);
  557. *pMajorVer = lTmp >> 16; //Major vers. no.
  558. *pMinorVer = lTmp & 0xff; //Minor vers. no.
  559. return;
  560. }
  561. LPVOID
  562. CommAssocAllocAssoc(
  563. VOID
  564. )
  565. /*++
  566. Routine Description:
  567. This function allocates an association
  568. Arguments:
  569. None
  570. Externals Used:
  571. None
  572. Return Value:
  573. Success status codes --
  574. Error status codes --
  575. Error Handling:
  576. Called by:
  577. ECommAssocAllocAssoc
  578. Side Effects:
  579. Comments:
  580. None
  581. --*/
  582. {
  583. return(
  584. AllocEnt(
  585. CommAssocAssocHeapHdl,
  586. &sAssocQueHd,
  587. &sAssocListCrtSec,
  588. &sAssocSeqNo,
  589. COMMASSOC_ASSOC_DS_SZ,
  590. &sNoOfAssocCrtSec
  591. )
  592. );
  593. }
  594. LPVOID
  595. CommAssocAllocDlg(
  596. VOID
  597. )
  598. /*++
  599. Routine Description:
  600. This function allocates a dialogue context block
  601. Arguments:
  602. None
  603. Externals Used:
  604. None
  605. Return Value:
  606. None
  607. Error Handling:
  608. Called by:
  609. ECommStartDlg, ProcTcpMsg
  610. Side Effects:
  611. Comments:
  612. None
  613. --*/
  614. {
  615. return(
  616. AllocEnt(
  617. CommAssocDlgHeapHdl,
  618. &sDlgQueHd,
  619. &sDlgListCrtSec,
  620. &sDlgSeqNo,
  621. COMMASSOC_DLG_DS_SZ,
  622. &sNoOfDlgCrtSec
  623. )
  624. );
  625. }
  626. LPVOID
  627. AllocEnt(
  628. IN HANDLE HeapHdl,
  629. IN PQUE_HD_T pQueHd,
  630. IN LPCRITICAL_SECTION pCrtSec,
  631. IN LPDWORD pSeqNoCntr,
  632. IN DWORD Size,
  633. IN LPDWORD pCntOfCrtSec
  634. )
  635. /*++
  636. Routine Description:
  637. This function is used to allocate a ctx. block (association or dlg).
  638. Arguments:
  639. HeapHdl - Heap from where the alloc. muxt be done
  640. pQueHd - Head of free list queue
  641. pCrtSec - Critical section protecting the above queue
  642. pSeqNoCtr - Counter value used to stamp the buffer if it is allocated
  643. as versus when it is taken from the free list
  644. Size - Size of buffer to allocate
  645. Externals Used:
  646. None
  647. Return Value:
  648. Ptr to the block allocated
  649. Error Handling:
  650. Called by:
  651. CommAssocAllocAssoc, CommAssocAllocDlg
  652. Side Effects:
  653. Comments:
  654. --*/
  655. {
  656. PCOMM_TOP_T pTop;
  657. // DWORD Error;
  658. PLIST_ENTRY pHead = &pQueHd->Head;
  659. EnterCriticalSection(pCrtSec);
  660. try {
  661. if (IsListEmpty(pHead))
  662. {
  663. pTop = WinsMscHeapAlloc(
  664. HeapHdl,
  665. Size
  666. );
  667. #ifdef WINSDBG
  668. IF_DBG(HEAP_CNTRS)
  669. {
  670. EnterCriticalSection(&NmsHeapCrtSec);
  671. NmsHeapAllocForList++;
  672. LeaveCriticalSection(&NmsHeapCrtSec);
  673. }
  674. #endif
  675. //
  676. // Init the critical section in the block we just allocated.
  677. //
  678. InitializeCriticalSection(&pTop->CrtSec);
  679. pTop->fCrtSecInited = TRUE;
  680. (*pCntOfCrtSec)++;
  681. pTop->SeqNo = (*pSeqNoCntr)++;
  682. }
  683. else
  684. {
  685. pTop = (PCOMM_TOP_T)RemoveTailList(pHead);
  686. //
  687. // Just took a free entry. Decrement count
  688. //
  689. if (!pTop->fCrtSecInited)
  690. {
  691. InitializeCriticalSection(&pTop->CrtSec);
  692. pTop->fCrtSecInited = TRUE;
  693. (*pCntOfCrtSec)++;
  694. }
  695. }
  696. }
  697. finally {
  698. LeaveCriticalSection(pCrtSec);
  699. }
  700. return(pTop);
  701. }
  702. VOID
  703. DeallocEnt(
  704. IN HANDLE HeapHdl,
  705. IN PQUE_HD_T pQueHd,
  706. IN LPCRITICAL_SECTION pCrtSec,
  707. IN LPDWORD pSeqNoCntr,
  708. IN LPVOID pEnt,
  709. IN LPDWORD pCntOfCrtSec
  710. )
  711. /*++
  712. Routine Description:
  713. The function deallocates a context block
  714. Arguments:
  715. pQueHd - Head of free list queue
  716. pCrtSec - Critical section protecting the above queue
  717. pSeqNoCtr - Counter value used to stamp the buffer before putting
  718. it in the queue.
  719. heap
  720. pEnt - entity to be deallocated
  721. Externals Used:
  722. None
  723. Return Value:
  724. None
  725. Error Handling:
  726. Called by:
  727. CommAssocDeallocDlg, CommAssocDeallocAssoc
  728. Side Effects:
  729. Comments:
  730. None
  731. --*/
  732. {
  733. PCOMM_TOP_T pTop;
  734. PLIST_ENTRY pHead = &pQueHd->Head;
  735. UNREFERENCED_PARAMETER(HeapHdl);
  736. pTop = pEnt;
  737. EnterCriticalSection(pCrtSec);
  738. try {
  739. (*pSeqNoCntr)++;
  740. pTop->SeqNo = *pSeqNoCntr;
  741. InsertTailList(pHead, &pTop->Head);
  742. //
  743. // Delete critical section if necessary to save on non-paged pool
  744. //
  745. if (*pCntOfCrtSec > COMM_FREE_COMM_HDL_THRESHOLD)
  746. {
  747. //
  748. //
  749. // We want to keep the non-paged pool within a limit.
  750. // Deallocate this block. This ensures that we will never
  751. // have more than COMM_FREE_COMM_HDL_THRESHOLD no of dlgs and
  752. // assocs in the free list.
  753. //
  754. DeleteCriticalSection(&pTop->CrtSec);
  755. (*pCntOfCrtSec)--;
  756. pTop->fCrtSecInited = FALSE;
  757. }
  758. } //end of try
  759. finally {
  760. LeaveCriticalSection(pCrtSec);
  761. }
  762. return;
  763. }
  764. VOID
  765. CommAssocDeallocAssoc(
  766. IN LPVOID pAssocCtx
  767. )
  768. /*++
  769. Routine Description:
  770. The function deallocates an association context block
  771. Arguments:
  772. pAssocCtx - Buffer (assoc. ctx block) to deallocate
  773. Externals Used:
  774. None
  775. Return Value:
  776. None
  777. Error Handling:
  778. Called by:
  779. CommAssocDeleteAssocInTbl, CommAssocSetUpAssoc, CommEndAssoc
  780. Side Effects:
  781. Comments:
  782. None
  783. --*/
  784. {
  785. DeallocEnt(
  786. CommAssocAssocHeapHdl,
  787. &sAssocQueHd,
  788. &sAssocListCrtSec,
  789. &sAssocSeqNo,
  790. pAssocCtx,
  791. &sNoOfAssocCrtSec
  792. );
  793. return;
  794. }
  795. VOID
  796. CommAssocDeallocDlg(
  797. IN LPVOID pDlgCtx
  798. )
  799. /*++
  800. Routine Description:
  801. The function deallocates a dialogue context block
  802. Arguments:
  803. pDlgCtx - Buffer (dlg. ctx block) to deallocate
  804. Externals Used:
  805. None
  806. Return Value:
  807. None
  808. Error Handling:
  809. Called by:
  810. RtlDeleteElementGenericTable
  811. Side Effects:
  812. Comments:
  813. None
  814. --*/
  815. {
  816. DeallocEnt(
  817. CommAssocDlgHeapHdl,
  818. &sDlgQueHd,
  819. &sDlgListCrtSec,
  820. &sDlgSeqNo,
  821. pDlgCtx,
  822. &sNoOfDlgCrtSec
  823. );
  824. return;
  825. }
  826. VOID
  827. CommAssocInit(
  828. VOID
  829. )
  830. /*++
  831. Routine Description:
  832. The function is called at init time to initialize the critical sections
  833. and queues for RESPONDER associations and dialogues pertaining to
  834. incoming request datagrams.
  835. Arguments:
  836. None
  837. Externals Used:
  838. None
  839. Return Value:
  840. None
  841. Error Handling:
  842. Called by:
  843. CommInit
  844. Side Effects:
  845. Comments:
  846. None
  847. --*/
  848. {
  849. //
  850. // Initialize the critical sections that guard the lists of
  851. // associations and non-udp dialogues
  852. //
  853. InitializeCriticalSection(&sAssocListCrtSec);
  854. InitializeCriticalSection(&sDlgListCrtSec);
  855. //
  856. // Initialize the critical section for the UDP table
  857. //
  858. InitializeCriticalSection(&sUdpDlgTblCrtSec);
  859. //
  860. // Initialize the list heads for the lists of associations
  861. // and non-udp dialogues
  862. //
  863. InitializeListHead(&sAssocQueHd.Head);
  864. InitializeListHead(&sDlgQueHd.Head);
  865. //
  866. // Initialize the list head for the list of active responder
  867. // associations
  868. //
  869. InitializeListHead(&sRspAssocQueHd.Head);
  870. InitializeListHead(&sUdpDlgHead);
  871. // Initialize the tag variable
  872. InitializeCriticalSection(&sTagAssoc.crtSection);
  873. sTagAssoc.nIdxLimit = 0;
  874. sTagAssoc.nMaxIdx = 0;
  875. sTagAssoc.ppStorage = NULL;
  876. sTagAssoc.pTagPool = NULL;
  877. return;
  878. }
  879. PCOMMASSOC_DLG_CTX_T
  880. CommAssocInsertUdpDlgInTbl(
  881. IN PCOMMASSOC_DLG_CTX_T pCtx,
  882. OUT LPBOOL pfNewElem
  883. )
  884. /*++
  885. Routine Description:
  886. This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
  887. Arguments:
  888. pDlgCtx - Dlg Ctx Block
  889. pfNewElem - flag indicating whether it is a new element
  890. Externals Used:
  891. None
  892. Return Value:
  893. Ptr to the dlg ctx block
  894. Error Handling:
  895. Called by:
  896. Side Effects:
  897. Comments:
  898. None
  899. --*/
  900. {
  901. PCOMMASSOC_DLG_CTX_T pDlgCtx;
  902. EnterCriticalSection(&sUdpDlgTblCrtSec);
  903. try {
  904. pDlgCtx = WINSMSC_INSERT_IN_TBL_M(
  905. &CommUdpNbtDlgTable,
  906. pCtx,
  907. sizeof(COMMASSOC_DLG_CTX_T),
  908. (PBOOLEAN)pfNewElem
  909. );
  910. }
  911. finally {
  912. LeaveCriticalSection(&sUdpDlgTblCrtSec);
  913. }
  914. return(pDlgCtx);
  915. }
  916. VOID
  917. CommAssocDeleteUdpDlgInTbl(
  918. IN PCOMMASSOC_DLG_CTX_T pDlgCtx
  919. )
  920. /*++
  921. Routine Description:
  922. This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
  923. Arguments:
  924. pDlgCtx - Dlg Ctx Block
  925. Externals Used:
  926. None
  927. Return Value:
  928. Ptr to the dlg ctx block
  929. Error Handling:
  930. Called by:
  931. Side Effects:
  932. Comments:
  933. None
  934. --*/
  935. {
  936. BOOLEAN fRetVal;
  937. EnterCriticalSection(&sUdpDlgTblCrtSec);
  938. try {
  939. DBGPRINT0(FLOW, "CommAssocDeleteUdpDlgInTbl:Deleting dlg from table\n");
  940. fRetVal = WINSMSC_DELETE_FRM_TBL_M(
  941. &CommUdpNbtDlgTable,
  942. pDlgCtx
  943. );
  944. if (fRetVal == (BOOLEAN)FALSE)
  945. {
  946. DBGPRINT0(ERR, "CommAssocDeleteUdpDlgInTbl:Could not delete dlg in table\n");
  947. }
  948. }
  949. finally {
  950. LeaveCriticalSection(&sUdpDlgTblCrtSec);
  951. }
  952. return;
  953. }
  954. LPVOID
  955. CommAssocCreateAssocInTbl(
  956. SOCKET SockNo
  957. )
  958. /*++
  959. Routine Description:
  960. This function is called to create an association ctx block for
  961. a tcp connection
  962. Arguments:
  963. SockNo - Socket # of socket mapped to the TCP connection
  964. Externals Used:
  965. sRspAssocQueHd
  966. Return Value:
  967. ptr to the associaton context block created for the TCP connection
  968. Error Handling:
  969. Called by:
  970. MonTcp (TCP listener thread)
  971. Side Effects:
  972. Comments:
  973. None
  974. --*/
  975. {
  976. PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
  977. //
  978. // Allocate/(grab from free list) an association
  979. //
  980. pAssocCtx = CommAssocAllocAssoc();
  981. pAssocCtx->SockNo = SockNo;
  982. pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
  983. CommAssocInsertAssocInTbl(pAssocCtx);
  984. return(pAssocCtx);
  985. }
  986. VOID
  987. CommAssocDeleteAssocInTbl(
  988. PCOMMASSOC_ASSOC_CTX_T pAssocCtx
  989. )
  990. /*++
  991. Routine Description:
  992. This function is called to delete an association context block from
  993. the table of active responder associations. The association ctx.
  994. block is deleted from the table and also deallocated (i.e. put
  995. in the free list)
  996. Arguments:
  997. pAssocCtx - Association context block to delete from a table
  998. Externals Used:
  999. sRspAssocQueHd
  1000. Return Value:
  1001. None
  1002. Error Handling:
  1003. Called by:
  1004. DelAssoc
  1005. Side Effects:
  1006. Comments:
  1007. None
  1008. --*/
  1009. {
  1010. //
  1011. // Unlink the association
  1012. //
  1013. COMMASSOC_UNLINK_RSP_ASSOC_M(pAssocCtx);
  1014. //
  1015. // Dealloc the assoc. so that it can be reused for some other
  1016. // TCP connection
  1017. //
  1018. CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
  1019. CommAssocDeallocAssoc(pAssocCtx);
  1020. return;
  1021. }
  1022. LPVOID
  1023. CommAssocLookupAssoc(
  1024. SOCKET SockNo
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This function is called to lookup an association context block
  1029. corresponding to a socket.
  1030. Arguments:
  1031. SockNo - Socket # of socket whose association context block is
  1032. desired
  1033. Externals Used:
  1034. sRspAssocQueHd
  1035. Return Value:
  1036. ptr to assoc ctx block or NULL if there is no assoc. mapped to the
  1037. socket
  1038. Error Handling:
  1039. Called by:
  1040. DelAssoc
  1041. Side Effects:
  1042. Comments:
  1043. None
  1044. --*/
  1045. {
  1046. PCOMMASSOC_ASSOC_CTX_T pTmp =
  1047. (PCOMMASSOC_ASSOC_CTX_T)sRspAssocQueHd.Head.Flink;
  1048. //
  1049. // If list is empty, return NULL
  1050. //
  1051. if (IsListEmpty(&sRspAssocQueHd.Head))
  1052. {
  1053. return(NULL);
  1054. }
  1055. //
  1056. // Search for the assoc. mapped to socket
  1057. //
  1058. for(
  1059. ;
  1060. pTmp != (PCOMMASSOC_ASSOC_CTX_T)&sRspAssocQueHd ;
  1061. pTmp = NEXT_ASSOC_M(pTmp)
  1062. )
  1063. {
  1064. if (pTmp->SockNo == SockNo)
  1065. {
  1066. return(pTmp);
  1067. }
  1068. }
  1069. //
  1070. // There is no assoc. mapped to socket SockNo. Return NULL
  1071. //
  1072. return(NULL);
  1073. }
  1074. VOID
  1075. CommAssocInsertAssocInTbl(
  1076. PCOMMASSOC_ASSOC_CTX_T pAssocCtx
  1077. )
  1078. /*++
  1079. Routine Description:
  1080. This function is called to insert an association at the head
  1081. of the list of associations currently being monitored
  1082. Arguments:
  1083. pAssocCtx - Assoc. Ctx. Block
  1084. Externals Used:
  1085. None
  1086. Return Value:
  1087. None
  1088. Error Handling:
  1089. Called by:
  1090. CommAssocCreateAssocInTbl, ECommMonDlg
  1091. Side Effects:
  1092. Comments:
  1093. Change to a macro
  1094. --*/
  1095. {
  1096. //
  1097. // Insert at the head of the list of active responder associations
  1098. //
  1099. // Insertion is done at the head of the list in order to optimize
  1100. // the lookup of the association when the first message comes on
  1101. // it from a remote WINS. Since the first message follows on the
  1102. // heels of the connection set up, the search for the association
  1103. // which starts from the head is optimized.
  1104. //
  1105. InsertHeadList(&sRspAssocQueHd.Head, &pAssocCtx->Top.Head);
  1106. return;
  1107. }
  1108. ULONG
  1109. CommAssocTagAlloc(
  1110. PCOMMASSOC_TAG_POOL_T pTag,
  1111. LPVOID pPtrValue
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. This function is used to create a mapping between a generic pointer (32bit/64bit)
  1116. and a 32bit tag.
  1117. Arguments:
  1118. pPtrValue - generic pointer value
  1119. Externals Used:
  1120. TBD
  1121. Return Value:
  1122. None
  1123. --*/
  1124. {
  1125. // a try..finally block is needed just in case the memory reallocation would raise.
  1126. // an exception. In this case, before leaving the try block and the function, the finally
  1127. // block gets executed and leaves cleanly the tag critical section. If this happens
  1128. // the exception will still be passed up the chain (since there is no except block present).
  1129. try
  1130. {
  1131. ULONG newTag;
  1132. DBGPRINT0(FLOW, "Entering CommAssocTagAlloc.\n");
  1133. EnterCriticalSection(&(pTag->crtSection));
  1134. // if nMaxIdx is 0 this means there is no entry available in the Tag pool
  1135. if (pTag->nMaxIdx == 0)
  1136. {
  1137. UINT i;
  1138. // tag pool needs to be enlarged. We might want to check if the buffers have not reached
  1139. // 2^32 entries (highly unlikely)
  1140. ULONG nNewLimit = pTag->nIdxLimit + COMMASSOC_TAG_CHUNK;
  1141. // realloc failures raise exceptions.
  1142. if (pTag->nIdxLimit == 0)
  1143. {
  1144. pTag->ppStorage = (LPVOID*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID));
  1145. pTag->pTagPool = (ULONG*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG));
  1146. }
  1147. else
  1148. {
  1149. WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID), (LPVOID)&(pTag->ppStorage));
  1150. WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG), &(pTag->pTagPool));
  1151. }
  1152. // mark the newly allocated entries as being free for use
  1153. pTag->nMaxIdx = COMMASSOC_TAG_CHUNK;
  1154. for (i = 0; i < pTag->nMaxIdx; i++)
  1155. {
  1156. // tags should be in the range 1... hence the pre-increment op here.
  1157. pTag->pTagPool[i] = ++pTag->nIdxLimit;
  1158. }
  1159. }
  1160. // at this point pTag->nMaxIdx entries are free for use and pTag->nMaxIdx is guaranteed
  1161. // to be greater than 0. The entries free for use have the indices in pTag->pTagPool[0..pTag->nMaxIdx-1]
  1162. // get the newly allocated tag
  1163. newTag = pTag->pTagPool[--pTag->nMaxIdx];
  1164. // map the pointer to this tag into the pointer storage
  1165. pTag->ppStorage[newTag-1] = pPtrValue;
  1166. #ifdef WINSDBG
  1167. // robust programming
  1168. pTag->pTagPool[pTag->nMaxIdx] = 0;
  1169. #endif
  1170. DBGPRINT2(REPL, "TagAlloc: tag for %p is %08x.\n", pPtrValue, newTag);
  1171. // return the newly allocated tag
  1172. return newTag;
  1173. }
  1174. finally
  1175. {
  1176. LeaveCriticalSection(&(pTag->crtSection));
  1177. DBGPRINT0(FLOW, "Leaving CommAssocTagAlloc.\n");
  1178. }
  1179. }
  1180. VOID
  1181. CommAssocTagFree(
  1182. PCOMMASSOC_TAG_POOL_T pTag,
  1183. ULONG nTag
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This function is used to free a mapping between a generic pointer (32bit/64bit)
  1188. and a 32bit tag.
  1189. Arguments:
  1190. nTag - tag value to be freed.
  1191. Externals Used:
  1192. TBD
  1193. Return Value:
  1194. None
  1195. --*/
  1196. {
  1197. DBGPRINT0(FLOW, "Entering CommAssocTagFree.\n");
  1198. EnterCriticalSection(&(pTag->crtSection));
  1199. #ifdef WINSDBG
  1200. // robust programming - just set the corresponding pointer from the storage to NULL
  1201. pTag->ppStorage[nTag-1] = NULL;
  1202. #endif
  1203. // just mark the nTag index as being free for use
  1204. pTag->pTagPool[pTag->nMaxIdx++] = nTag;
  1205. DBGPRINT1(REPL, "TagFree for tag %08x.\n", nTag);
  1206. // 'Free' has to match with 'Alloc' so nMaxIdx can't exceed under no circumstances nIdxLimit
  1207. ASSERT (pTag->nMaxIdx <= pTag->nIdxLimit);
  1208. LeaveCriticalSection(&(pTag->crtSection));
  1209. DBGPRINT0(FLOW, "Leaving CommAssocTagFree.\n");
  1210. }
  1211. LPVOID
  1212. CommAssocTagMap(
  1213. PCOMMASSOC_TAG_POOL_T pTag,
  1214. ULONG nTag
  1215. )
  1216. /*++
  1217. Routine Description:
  1218. This function is used to retrieve a generic pointer (32bit/64bit) that
  1219. is uniquely identified through a 32bit tag.
  1220. Arguments:
  1221. nTag - tag value that identifies the generic pointer.
  1222. Externals Used:
  1223. TBD
  1224. Return Value:
  1225. None
  1226. --*/
  1227. {
  1228. DBGPRINT0(FLOW, "Entering CommAssocTagMap.\n");
  1229. DBGPRINT2(REPL, "TagMap for tag %08x is %p.\n",
  1230. nTag,
  1231. nTag == 0 ? NULL : pTag->ppStorage[nTag-1]);
  1232. // the indices that were given have to fall in the range 0..pTag->nIdxLimit
  1233. ASSERT (nTag <= pTag->nIdxLimit);
  1234. DBGPRINT0(FLOW, "Leaving CommAssocTagMap.\n");
  1235. // return the (64bit) value from pStorage, associated with the nTag provided
  1236. return nTag == 0 ? NULL : pTag->ppStorage[nTag-1];
  1237. }