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.

1726 lines
38 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. queue.c
  5. Abstract:
  6. Contains functions for queuing and dequeuing to/from the various
  7. work queues
  8. Functions:
  9. QueInsertNbtWrkItm
  10. QueRemoveNbtWrkItm
  11. QueInsertChlReqWrkItm
  12. QueRemoveChlReqWrkItm
  13. QueInsertChlRspWrkItm
  14. QueRemoveChlRspWrkItm
  15. QueInsertWrkItm
  16. QueGetWrkItm
  17. QueAllocWrkItm
  18. QueDeallocWrkItm
  19. QueInsertWrkItmAtHdOfList
  20. Portability:
  21. This module is portable
  22. Author:
  23. Pradeep Bahl (pradeepb) 18-Nov-1992
  24. Revision History:
  25. Modification date Person Description of modification
  26. ----------------- ------- ----------------------------
  27. --*/
  28. /*
  29. * Includes
  30. */
  31. #include "wins.h"
  32. #include "comm.h"
  33. //#include "winsque.h"
  34. #include "nms.h"
  35. #include "nmsdb.h"
  36. #include "nmschl.h"
  37. #include "winsmsc.h"
  38. #include "winsevt.h"
  39. #include "rplpush.h"
  40. #include "rplmsgf.h"
  41. #include "winsque.h"
  42. /*
  43. * Local Macro Declarations
  44. */
  45. /*
  46. * Local Typedef Declarations
  47. */
  48. /*
  49. * Global Variable Definitions
  50. */
  51. //
  52. // The various queue heads
  53. //
  54. QUE_HD_T QueNbtWrkQueHd; //head for nbt req queue
  55. #if REG_N_QUERY_SEP > 0
  56. QUE_HD_T QueOtherNbtWrkQueHd; //head for nbt req queue
  57. #endif
  58. DWORD QueOtherNbtWrkQueMaxLen;
  59. QUE_HD_T QueRplPullQueHd; //head for rpl pull thread's queue
  60. QUE_HD_T QueRplPushQueHd; //head for rpl push thread's queue
  61. QUE_HD_T QueNmsNrcqQueHd; //head for challenge queue used by NBT
  62. QUE_HD_T QueNmsRrcqQueHd; //head for challenge queue used by Replicator
  63. QUE_HD_T QueNmsCrqQueHd; //head for response queue to challenges sent
  64. QUE_HD_T QueWinsTmmQueHd; //head for timer manager's queue
  65. QUE_HD_T QueWinsScvQueHd; //head for Scavenger's queue
  66. QUE_HD_T QueInvalidQueHd; //head for an invalid queue
  67. HANDLE QueBuffHeapHdl; //handle to heap for use for nbt queue items
  68. /*
  69. * Local Variable Definitions
  70. */
  71. /*
  72. pWinsQueQueHd
  73. Array indexed by the enumerator QUE_TYP_E values. This array
  74. maps the QUE_TYP_E to the address of the queue head
  75. */
  76. PQUE_HD_T pWinsQueQueHd[QUE_E_TOTAL_NO_QS] = {
  77. &QueNbtWrkQueHd, //nbt requests
  78. #if REG_N_QUERY_SEP > 0
  79. &QueOtherNbtWrkQueHd, //nbt requests
  80. #endif
  81. &QueRplPullQueHd, //Pull requests
  82. &QueRplPushQueHd, //Push requests
  83. &QueNmsNrcqQueHd, //Chl request from nbt thds
  84. &QueNmsRrcqQueHd, //Chl req. from Pull thd
  85. &QueNmsCrqQueHd, //Chl rsp from UDP thd
  86. &QueWinsTmmQueHd, //timer queue
  87. &QueWinsScvQueHd, //Scavenger queue
  88. &QueInvalidQueHd
  89. };
  90. STATIC fsChlWaitForRsp = FALSE;
  91. CHECK("The timer queue may not be a PLIST_ENTRY queue. We may not")
  92. CHECK("just insert the work item at the end")
  93. /*
  94. * Local Function Prototype Declarations
  95. */
  96. STATIC
  97. BOOL
  98. ChlRspDropped(
  99. MSG_T pMsg
  100. );
  101. //
  102. // Function definitions start here
  103. //
  104. STATUS
  105. QueInsertNbtWrkItm(
  106. IN PCOMM_HDL_T pDlgHdl,
  107. IN MSG_T pMsg,
  108. IN MSG_LEN_T MsgLen
  109. )
  110. /*++
  111. Routine Description:
  112. This function inserts a work item on the nbt request queue
  113. Arguments:
  114. pDlgHdl - Handle to dialogue under which the nbt request was received
  115. pMsg - Nbt work item
  116. MsgLen - Size of work item
  117. Externals Used:
  118. None
  119. Return Value:
  120. Success status codes -- WINS_SUCCESS
  121. Error status codes -- WINS_FAILURE
  122. Error Handling:
  123. Called by:
  124. QueNbtReq in nms.c
  125. Side Effects:
  126. Comments:
  127. None
  128. --*/
  129. {
  130. PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
  131. STATUS RetStat;
  132. QueAllocWrkItm(
  133. QueBuffHeapHdl,
  134. sizeof(NBT_REQ_WRK_ITM_T),
  135. (LPVOID *)&pNbtWrkItm
  136. );
  137. pNbtWrkItm->DlgHdl = *pDlgHdl;
  138. pNbtWrkItm->pMsg = pMsg;
  139. pNbtWrkItm->MsgLen = MsgLen;
  140. RetStat = QueInsertWrkItm(
  141. (PLIST_ENTRY)pNbtWrkItm,
  142. QUE_E_NBT_REQ,
  143. NULL /*ptr to que head*/
  144. );
  145. return(RetStat);
  146. }
  147. STATUS
  148. QueRemoveNbtWrkItm(
  149. OUT PCOMM_HDL_T pDlgHdl,
  150. OUT PMSG_T ppMsg,
  151. OUT PMSG_LEN_T pMsgLen
  152. )
  153. /*++
  154. Routine Description:
  155. This function removes a work item from the nbt queue.
  156. Arguments:
  157. pDlgHdl - Handle to dialogue of nbt request dequeued
  158. pMsg - Nbt work item
  159. MsgLen - Size of work item
  160. Externals Used:
  161. None
  162. Return Value:
  163. Success status codes -- WINS_SUCCESS
  164. Error status codes -- WINS_FAILURE
  165. Error Handling:
  166. Called by:
  167. NbtThdInitFn() in nms.c
  168. Side Effects:
  169. Comments:
  170. None
  171. --*/
  172. {
  173. PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
  174. STATUS RetStat;
  175. RetStat = QueGetWrkItm(QUE_E_NBT_REQ, &pNbtWrkItm);
  176. if (RetStat != WINS_SUCCESS)
  177. {
  178. *ppMsg = NULL;
  179. }
  180. else
  181. {
  182. *ppMsg = pNbtWrkItm->pMsg;
  183. *pMsgLen = pNbtWrkItm->MsgLen;
  184. *pDlgHdl = pNbtWrkItm->DlgHdl;
  185. QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
  186. }
  187. return(RetStat);
  188. }
  189. #if REG_N_QUERY_SEP > 0
  190. STATUS
  191. QueInsertOtherNbtWrkItm(
  192. IN PCOMM_HDL_T pDlgHdl,
  193. IN MSG_T pMsg,
  194. IN MSG_LEN_T MsgLen
  195. )
  196. /*++
  197. Routine Description:
  198. This function inserts a work item on the nbt request queue
  199. Arguments:
  200. pDlgHdl - Handle to dialogue under which the nbt request was received
  201. pMsg - Nbt work item
  202. MsgLen - Size of work item
  203. Externals Used:
  204. None
  205. Return Value:
  206. Success status codes -- WINS_SUCCESS
  207. Error status codes -- WINS_FAILURE
  208. Error Handling:
  209. Called by:
  210. QueNbtReq in nms.c
  211. Side Effects:
  212. Comments:
  213. None
  214. --*/
  215. {
  216. PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
  217. STATUS RetStat;
  218. static BOOL SpoofingStarted = FALSE;
  219. QueAllocWrkItm(
  220. QueBuffHeapHdl,
  221. sizeof(NBT_REQ_WRK_ITM_T),
  222. (LPVOID *)&pNbtWrkItm
  223. );
  224. pNbtWrkItm->DlgHdl = *pDlgHdl;
  225. pNbtWrkItm->pMsg = pMsg;
  226. pNbtWrkItm->MsgLen = MsgLen;
  227. RetStat = QueInsertWrkItm(
  228. (PLIST_ENTRY)pNbtWrkItm,
  229. QUE_E_OTHER_NBT_REQ,
  230. NULL /*ptr to que head*/
  231. );
  232. //
  233. // If the queue is full, the request was not inserted, so
  234. // drop it. Log an event after every 100 requests have
  235. // been dropped
  236. //
  237. if (RetStat == WINS_QUEUE_FULL)
  238. {
  239. static DWORD sNoOfReqSpoofed = 0;
  240. static DWORD sBlockOfReq = 1;
  241. #if DBG
  242. static DWORD sNoOfReqDropped = 0;
  243. #endif
  244. if (!WinsCnf.fDoSpoofing)
  245. {
  246. #if DBG
  247. NmsRegReqQDropped++;
  248. if (sNoOfReqDropped++ == 5000)
  249. {
  250. sNoOfReqDropped = 0;
  251. DBGPRINT1(ERR, "ENmsHandleMsg: REG QUEUE FULL. REQUESTS DROPPED = (%d\n", NmsRegReqQDropped);
  252. }
  253. #endif
  254. //
  255. // NOTE : freeing the buffers here takes away from modularity aspects
  256. // of code but saves us cycles on the critical path
  257. //
  258. ECommFreeBuff(pMsg);
  259. ECommEndDlg(pDlgHdl);
  260. }
  261. else
  262. {
  263. //
  264. // we respond to groups of 300
  265. // refresh/reg requests with a refresh interval of a multiple of
  266. // 5 mts. The multiple is based on the group #. The refresh interval
  267. // is not allowed to go over 1-2 hrs .
  268. //
  269. if (sNoOfReqSpoofed > 100)
  270. {
  271. if (sBlockOfReq == 10)
  272. {
  273. sBlockOfReq = 1;
  274. }
  275. else
  276. {
  277. sBlockOfReq++;
  278. }
  279. sNoOfReqSpoofed = 0;
  280. }
  281. else
  282. {
  283. sNoOfReqSpoofed++;
  284. }
  285. if (!SpoofingStarted)
  286. {
  287. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_SPOOFING_STARTED);
  288. SpoofingStarted = TRUE;
  289. }
  290. DBGPRINT1(DET, "QueInsertOtherNbtWrkItm: Spoofing - SpoofBlockNum %d\n", sBlockOfReq);
  291. NmsMsgfSndNamRsp(pDlgHdl, pMsg, MsgLen, sBlockOfReq);
  292. }
  293. QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
  294. }
  295. if ((WINS_SUCCESS == RetStat) && SpoofingStarted && QueOtherNbtWrkQueHd.NoOfEntries < (QueOtherNbtWrkQueMaxLen >> 2))
  296. {
  297. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_SPOOFING_COMPLETED);
  298. SpoofingStarted = FALSE;
  299. }
  300. return(RetStat);
  301. }
  302. STATUS
  303. QueRemoveOtherNbtWrkItm(
  304. OUT PCOMM_HDL_T pDlgHdl,
  305. OUT PMSG_T ppMsg,
  306. OUT PMSG_LEN_T pMsgLen
  307. )
  308. /*++
  309. Routine Description:
  310. This function removes a work item from the nbt queue.
  311. Arguments:
  312. pDlgHdl - Handle to dialogue of nbt request dequeued
  313. pMsg - Nbt work item
  314. MsgLen - Size of work item
  315. Externals Used:
  316. None
  317. Return Value:
  318. Success status codes -- WINS_SUCCESS
  319. Error status codes -- WINS_FAILURE
  320. Error Handling:
  321. Called by:
  322. NbtThdInitFn() in nms.c
  323. Side Effects:
  324. Comments:
  325. None
  326. --*/
  327. {
  328. PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
  329. STATUS RetStat;
  330. RetStat = QueGetWrkItm(QUE_E_OTHER_NBT_REQ, &pNbtWrkItm);
  331. if (RetStat != WINS_SUCCESS)
  332. {
  333. *ppMsg = NULL;
  334. }
  335. else
  336. {
  337. *ppMsg = pNbtWrkItm->pMsg;
  338. *pMsgLen = pNbtWrkItm->MsgLen;
  339. *pDlgHdl = pNbtWrkItm->DlgHdl;
  340. QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
  341. }
  342. return(RetStat);
  343. }
  344. #endif
  345. STATUS
  346. QueInsertChlReqWrkItm(
  347. IN NMSCHL_CMD_TYP_E CmdTyp_e,
  348. IN WINS_CLIENT_E Client_e,
  349. IN PCOMM_HDL_T pDlgHdl,
  350. IN MSG_T pMsg,
  351. IN MSG_LEN_T MsgLen,
  352. IN DWORD QuesNamSecLen,
  353. IN PNMSDB_ROW_INFO_T pNodeToReg,
  354. IN PNMSDB_STAT_INFO_T pNodeInCnf,
  355. //IN PCOMM_ADD_T pAddOfNodeInCnf,
  356. IN PCOMM_ADD_T pAddOfRemWins
  357. )
  358. /*++
  359. Routine Description:
  360. This function inserts a work item on the nbt request queue
  361. Arguments:
  362. pDlgHdl - Handle to dialogue under which the nbt request was received
  363. pMsg - Nbt work item
  364. MsgLen - Size of work item
  365. Externals Used:
  366. None
  367. Return Value:
  368. Success status codes -- WINS_SUCCESS
  369. Error status codes -- WINS_FAILURE
  370. Error Handling:
  371. Called by:
  372. NmsChlHdlNamReg
  373. Side Effects:
  374. Comments:
  375. None
  376. --*/
  377. {
  378. PCHL_REQ_WRK_ITM_T pWrkItm = NULL;
  379. STATUS RetStat = WINS_SUCCESS;
  380. DWORD Error = 0;
  381. BOOL fLvCrtSec = FALSE;
  382. DWORD i;
  383. QueAllocWrkItm(
  384. NmsChlHeapHdl,
  385. sizeof(CHL_REQ_WRK_ITM_T),
  386. (LPVOID *)&pWrkItm
  387. );
  388. pWrkItm->CmdTyp_e = CmdTyp_e;
  389. pWrkItm->Client_e = Client_e;
  390. if (pDlgHdl != NULL)
  391. {
  392. pWrkItm->DlgHdl = *pDlgHdl;
  393. }
  394. pWrkItm->pMsg = pMsg;
  395. pWrkItm->MsgLen = MsgLen;
  396. pWrkItm->QuesNamSecLen = QuesNamSecLen;
  397. pWrkItm->NodeToReg = *pNodeToReg;
  398. pWrkItm->NodeAddsInCnf.NoOfMems = pNodeInCnf->NodeAdds.NoOfMems;
  399. for (i=0; i < pNodeInCnf->NodeAdds.NoOfMems; i++)
  400. {
  401. pWrkItm->NodeAddsInCnf.Mem[i] = pNodeInCnf->NodeAdds.Mem[i];
  402. }
  403. pWrkItm->NoOfAddsToUse = pNodeInCnf->NodeAdds.NoOfMems;
  404. pWrkItm->NoOfAddsToUseSv = pNodeInCnf->NodeAdds.NoOfMems;
  405. pWrkItm->OwnerIdInCnf = pNodeInCnf->OwnerId;
  406. pWrkItm->fGroupInCnf = NMSDB_ENTRY_GRP_M(pNodeInCnf->EntTyp);
  407. // pWrkItm->NodeTypInCnf = pNodeInCnf->NodeTyp;
  408. // pWrkItm->EntTypInCnf = pNodeInCnf->EntTyp;
  409. if (pNodeToReg->pNodeAdd != NULL)
  410. {
  411. pWrkItm->AddToReg = *(pNodeToReg->pNodeAdd);
  412. }
  413. if (pAddOfRemWins != NULL)
  414. {
  415. pWrkItm->AddOfRemWins = *pAddOfRemWins;
  416. }
  417. switch(Client_e)
  418. {
  419. case(WINS_E_NMSNMH):
  420. pWrkItm->QueTyp_e = QUE_E_NMSNRCQ;
  421. break;
  422. case(WINS_E_RPLPULL):
  423. pWrkItm->QueTyp_e = QUE_E_NMSRRCQ;
  424. break;
  425. default:
  426. DBGPRINT0(ERR, "QueInsertChlWrkItm: Invalid Client\n");
  427. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  428. break;
  429. }
  430. RetStat = QueInsertWrkItm(
  431. (PLIST_ENTRY)pWrkItm,
  432. pWrkItm->QueTyp_e,
  433. NULL /*ptr to que head*/
  434. );
  435. return(RetStat);
  436. }
  437. STATUS
  438. QueRemoveChlReqWrkItm(
  439. IN HANDLE EvtHdl,
  440. IN OUT LPVOID *ppaWrkItm,
  441. OUT LPDWORD pNoOfReqs
  442. )
  443. /*++
  444. Routine Description:
  445. This function removes a work item from the nbt queue.
  446. Arguments:
  447. EvtHdl - handle of event signaled (not used currently)
  448. ppaWrkItm - pointer to array of pointers (to work items) to
  449. initialize
  450. pNoOfReqs - No of Requests acquired (in the array pointed by
  451. the ppaWrkItm arg
  452. Externals Used:
  453. None
  454. Return Value:
  455. Success status codes -- WINS_SUCCESS
  456. Error status codes -- WINS_FAILURE
  457. Error Handling:
  458. Called by:
  459. ChlThdInitFn() in nmschl.c
  460. Side Effects:
  461. Comments:
  462. None
  463. --*/
  464. {
  465. STATUS RetStat = WINS_SUCCESS;
  466. PQUE_HD_T pQueHd;
  467. UNREFERENCED_PARAMETER(EvtHdl);
  468. *pNoOfReqs = 0;
  469. //
  470. // EvtHdl is the handle of the event signaled. We don't use
  471. // it since we always need to check the queues in the sequence
  472. // Nrcq, Rrcq, Srcq irrespective of the event that got signaled.
  473. //
  474. // EvtHdl is passed as an input argument for future extensibility
  475. //
  476. // We could have had one critical section for both the queues but that
  477. // could slow NBT threads due to replication. We don't
  478. // want that.
  479. //
  480. //
  481. // First check the NBT Request challenge queue
  482. //
  483. pQueHd = &QueNmsNrcqQueHd;
  484. EnterCriticalSection(&pQueHd->CrtSec);
  485. try {
  486. //
  487. // We have a limit to the number of nodes
  488. // we will challenge at any one time
  489. //
  490. while (
  491. (!IsListEmpty(&pQueHd->Head)) &&
  492. (*pNoOfReqs < NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
  493. )
  494. {
  495. *ppaWrkItm++ = RemoveHeadList(&pQueHd->Head);
  496. (*pNoOfReqs)++;
  497. }
  498. }
  499. finally {
  500. LeaveCriticalSection(&pQueHd->CrtSec);
  501. }
  502. //
  503. // if we have reached the limit return
  504. //
  505. if (*pNoOfReqs == NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
  506. {
  507. DBGPRINT0(CHL, "QueRemoveChlReqWrkItm: Limit reached with just nbt requests\n");
  508. *ppaWrkItm = NULL; //delimiter to the list
  509. return(WINS_SUCCESS);
  510. }
  511. //
  512. // Now check the Replicator request challenge queue (populated
  513. // by the Pull handler
  514. //
  515. pQueHd = &QueNmsRrcqQueHd;
  516. EnterCriticalSection(&pQueHd->CrtSec);
  517. try {
  518. while(
  519. (!IsListEmpty(&pQueHd->Head)) &&
  520. (*pNoOfReqs < NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
  521. )
  522. {
  523. *ppaWrkItm++ = RemoveHeadList(&pQueHd->Head);
  524. (*pNoOfReqs)++;
  525. }
  526. }
  527. finally {
  528. LeaveCriticalSection(&pQueHd->CrtSec);
  529. }
  530. if (*pNoOfReqs == 0)
  531. {
  532. RetStat = WINS_NO_REQ;
  533. }
  534. else
  535. {
  536. *ppaWrkItm = NULL; //delimiter to the list
  537. }
  538. return(RetStat);
  539. }
  540. STATUS
  541. QueInsertChlRspWrkItm(
  542. IN PCOMM_HDL_T pDlgHdl,
  543. IN MSG_T pMsg,
  544. IN MSG_LEN_T MsgLen
  545. )
  546. /*++
  547. Routine Description:
  548. This function inserts a work item on the challenge response queue
  549. Arguments:
  550. pDlgHdl - Handle to dialogue under which the nbt response was received
  551. pMsg - response message
  552. MsgLen - response msg length
  553. Externals Used:
  554. None
  555. Return Value:
  556. Success status codes -- WINS_SUCCESS
  557. Error status codes -- WINS_FAILURE
  558. Error Handling:
  559. Called by:
  560. ENmsHdlMsg in nms.c
  561. Side Effects:
  562. Comments:
  563. None
  564. --*/
  565. {
  566. PCHL_REQ_WRK_ITM_T pWrkItm = NULL;
  567. STATUS RetStat = WINS_SUCCESS;
  568. DWORD Error = 0;
  569. if (!ChlRspDropped(pMsg))
  570. {
  571. QueAllocWrkItm(
  572. NmsChlHeapHdl,
  573. sizeof(CHL_RSP_WRK_ITM_T),
  574. (LPVOID *)&pWrkItm
  575. );
  576. pWrkItm->DlgHdl = *pDlgHdl;
  577. pWrkItm->pMsg = pMsg;
  578. pWrkItm->MsgLen = MsgLen;
  579. RetStat = QueInsertWrkItm(
  580. (PLIST_ENTRY)pWrkItm,
  581. QUE_E_NMSCRQ,
  582. NULL /*ptr to que head*/
  583. );
  584. }
  585. return(RetStat);
  586. }
  587. STATUS
  588. QueRemoveChlRspWrkItm(
  589. IN LPVOID *ppWrkItm
  590. )
  591. /*++
  592. Routine Description:
  593. This function removes a work item from the nbt queue.
  594. Arguments:
  595. ppaWrkItm - address of an array of pointers to chl request work items
  596. Externals Used:
  597. None
  598. Return Value:
  599. Success status codes -- WINS_SUCCESS
  600. Error status codes -- WINS_FAILURE
  601. Error Handling:
  602. Called by:
  603. ChlThdInitFn() in nmschl.c
  604. Side Effects:
  605. Comments:
  606. None
  607. --*/
  608. {
  609. STATUS RetStat;
  610. RetStat = QueGetWrkItm(QUE_E_NMSCRQ, ppWrkItm);
  611. return(RetStat);
  612. }
  613. STATUS
  614. QueInsertWrkItm (
  615. IN PLIST_ENTRY pWrkItm,
  616. IN OPTIONAL QUE_TYP_E QueTyp_e,
  617. IN OPTIONAL PQUE_HD_T pQueHdPassed
  618. )
  619. /*++
  620. Routine Description:
  621. This function is called to queue a work item on
  622. a queue. If the pQueHdPassed is Non NULL, the work item is queued
  623. on that queue, else, it is queued on the queue specified by
  624. QueTyp_e.
  625. TMM will use pQueHdPassed to specify the queue while other clients
  626. of the queue services will specify QueTyp_e
  627. Arguments:
  628. pWrkItm - Work Item to queue
  629. QueTyp_e - Type of queue to queue it on (may or may not have valid value)
  630. pQueHdPassed - Head of queue (may or may not be passed)
  631. Externals Used:
  632. None
  633. Return Value:
  634. Success status codes -- WINS_SUCCESS
  635. Error status codes -- WINS_FAILURE
  636. Error Handling:
  637. Called by:
  638. ERplInsertQue, QueInsertNbtWrkItm
  639. Side Effects:
  640. Comments:
  641. None
  642. --*/
  643. {
  644. STATUS RetStat = WINS_SUCCESS;
  645. PQUE_HD_T pQueHd = NULL;
  646. // DWORD Error;
  647. if (pQueHdPassed == NULL)
  648. {
  649. pQueHd = pWinsQueQueHd[QueTyp_e];
  650. }
  651. else
  652. {
  653. pQueHd = pQueHdPassed;
  654. }
  655. EnterCriticalSection(&pQueHd->CrtSec);
  656. try {
  657. //
  658. // If we are surpassing the limit in the Reg/Ref/Rel queue,
  659. // don't insert the wrk. item.
  660. //
  661. if ((pQueHd == &QueOtherNbtWrkQueHd) &&
  662. (pQueHd->NoOfEntries > QueOtherNbtWrkQueMaxLen))
  663. {
  664. RetStat = WINS_QUEUE_FULL;
  665. }
  666. else
  667. {
  668. InsertTailList(&pQueHd->Head, pWrkItm);
  669. pQueHd->NoOfEntries++;
  670. if (!SetEvent(pQueHd->EvtHdl))
  671. {
  672. // Error = GetLastError();
  673. RetStat = WINS_FAILURE;
  674. }
  675. }
  676. }
  677. finally {
  678. LeaveCriticalSection(&pQueHd->CrtSec);
  679. }
  680. return(RetStat);
  681. }
  682. STATUS
  683. QueGetWrkItm (
  684. IN QUE_TYP_E QueTyp_e,
  685. OUT LPVOID *ppWrkItm
  686. )
  687. /*++
  688. Routine Description:
  689. This function is called to dequeue a work item from
  690. a queue
  691. Arguments:
  692. QueTyp_e - Type of queue to get the wrk item from
  693. ppWrkItm - Work Item
  694. Externals Used:
  695. None
  696. Return Value:
  697. Success status codes -- WINS_SUCCESS or WINS_NO_REQ
  698. Error status codes -- None at present
  699. Error Handling:
  700. Called by:
  701. RplPullInit, QueNbtRemoveWrkItm
  702. Side Effects:
  703. Comments:
  704. None
  705. --*/
  706. {
  707. STATUS RetStat = WINS_SUCCESS;
  708. PQUE_HD_T pQueHd;
  709. pQueHd = pWinsQueQueHd[QueTyp_e];
  710. EnterCriticalSection(&pQueHd->CrtSec);
  711. try {
  712. if (IsListEmpty(&pQueHd->Head))
  713. {
  714. *ppWrkItm = NULL;
  715. RetStat = WINS_NO_REQ;
  716. }
  717. else
  718. {
  719. *ppWrkItm = RemoveHeadList(&pQueHd->Head);
  720. pQueHd->NoOfEntries--;
  721. }
  722. }
  723. finally {
  724. LeaveCriticalSection(&pQueHd->CrtSec);
  725. }
  726. return(RetStat);
  727. }
  728. __inline
  729. VOID
  730. QueAllocWrkItm(
  731. IN HANDLE HeapHdl,
  732. IN DWORD Size,
  733. OUT LPVOID *ppBuf
  734. )
  735. /*++
  736. Routine Description:
  737. This function allocates a work item. The work item is allocated
  738. from a heap
  739. Arguments:
  740. ppBuf - Buffer (work item) allocated
  741. Externals Used:
  742. None
  743. Return Value:
  744. None
  745. Error Handling:
  746. Called by:
  747. QueInsertNbtWrkItm
  748. Side Effects:
  749. Comments:
  750. None
  751. --*/
  752. {
  753. //
  754. // WinsMscHeapAlloc will return an exception if it is not able to
  755. // allocate a buffer. So there is no need to check the return value
  756. // for NULL.
  757. //
  758. *ppBuf = WinsMscHeapAlloc(HeapHdl, Size );
  759. return;
  760. }
  761. __inline
  762. VOID
  763. QueDeallocWrkItm(
  764. IN HANDLE HeapHdl,
  765. IN PVOID pBuff
  766. )
  767. /*++
  768. Routine Description:
  769. This function deallcoated a nbt request work item
  770. Arguments:
  771. pBuff - Nbt req. work item to deallocate
  772. Externals Used:
  773. None
  774. Return Value:
  775. Success status codes -- WINS_SUCCESS
  776. Error status codes -- none currently
  777. Error Handling:
  778. Called by:
  779. QueRemoveNbtWrkItm
  780. Side Effects:
  781. Comments:
  782. None
  783. --*/
  784. {
  785. WinsMscHeapFree(
  786. HeapHdl,
  787. pBuff
  788. );
  789. return;
  790. }
  791. STATUS
  792. QueInsertWrkItmAtHdOfList (
  793. IN PLIST_ENTRY pWrkItm,
  794. IN QUE_TYP_E QueTyp_e,
  795. IN PQUE_HD_T pQueHdPassed
  796. )
  797. /*++
  798. Routine Description:
  799. This function is called to queue a work item
  800. at the head of a queue. If the pQueHdPassed is Non NULL,
  801. the work item is queued on that queue, else, it is queued on
  802. the queue specified by QueTyp_e.
  803. TMM will use pQueHdPassed to specify the queue while other clients
  804. of the queue services will specify QueTyp_e
  805. Arguments:
  806. pWrlItm - Work Item to queue
  807. QueTyp_e - Type of queue to queue it on (may or may not have valid value)
  808. pQueHdPassed - ListHead of queue (may or may not be passed)
  809. Externals Used:
  810. None
  811. Return Value:
  812. Success status codes -- WINS_SUCCESS
  813. Error status codes -- WINS_FAILURE
  814. Error Handling:
  815. Called by:
  816. ProcRsp in nmschl.c
  817. Side Effects:
  818. Comments:
  819. This function differs from QueInsertWrkItm in that it inserts
  820. the work item at the head of a queue versus at the tail. I
  821. prefered to create this function rather than have an extra
  822. argument to QueInsertWrkItm to save an if test. QueInsertWrkItm
  823. is used by the UDP listener thread and I want to do the minimum
  824. work I can in that thread.
  825. --*/
  826. {
  827. FUTURES("I may get rid of this function since it is very similar to QueInsertWrkItm")
  828. STATUS RetStat = WINS_SUCCESS;
  829. PQUE_HD_T pQueHd = NULL;
  830. DWORD Error;
  831. if (pQueHdPassed == NULL)
  832. {
  833. pQueHd = pWinsQueQueHd[QueTyp_e];
  834. }
  835. else
  836. {
  837. pQueHd = pQueHdPassed;
  838. }
  839. EnterCriticalSection(&pQueHd->CrtSec);
  840. try {
  841. InsertHeadList(&pQueHd->Head, pWrkItm);
  842. if (!SetEvent(pQueHd->EvtHdl))
  843. {
  844. Error = GetLastError();
  845. RetStat = WINS_FAILURE;
  846. }
  847. }
  848. finally {
  849. LeaveCriticalSection(&pQueHd->CrtSec);
  850. }
  851. #ifdef WINSDBG
  852. NmsChlNoReqAtHdOfList++;
  853. #endif
  854. return(RetStat);
  855. }
  856. STATUS
  857. QueInsertRplPushWrkItm (
  858. IN PLIST_ENTRY pWrkItm,
  859. IN BOOL fAlreadyInCrtSec
  860. )
  861. /*++
  862. Routine Description:
  863. This function is called to queue a work item on
  864. the Push thread's queue.
  865. Arguments:
  866. pWrkItm - Work Item to queue
  867. Externals Used:
  868. None
  869. Return Value:
  870. Success status codes -- WINS_SUCCESS
  871. Error status codes -- WINS_FAILURE
  872. Error Handling:
  873. Called by:
  874. ERplInsertQue
  875. Side Effects:
  876. Comments:
  877. None
  878. --*/
  879. {
  880. STATUS RetStat = WINS_SUCCESS;
  881. PQUE_HD_T pQueHd = pWinsQueQueHd[QUE_E_RPLPUSH];
  882. //
  883. // if we are already in the critical section, no need to enter it
  884. // again
  885. //
  886. if (!fAlreadyInCrtSec)
  887. {
  888. EnterCriticalSection(&pQueHd->CrtSec);
  889. }
  890. try {
  891. //
  892. // if the push thread does not exist, create it.
  893. //
  894. if (!fRplPushThdExists)
  895. {
  896. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdHdl =
  897. WinsMscCreateThd(
  898. RplPushInit,
  899. NULL,
  900. &WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdId
  901. );
  902. fRplPushThdExists = TRUE;
  903. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].fTaken = TRUE;
  904. WinsThdPool.ThdCount++;
  905. }
  906. //
  907. // Insert the work item and signal the thread.
  908. //
  909. InsertTailList(&pQueHd->Head, pWrkItm);
  910. if (!SetEvent(pQueHd->EvtHdl))
  911. {
  912. WINSEVT_LOG_M(WINS_EVT_SFT_ERR, GetLastError());
  913. RetStat = WINS_FAILURE;
  914. }
  915. }
  916. except(EXCEPTION_EXECUTE_HANDLER) {
  917. DWORD ExcCode = GetExceptionCode();
  918. DBGPRINT1(EXC, "QueInsertRplPushWrkItm: Got exception (%d)\n",ExcCode);
  919. //
  920. // no need to log an event. WinsMscCreateThd logs it
  921. //
  922. }
  923. //
  924. // If we entered the critical section, we should get out of it
  925. //
  926. if (!fAlreadyInCrtSec)
  927. {
  928. LeaveCriticalSection(&pQueHd->CrtSec);
  929. }
  930. return(RetStat);
  931. }
  932. VOID
  933. QueChlWaitForRsp(
  934. VOID
  935. )
  936. {
  937. EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
  938. fsChlWaitForRsp = TRUE;
  939. LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
  940. return;
  941. }
  942. VOID
  943. QueChlNoWaitForRsp(
  944. VOID
  945. )
  946. {
  947. EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
  948. fsChlWaitForRsp = FALSE;
  949. LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
  950. return;
  951. }
  952. BOOL
  953. ChlRspDropped(
  954. MSG_T pMsg
  955. )
  956. {
  957. BOOL fFreeBuff = FALSE;
  958. EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
  959. //
  960. // If the challenge thread is not wait for responses, drop the
  961. // datagram
  962. //
  963. if (!fsChlWaitForRsp)
  964. {
  965. fFreeBuff = TRUE;
  966. }
  967. LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
  968. if (fFreeBuff)
  969. {
  970. #ifdef WINSDBG
  971. NmsChlNoRspDropped++;
  972. #endif
  973. ECommFreeBuff(pMsg);
  974. return(TRUE);
  975. }
  976. return(FALSE);
  977. }
  978. STATUS
  979. QueInsertNetNtfWrkItm (
  980. IN PLIST_ENTRY pWrkItm
  981. )
  982. /*++
  983. Routine Description:
  984. This function is called to queue a push ntf work item on
  985. the RPLPULL queue. It checks if there is another push ntf
  986. work item from the same WINS on the queue. If there is, it is replaced
  987. with this new one. This is done because the new one has more information
  988. than the previous one. The old one is terminated to free up the connection.
  989. Arguments:
  990. pWrkItm - Work Item to queue
  991. Externals Used:
  992. None
  993. Return Value:
  994. Success status codes -- WINS_SUCCESS
  995. Error status codes -- WINS_FAILURE
  996. Error Handling:
  997. Called by:
  998. ERplInsertQue, QueInsertNbtWrkItm
  999. Side Effects:
  1000. Comments:
  1001. None
  1002. --*/
  1003. {
  1004. STATUS RetStat = WINS_SUCCESS;
  1005. PQUE_HD_T pQueHd = NULL;
  1006. PQUE_RPL_REQ_WRK_ITM_T pTmp;
  1007. COMM_IP_ADD_T IpAddNew;
  1008. COMM_IP_ADD_T IpAddInList;
  1009. BOOL fBreak = FALSE;
  1010. PRPL_CONFIG_REC_T pCnfRec;
  1011. //
  1012. // Get address of the WINS sending the notfication
  1013. //
  1014. pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItm;
  1015. pCnfRec = pTmp->pClientCtx;
  1016. COMM_GET_IPADD_M(&pTmp->DlgHdl, &IpAddNew);
  1017. pQueHd = pWinsQueQueHd[QUE_E_RPLPULL];
  1018. EnterCriticalSection(&pQueHd->CrtSec);
  1019. try {
  1020. for(pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pQueHd->Head.Flink;
  1021. pTmp != (PQUE_RPL_REQ_WRK_ITM_T)pQueHd;
  1022. pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pTmp->Head.Flink)
  1023. {
  1024. if ( pTmp->CmdTyp_e == QUE_E_CMD_HDL_PUSH_NTF )
  1025. {
  1026. //
  1027. // Get address of the WINS that sent this notification
  1028. //
  1029. COMM_GET_IPADD_M(&pTmp->DlgHdl, &IpAddInList);
  1030. if (IpAddInList == IpAddNew)
  1031. {
  1032. DBGPRINT1(DET, "QueInsertNetNtfWrkItm: Found an earlier Net Ntf work item. Replacing it. WINS address = (%x)\n", IpAddInList);
  1033. //
  1034. // switch the work items since the new one takes precedence
  1035. // over the old one.
  1036. //
  1037. pWrkItm->Flink = pTmp->Head.Flink;
  1038. pWrkItm->Blink = pTmp->Head.Blink;
  1039. pTmp->Head.Blink->Flink = pWrkItm;
  1040. pTmp->Head.Flink->Blink = pWrkItm;
  1041. fBreak = TRUE;
  1042. break;
  1043. }
  1044. }
  1045. }
  1046. //
  1047. // If there was no match, insert at tail end of list
  1048. //
  1049. if (!fBreak)
  1050. {
  1051. InsertTailList(&pQueHd->Head, pWrkItm);
  1052. }
  1053. if (!SetEvent(pQueHd->EvtHdl))
  1054. {
  1055. // Error = GetLastError();
  1056. RetStat = WINS_FAILURE;
  1057. }
  1058. } // end of try
  1059. finally {
  1060. LeaveCriticalSection(&pQueHd->CrtSec);
  1061. }
  1062. //
  1063. // If we found a match, terminate the old work item
  1064. //
  1065. // Do this outside the critical section
  1066. //
  1067. if (fBreak)
  1068. {
  1069. CHECK("Can we avoid the try block")
  1070. try {
  1071. #if PRSCONN
  1072. RPLMSGF_MSG_OPCODE_E Opcode_e;
  1073. BOOL fPrsDlg;
  1074. #endif
  1075. #if PRSCONN
  1076. //
  1077. // If the ntf was sent on a persistent dlg, we do not terminate it since
  1078. // it will be terminated by the remote WINS when it so chooses. This
  1079. // dlg is used for multiple such notifications. If
  1080. // it was sent on a non-persistent dlg, we will terminate it since the
  1081. // remote WINS create a dlg for each such notification
  1082. //
  1083. RPLMSGF_GET_OPC_FROM_MSG_M(pTmp->pMsg, Opcode_e);
  1084. fPrsDlg = ((Opcode_e == RPLMSGF_E_UPDATE_NTF_PRS) || (Opcode_e == RPLMSGF_E_UPDATE_NTF_PROP_PRS));
  1085. if (!fPrsDlg)
  1086. {
  1087. ECommEndDlg(&pTmp->DlgHdl);
  1088. }
  1089. #else
  1090. ECommEndDlg(&pTmp->DlgHdl);
  1091. #endif
  1092. //
  1093. // Terminate the dequeued request.
  1094. //
  1095. ECommFreeBuff(pTmp->pMsg - COMM_HEADER_SIZE);
  1096. QueDeallocWrkItm(RplWrkItmHeapHdl, pTmp);
  1097. }
  1098. except (EXCEPTION_EXECUTE_HANDLER) {
  1099. DBGPRINTEXC("QueInsertNtfWrkItm");
  1100. }
  1101. }
  1102. return(RetStat);
  1103. }
  1104. STATUS
  1105. QueInsertSndNtfWrkItm (
  1106. IN PLIST_ENTRY pWrkItmp
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This function is called to queue a send push ntf work item on
  1111. the RPLPULL queue. It checks if there is another send push ntf
  1112. work item from the same WINS on the queue. If there is, it is replaced
  1113. with this new one. This is done because the new one has more information
  1114. than the previous one. The old one is terminated to free up the connection.
  1115. Arguments:
  1116. pWrkItm - Work Item to queue
  1117. Externals Used:
  1118. None
  1119. Return Value:
  1120. Success status codes -- WINS_SUCCESS
  1121. Error status codes -- WINS_FAILURE
  1122. Error Handling:
  1123. Called by:
  1124. ERplInsertQue, QueInsertNbtWrkItm
  1125. Side Effects:
  1126. Comments:
  1127. None
  1128. --*/
  1129. {
  1130. STATUS RetStat = WINS_SUCCESS;
  1131. PQUE_HD_T pQueHd = NULL;
  1132. PQUE_RPL_REQ_WRK_ITM_T pTmp;
  1133. PQUE_RPL_REQ_WRK_ITM_T pWrkItm = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItmp;
  1134. COMM_IP_ADD_T IpAddNew;
  1135. COMM_IP_ADD_T IpAddInList;
  1136. BOOL fBreak = FALSE;
  1137. PRPL_CONFIG_REC_T pCnfRec;
  1138. pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItm;
  1139. pCnfRec = pTmp->pClientCtx;
  1140. IpAddNew = pCnfRec->WinsAdd.Add.IPAdd;
  1141. pQueHd = pWinsQueQueHd[QUE_E_RPLPULL];
  1142. EnterCriticalSection(&pQueHd->CrtSec);
  1143. try {
  1144. for(
  1145. pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pQueHd->Head.Flink;
  1146. pTmp != (PQUE_RPL_REQ_WRK_ITM_T)pQueHd;
  1147. // no 3rd expression
  1148. )
  1149. {
  1150. //
  1151. // If this is a push ntf item, then go on to the next if test
  1152. //
  1153. if (( pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF ) ||
  1154. (pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF_PROP))
  1155. {
  1156. IpAddInList = ((PRPL_CONFIG_REC_T)(pTmp->pClientCtx))->WinsAdd.Add.IPAdd;
  1157. //
  1158. // If the push is to the same WINS, replace the work item
  1159. //
  1160. if (IpAddInList == IpAddNew)
  1161. {
  1162. if (pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF_PROP)
  1163. {
  1164. pWrkItm->CmdTyp_e = pTmp->CmdTyp_e;
  1165. }
  1166. DBGPRINT1(DET, "QueInsertSndNtfWrkItm: Found an earlier Snd Ntf work item. Replacing it. WINS address = (%x)\n", IpAddInList);
  1167. //
  1168. // switch the work items since the new one takes precedence
  1169. // over the old one.
  1170. //
  1171. pWrkItmp->Flink = pTmp->Head.Flink;
  1172. pWrkItmp->Blink = pTmp->Head.Blink;
  1173. pTmp->Head.Blink->Flink = pWrkItmp;
  1174. pTmp->Head.Flink->Blink = pWrkItmp;
  1175. fBreak = TRUE;
  1176. break;
  1177. }
  1178. }
  1179. pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pTmp->Head.Flink;
  1180. }
  1181. if (!fBreak)
  1182. {
  1183. InsertTailList(&pQueHd->Head, pWrkItmp);
  1184. }
  1185. if (!SetEvent(pQueHd->EvtHdl))
  1186. {
  1187. // Error = GetLastError();
  1188. RetStat = WINS_FAILURE;
  1189. }
  1190. }
  1191. finally {
  1192. LeaveCriticalSection(&pQueHd->CrtSec);
  1193. //
  1194. // if we replaced an item, we need to deallocate it here.
  1195. //
  1196. if (fBreak)
  1197. {
  1198. QueDeallocWrkItm(RplWrkItmHeapHdl, pTmp);
  1199. }
  1200. }
  1201. return(RetStat);
  1202. }
  1203. __inline
  1204. STATUS
  1205. QueInsertScvWrkItm (
  1206. IN PLIST_ENTRY pWrkItm
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. This function is called to queue a work item on
  1211. the Push thread's queue.
  1212. Arguments:
  1213. pWrkItm - Work Item to queue
  1214. Externals Used:
  1215. None
  1216. Return Value:
  1217. Success status codes -- WINS_SUCCESS
  1218. Error status codes -- WINS_FAILURE
  1219. Error Handling:
  1220. Called by:
  1221. ERplInsertQue
  1222. Side Effects:
  1223. Comments:
  1224. None
  1225. --*/
  1226. {
  1227. return(QueInsertWrkItm ( pWrkItm, QUE_E_WINSSCVQ, NULL));
  1228. }
  1229. __inline
  1230. STATUS
  1231. QueRemoveScvWrkItm(
  1232. IN OUT LPVOID *ppWrkItm
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. This function removes a work item from the nbt queue.
  1237. Arguments:
  1238. ppWrkItm - pointer to array of pointers (to work items) to
  1239. initialize
  1240. Externals Used:
  1241. None
  1242. Return Value:
  1243. Success status codes -- WINS_SUCCESS
  1244. Error status codes -- WINS_FAILURE
  1245. Error Handling:
  1246. Called by:
  1247. Side Effects:
  1248. Comments:
  1249. None
  1250. --*/
  1251. {
  1252. return(QueGetWrkItm(QUE_E_WINSSCVQ, ppWrkItm));
  1253. }
  1254. VOID
  1255. WinsQueInit(
  1256. LPTSTR pName,
  1257. PQUE_HD_T pQueHd
  1258. )
  1259. /*++
  1260. Routine Description:
  1261. Function to init a queue
  1262. Arguments:
  1263. Externals Used:
  1264. None
  1265. Return Value:
  1266. Success status codes --
  1267. Error status codes --
  1268. Error Handling:
  1269. Called by:
  1270. Side Effects:
  1271. Comments:
  1272. None
  1273. --*/
  1274. {
  1275. //
  1276. // Create the response event handle. This event is signaled
  1277. // by the UDP listener thread when it stores a response
  1278. // in the spReqWrkItmArr array
  1279. //
  1280. WinsMscCreateEvt(
  1281. pName,
  1282. FALSE, //auto-reset
  1283. &pQueHd->EvtHdl
  1284. );
  1285. //
  1286. // Initialize the critical section for the response queue
  1287. //
  1288. InitializeCriticalSection(&pQueHd->CrtSec);
  1289. //
  1290. //Initialize the queue head for the response queue
  1291. //
  1292. InitializeListHead(&pQueHd->Head);
  1293. pQueHd->NoOfEntries = 0; //not required really since QueHd structures
  1294. //are externs
  1295. return;
  1296. }