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.

3786 lines
105 KiB

  1. /*
  2. Possible improvements
  3. If there were a way to end all sessions with one Jet call, there would be
  4. no need to have each nbt thread call WinsMscWaitUntilSignaled. It could simply
  5. call WaitForSingleObject.
  6. */
  7. /*++
  8. Copyright (c) 1990 Microsoft Corporation
  9. Module Name:
  10. nms.c
  11. Abstract:
  12. This module contains functions used by the name space manager (NMS)
  13. This is the top-most module of the name space manager component of
  14. WINS. It contains functions used for initializing WINS and for
  15. providing an interface nto NMS to other components to WINS.
  16. Functions:
  17. main
  18. WinsMain
  19. Init
  20. CreateNbtThdPool
  21. NbtThdInitFn
  22. CreateMem
  23. ENmsHandleMsg
  24. NmsAllocWrkItm
  25. NmsDeallocWrkItm
  26. NmsServiceControlHandler
  27. SignalWinsThds
  28. UpdateStatus
  29. WrapUp
  30. Portability:
  31. This module is portable across various platforms
  32. Author:
  33. Pradeep Bahl (PradeepB) Dec-1992
  34. Revision History:
  35. Modification date Person Description of modification
  36. ----------------- ------- ----------------------------
  37. --*/
  38. #include "wins.h"
  39. #include <lmerr.h>
  40. #include <lmcons.h>
  41. #include <secobj.h> //required for ACE_DATA
  42. #include "winsif.h" //required because winsif_v1_0_s_ifspec is being
  43. //referenced
  44. #include "winsi2.h"
  45. #ifdef WINSDBG
  46. #include <time.h>
  47. #endif
  48. #include "winscnf.h"
  49. #include "nmsdb.h"
  50. #include "winsque.h"
  51. #include "winsthd.h"
  52. #include "comm.h"
  53. #include "assoc.h"
  54. #include "winsmsc.h"
  55. #include "nms.h"
  56. #include "nmsmsgf.h"
  57. #include "nmschl.h"
  58. #include "nmsnmh.h"
  59. #include "nmsscv.h"
  60. #include "winsevt.h"
  61. #include "winstmm.h"
  62. #include "rplpull.h"
  63. #include "rplpush.h"
  64. #include "winsintf.h"
  65. #include "lmaccess.h"
  66. #include "winswriter.hpp"
  67. /*
  68. * Local Macro Declarations
  69. */
  70. #define NMS_RANGE_SIZE 500
  71. #define NMS_HW_SIZE 400
  72. #define DBG_FILE_MAX_SIZE 1000000 //1 MB
  73. #define DBG_TIME_INTVL_FOR_CHK 1800 //30 mts
  74. /*
  75. * Local Typedef Declarations
  76. */
  77. /*
  78. * Global Variable Definitions
  79. */
  80. WINSTHD_POOL_T WinsThdPool; //thread pool for WINS
  81. DWORD WinsTlsIndex; //TLS index for NBT threads
  82. HANDLE NmsMainTermEvt; //For terminating the WINS service
  83. HANDLE NmsTermEvt; //Termination event
  84. HANDLE NmsCrDelNbtThdEvt;
  85. CRITICAL_SECTION NmsTermCrtSec; //Critical Section guarding count of
  86. //threads
  87. //STATIC CRITICAL_SECTION sSvcCtrlCrtSec; //Critical Section guarding service
  88. //controller initiated action
  89. GENERIC_MAPPING NmsInfoMapping = {
  90. STANDARD_RIGHTS_READ,
  91. STANDARD_RIGHTS_WRITE,
  92. STANDARD_RIGHTS_EXECUTE,
  93. WINS_ALL_ACCESS
  94. };
  95. #ifdef WINSDBG
  96. FUTURES("put all ctrs in a structure")
  97. CRITICAL_SECTION sDbgCrtSec;
  98. DWORD NmsGenHeapAlloc;
  99. DWORD NmsDlgHeapAlloc;
  100. DWORD NmsTcpMsgHeapAlloc;
  101. DWORD NmsUdpHeapAlloc;
  102. DWORD NmsUdpDlgHeapAlloc;
  103. DWORD NmsQueHeapAlloc;
  104. DWORD NmsAssocHeapAlloc;
  105. DWORD NmsRpcHeapAlloc;
  106. DWORD NmsRplWrkItmHeapAlloc;
  107. DWORD NmsChlHeapAlloc;
  108. DWORD NmsTmmHeapAlloc;
  109. DWORD NmsCatchAllHeapAlloc;
  110. DWORD NmsHeapAllocForList;
  111. DWORD NmsGenHeapFree;
  112. DWORD NmsDlgHeapFree;
  113. DWORD NmsTcpMsgHeapFree;
  114. DWORD NmsUdpHeapFree;
  115. DWORD NmsUdpDlgHeapFree;
  116. DWORD NmsQueHeapFree;
  117. DWORD NmsAssocHeapFree;
  118. DWORD NmsRpcHeapFree;
  119. DWORD NmsRplWrkItmHeapFree;
  120. DWORD NmsChlHeapFree;
  121. DWORD NmsTmmHeapFree;
  122. DWORD NmsCatchAllHeapFree;
  123. DWORD NmsHeapCreate;
  124. DWORD NmsHeapDestroy;
  125. //
  126. // Count of updates (to version number) made by WINS.
  127. //
  128. DWORD NmsUpdCtrs[WINS_NO_OF_CLIENTS][2][4][3][2];
  129. DWORD NmsRplUpd;
  130. DWORD NmsRplGUpd;
  131. DWORD NmsNmhUpd;
  132. DWORD NmsNmhGUpd;
  133. DWORD NmsNmhRelUpd;
  134. DWORD NmsNmhRelGUpd;
  135. DWORD NmsScvUpd;
  136. DWORD NmsScvGUpd;
  137. DWORD NmsChlUpd;
  138. DWORD NmsChlGUpd;
  139. DWORD NmsRpcUpd;
  140. DWORD NmsRpcGUpd;
  141. DWORD NmsOthUpd;
  142. DWORD NmsOthGUpd;
  143. NMS_CTRS_T NmsCtrs;
  144. CRITICAL_SECTION NmsHeapCrtSec;
  145. STATIC volatile DWORD sReqDq = 0; //for testing only
  146. STATIC volatile DWORD sRegReqDq = 0; //for testing only
  147. STATIC volatile DWORD sReqQ = 0; //for testing only
  148. STATIC volatile DWORD sRegReqQ = 0; //for testing only
  149. STATIC volatile DWORD sRsp = 0; //for testing only
  150. STATIC time_t sDbgLastChkTime;
  151. volatile DWORD NmsRegReqQDropped = 0; //for testing only
  152. extern DWORD NmsGenHeapAlloc;
  153. #endif
  154. PSECURITY_DESCRIPTOR pNmsSecurityDescriptor = NULL;
  155. COMM_ADD_T NmsLocalAdd = {0}; //My own address
  156. ULONG WinsDbg; //for debugging purposes. see winsdbg.h
  157. /*
  158. * NmsTotalTrmThdCnt -- The total number of threads that deal with NmsTermEvt
  159. * event
  160. * These are -- main thread, nbt threads, name challenge thd,
  161. * scavenger thread, replication threads
  162. */
  163. DWORD NmsTotalTrmThdCnt = 1; //set to 1 for the main thread
  164. HANDLE GenBuffHeapHdl; //handle to heap for use for queue items
  165. HANDLE NmsRpcHeapHdl; //handle to heap for use by rpc
  166. DWORD NmsNoOfNbtThds = 0;
  167. BOOL fNmsAbruptTerm = FALSE;
  168. BOOL fNmsMainSessionActive = FALSE;
  169. //
  170. // Counter to indicate how many rpc calls that have to do with Jet are
  171. // currently in progress
  172. //
  173. DWORD NmsNoOfRpcCallsToDb;
  174. //
  175. // This is set to TRUE to indicate that there are one or more threads
  176. // that have active DB sessions but are not included in the count of
  177. // threads with such sessions. When this is set to TRUE, the main thread
  178. // will not call JetTerm (from within NmsDbRelRes) due to a limitation
  179. // in Jet. We take a thread out of the count when it is involved in an
  180. // activity that can take long since we do not want to hold up WINS termination
  181. // for long. For example, the pull thread is taken out when it is trying
  182. // to establish a connection.
  183. //
  184. BOOL fNmsThdOutOfReck = FALSE;
  185. #if defined (DBGSVC) || TEST_DATA > 0
  186. HANDLE NmsFileHdl = INVALID_HANDLE_VALUE;
  187. HANDLE NmsDbgFileHdl = INVALID_HANDLE_VALUE;
  188. #define QUERY_FAIL_FILE TEXT("wins.out")
  189. #endif
  190. VERS_NO_T NmsRangeSize = {0};
  191. VERS_NO_T NmsHalfRangeSize = {0};
  192. VERS_NO_T NmsVersNoToStartFromNextTime = {0};
  193. VERS_NO_T NmsHighWaterMarkVersNo = {0};
  194. /*
  195. * Local Variable Definitions
  196. */
  197. static BOOL sfHeapsCreated = FALSE;
  198. static HANDLE sNbtThdEvtHdlArray[3]; //event array to wait on (NBT thread)
  199. static BOOL fsBackupOnTerm = TRUE;
  200. #if REG_N_QUERY_SEP > 0
  201. STATIC HANDLE sOtherNbtThdEvtHdlArray[2]; //event array to wait on (NBT thread)
  202. #endif
  203. SERVICE_STATUS ServiceStatus;
  204. SERVICE_STATUS_HANDLE ServiceStatusHdl;
  205. /*
  206. * Local Function Prototype Declarations
  207. */
  208. #if TEST_DATA > 0 || defined(DBGSVC)
  209. STATIC BOOL
  210. DbgOpenFile(
  211. LPTSTR pFileNm,
  212. BOOL fReopen
  213. );
  214. #endif
  215. STATIC
  216. STATUS
  217. ProcessInit(
  218. VOID
  219. );
  220. //
  221. // Create a pool of NBT threads (Threads that service NBT requests)
  222. //
  223. STATIC
  224. STATUS
  225. CreateNbtThdPool(
  226. IN DWORD NoOfThds,
  227. IN LPTHREAD_START_ROUTINE NbtThdInitFn
  228. );
  229. //
  230. // Initialize memory for use by NMS
  231. //
  232. STATIC
  233. VOID
  234. CreateMem(
  235. VOID
  236. );
  237. //
  238. // Startup function of an NBT thread
  239. //
  240. STATIC
  241. DWORD
  242. NbtThdInitFn(
  243. IN LPVOID pThreadParam
  244. );
  245. #if REG_N_QUERY_SEP > 0
  246. //
  247. // Startup function of an NBT thread for registering
  248. //
  249. STATIC
  250. DWORD
  251. OtherNbtThdInitFn(
  252. IN LPVOID pThreadParam
  253. );
  254. #endif
  255. //
  256. // Signal all threads inside WINS that have a session with the db engine
  257. //
  258. STATIC
  259. VOID
  260. SignalWinsThds (
  261. VOID
  262. );
  263. //
  264. // Update status for the benefit of the service controller
  265. //
  266. STATIC
  267. VOID
  268. UpdateStatus(
  269. VOID
  270. );
  271. STATIC
  272. VOID
  273. CrDelNbtThd(
  274. VOID
  275. );
  276. //
  277. // Main function of WINS called by the thread that is created for
  278. // listerning to the service controller
  279. //
  280. STATIC
  281. VOID
  282. WinsMain(
  283. DWORD dwArgc,
  284. LPTSTR *lpszArgv
  285. );
  286. //
  287. // Responsible for the reinitialization of WINS
  288. //
  289. STATIC
  290. VOID
  291. Reinit(
  292. WINSCNF_HDL_SIGNALED_E IndexOfHdlSignaled_e
  293. );
  294. //
  295. // Responsible for initializing RPC
  296. //
  297. STATIC
  298. BOOL
  299. InitializeRpc(
  300. VOID
  301. );
  302. STATIC
  303. BOOL
  304. InitSecurity(
  305. VOID
  306. );
  307. STATIC
  308. VOID
  309. WrapUp(
  310. DWORD ErrorCode,
  311. BOOL fSvcSpecific
  312. );
  313. STATIC
  314. VOID
  315. GetMachineInfo(
  316. VOID
  317. );
  318. //
  319. // The main function
  320. //
  321. VOID __cdecl
  322. main(
  323. VOID
  324. )
  325. /*++
  326. Routine Description:
  327. This is the main function of the WINS server. It calls the
  328. StartServiceCtrlDispatcher to connect the main thread of this process
  329. (executing this function) to the Service Control Manager.
  330. Arguments:
  331. dwArgc - no. of arguments to this function
  332. lpszArgv - list of pointers to the arguments
  333. Externals Used:
  334. WinsCnf
  335. Return Value:
  336. None
  337. Error Handling:
  338. Message is printed if DBG ids defined
  339. Called by:
  340. Startup code
  341. Side Effects:
  342. None
  343. Comments:
  344. None
  345. --*/
  346. {
  347. //
  348. //WINS server is a service in its own process
  349. //
  350. SERVICE_TABLE_ENTRY DispatchTable[] = {
  351. { WINS_SERVER, WinsMain },
  352. { NULL, NULL }
  353. };
  354. //
  355. // Set WinsDbg if debugging is turned on
  356. // Set RplEnabled if Replicator functionality is to be turned on
  357. // Set ScvEnabled if Scavenging functionality is to be turned on
  358. //
  359. DBGINIT;
  360. DBGCHK_IF_RPL_DISABLED;
  361. DBGCHK_IF_SCV_DISABLED;
  362. DBGCHK_IF_PERFMON_ENABLED;
  363. #ifndef WINS_INTERACTIVE
  364. if (! StartServiceCtrlDispatcher(DispatchTable) )
  365. {
  366. DBGPRINT0(ERR, "Main: StartServiceCtrlDispatcher Error\n");
  367. return;
  368. }
  369. #else
  370. WinsMain(1, (LPTSTR *)NULL);
  371. #endif
  372. return;
  373. }
  374. VOID
  375. WinsMain(
  376. DWORD dwArgc,
  377. LPTSTR *lpszArgv
  378. )
  379. /*++
  380. Routine Description:
  381. This is the SERVICE_MAIN_FUNCTION of the WINS server. It
  382. is called when the service controller starts the service.
  383. Arguments:
  384. dwArgc -- no of arguments
  385. lpszArgc -- argument strings
  386. Externals Used:
  387. WinsCnf
  388. NmsTermEvt
  389. Return Value:
  390. None
  391. Error Handling:
  392. Called by:
  393. main()
  394. Side Effects:
  395. Comments:
  396. None
  397. --*/
  398. {
  399. STATUS RetStat = WINS_SUCCESS;
  400. #ifndef WINS_INTERACTIVE
  401. DWORD Error;
  402. #endif
  403. HANDLE ThdEvtHdlArray[WINSCNF_E_NO_OF_HDLS_TO_MONITOR];
  404. WINSCNF_HDL_SIGNALED_E IndexOfHdlSignaled_e;//index in the
  405. //ThdEvtHdlArray of the
  406. //handle that got signaled. Used as
  407. //an arg to WinsMscWaitUntilSignaled
  408. DWORD ExitCode = WINS_SUCCESS;
  409. UNREFERENCED_PARAMETER(dwArgc);
  410. UNREFERENCED_PARAMETER(lpszArgv);
  411. /*
  412. * Initialize the critical section that guards the
  413. * NmsTotalTrmThdCnt count var.
  414. *
  415. * NOTE: The initialization of this critical section should occur
  416. * prior to registering with the service controller. We are playing
  417. * it safe just in case in the future SignalWinsThds gets called
  418. * as part of the cleanup action due to an error that occurs right after
  419. * we have made ourselves known to the service controller
  420. *
  421. * In any case, we must initialize it before calling NmsDbThdInit(). In
  422. * short it must occue prior to the creation of any thread
  423. *
  424. */
  425. InitializeCriticalSection(&NmsTermCrtSec);
  426. #ifndef WINS_INTERACTIVE
  427. //
  428. // Initialize all the status fields so that subsequent calls to
  429. // SetServiceStatus need to only update fields that changed.
  430. //
  431. ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  432. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  433. ServiceStatus.dwControlsAccepted = 0;
  434. ServiceStatus.dwCheckPoint = 1;
  435. //
  436. // Though 10000 is fine most of the times, for a slow overloaded system,
  437. // it may not be enough. Let us be extra conservative and specify
  438. // 60000 (60 secs). Most of the time is taken by Jet. In fact, in
  439. // case the db is corrupted, we will do a restore which can take long.
  440. // So, add another 60 secs for a grand total of 120000.
  441. //
  442. FUTURES("Specify 60 secs here and 60secs in nmsdb.c if Restore is to be")
  443. FUTURES("attempted")
  444. ServiceStatus.dwWaitHint = 120000;
  445. ServiceStatus.dwWin32ExitCode = NO_ERROR;
  446. ServiceStatus.dwServiceSpecificExitCode = 0;
  447. // InitializeCriticalSection(&sSvcCtrlCrtSec);
  448. //
  449. // Initialize workstation to receive service requests by registering the
  450. // control handler.
  451. //
  452. ServiceStatusHdl = RegisterServiceCtrlHandler(
  453. WINS_SERVER,
  454. NmsServiceControlHandler
  455. );
  456. if ( ServiceStatusHdl == (SERVICE_STATUS_HANDLE) 0) {
  457. Error = GetLastError();
  458. DBGPRINT1(ERR,"Wins: RegisterServiceCtrlHandler error = (%d)\n",
  459. Error);
  460. return;
  461. }
  462. //
  463. // Tell Service Controller that we are start pending.
  464. //
  465. UpdateStatus();
  466. #endif
  467. #ifdef WINSDBG
  468. InitializeCriticalSection(&sDbgCrtSec);
  469. #endif
  470. #ifdef WINSDBG
  471. DBGSTART_PERFMON
  472. fWinsCnfHighResPerfCntr =
  473. QueryPerformanceFrequency(&LiWinsCnfPerfCntrFreq);
  474. if (!fWinsCnfHighResPerfCntr)
  475. {
  476. printf("WinsMain: The hardware does not support the high resolution performance monitor\n");
  477. }
  478. else
  479. {
  480. printf("WinsMain: The hardware supports the high resolution performance monitor.\nThe FREQUENCY is (%d %d)\n",
  481. LiWinsCnfPerfCntrFreq.HighPart,
  482. LiWinsCnfPerfCntrFreq.LowPart
  483. );
  484. }
  485. DBGEND_PERFMON
  486. #endif
  487. try {
  488. /*
  489. First and foremost, open (or create if non-existent) the log file
  490. */
  491. WinsCnfInitLog();
  492. //
  493. // Call the initialization function for WINS. This function will
  494. // make the WINS server operational.
  495. //
  496. #ifdef WINSDBG
  497. IF_DBG(INIT_BRKPNT)
  498. {
  499. DbgUserBreakPoint();
  500. }
  501. #endif
  502. RetStat = ProcessInit();
  503. if ( RetStat != WINS_SUCCESS)
  504. {
  505. fNmsAbruptTerm = TRUE;
  506. WrapUp(RetStat, TRUE);
  507. DBGPRINT0(ERR, "WinsMain: Initialization Failed\n");
  508. DBGPRINT0(ERR, "WINS Server has terminated\n");
  509. return;
  510. }
  511. #ifndef WINS_INTERACTIVE
  512. else
  513. {
  514. //
  515. // Tell the service controller that we are up and running now
  516. //
  517. ServiceStatus.dwCheckPoint = 0;
  518. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  519. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  520. SERVICE_ACCEPT_SHUTDOWN |
  521. SERVICE_ACCEPT_PAUSE_CONTINUE;
  522. UpdateStatus( );
  523. if (fWinsCnfInitStatePaused)
  524. {
  525. ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  526. UpdateStatus( );
  527. }
  528. }
  529. //
  530. // If Continue has been sent by the pull thread, it may have been
  531. // sent while we were in the START_PENDING state. So, send it again.
  532. // Sending it again is ok. We should also send it if we don't have
  533. // any pnrs to pull from.
  534. //
  535. EnterCriticalSection(&RplVersNoStoreCrtSec);
  536. if ((fRplPullContinueSent) || (WinsCnf.PullInfo.NoOfPushPnrs == 0))
  537. {
  538. WinsMscSendControlToSc(SERVICE_CONTROL_CONTINUE);
  539. }
  540. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  541. #endif
  542. //
  543. // Wait until we are told to stop or when the configuration changes.
  544. //
  545. //
  546. // Initialize the array of handles on which this thread will
  547. // wait.
  548. //
  549. // K&R C and ANSI C do not allow non-constant initialization of
  550. // an array or a structure. C++ (not all compilers) allows it.
  551. // So, we do it at run time.
  552. //
  553. ThdEvtHdlArray[WINSCNF_E_WINS_HDL] = WinsCnf.WinsKChgEvtHdl;
  554. ThdEvtHdlArray[WINSCNF_E_PARAMETERS_HDL] = WinsCnf.ParametersKChgEvtHdl;
  555. ThdEvtHdlArray[WINSCNF_E_PARTNERS_HDL] = WinsCnf.PartnersKChgEvtHdl;
  556. ThdEvtHdlArray[WINSCNF_E_TERM_HDL] = NmsMainTermEvt;
  557. FUTURES("I may want to create another thread to do all the initialization and")
  558. FUTURES("wait on the registry change notification key. That way, the main")
  559. FUTURES("thread will wait only on the TermEvt event. The justification for")
  560. FUTURES("having another thread is debatable, so I am not doing so now ")
  561. while(TRUE)
  562. {
  563. WinsMscWaitUntilSignaled (
  564. ThdEvtHdlArray,
  565. sizeof(ThdEvtHdlArray)/sizeof(HANDLE),
  566. (LPDWORD)&IndexOfHdlSignaled_e,
  567. TRUE
  568. );
  569. if (IndexOfHdlSignaled_e == WINSCNF_E_TERM_HDL)
  570. {
  571. DBGPRINT0(FLOW, "WinsMain: Got termination signal\n");
  572. //
  573. // Wrap up
  574. //
  575. WrapUp(ERROR_SUCCESS, FALSE);
  576. break;
  577. }
  578. else // registry change notification received. Do reinitialization
  579. {
  580. //
  581. // reinitialize the WINS server according to changes in the
  582. // registry
  583. //
  584. Reinit(IndexOfHdlSignaled_e);
  585. }
  586. }
  587. }
  588. except(EXCEPTION_EXECUTE_HANDLER) {
  589. DBGPRINTEXC("WinsMain");
  590. //
  591. // we received an exception. Set the fNmsAbruptTerm so that
  592. // JetTerm is not called.
  593. //
  594. fNmsAbruptTerm = TRUE;
  595. //
  596. // Have an exception handler around this call just in case the
  597. // WINS or the system is really sick and Wrapup also generates
  598. // an exception. We are not bothered about performance at this
  599. // point.
  600. //
  601. FUTURES("Check into restructuring the exception handlers in a better way")
  602. try {
  603. WrapUp(GetExceptionCode(), TRUE);
  604. }
  605. except (EXCEPTION_EXECUTE_HANDLER) {
  606. DBGPRINTEXC("WinsMain");
  607. }
  608. ExitCode = GetExceptionCode();
  609. WINSEVT_LOG_M(ExitCode, WINS_EVT_ABNORMAL_SHUTDOWN);
  610. }
  611. #ifndef WINS_INTERACTIVE
  612. //
  613. // If it is not one of WINS specific codes, it may be a WIN32 api
  614. // or NTstatus codes. Just in case it is an NTStatus codes, convert
  615. // it to a wins32 code since that is what the Service Controller likes.
  616. //
  617. if ((ExitCode & WINS_FIRST_ERR_STATUS) != WINS_FIRST_ERR_STATUS)
  618. {
  619. ExitCode = RtlNtStatusToDosError((NTSTATUS)ExitCode);
  620. ServiceStatus.dwWin32ExitCode = ExitCode;
  621. ServiceStatus.dwServiceSpecificExitCode = 0;
  622. }
  623. else
  624. {
  625. ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  626. ServiceStatus.dwServiceSpecificExitCode = ExitCode;
  627. }
  628. //
  629. // We are done with cleaning up. Tell Service Controller that we are
  630. // stopped.
  631. //
  632. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  633. ServiceStatus.dwControlsAccepted = 0;
  634. ServiceStatus.dwCheckPoint = 0;
  635. ServiceStatus.dwWaitHint = 0;
  636. UpdateStatus();
  637. #endif
  638. DBGPRINT0(ERR, "WINS Server has terminated\n");
  639. return;
  640. } // end of WinsMain()
  641. STATUS
  642. ProcessInit(
  643. VOID
  644. )
  645. /*++
  646. Routine Description:
  647. This is the function that initializes the WINS. It is executed in
  648. the main thread of the process
  649. Arguments:
  650. None
  651. Externals Used:
  652. None
  653. Called by:
  654. WinsMain()
  655. Comments:
  656. None
  657. Return Value:
  658. Success status codes -- WINS_SUCCESS
  659. Error status codes -- WINS_FAILURE
  660. --*/
  661. {
  662. DWORD NoOfThds;
  663. /*
  664. * Initialize the Critical Section used for name registrations and
  665. * refreshes
  666. */
  667. InitializeCriticalSection(&NmsNmhNamRegCrtSec);
  668. //
  669. // Initialize the critical section that protects the statistics
  670. // var. (WinsIntfStat). This needs to be done here before any
  671. // thread is created because various threads call WinsIntfSetTime
  672. // which uses this critical section
  673. //
  674. InitializeCriticalSection(&WinsIntfCrtSec);
  675. InitializeCriticalSection(&WinsIntfPotentiallyLongCrtSec);
  676. InitializeCriticalSection(&WinsIntfNoOfUsersCrtSec);
  677. #if TEST_DATA > 0
  678. //
  679. // Set WinsDbg so that we don't miss any printfs until we read
  680. // the registry
  681. //
  682. WinsDbg = DBG_ERR | DBG_EXC | DBG_FLOW | DBG_DET | DBG_HEAP_CRDL |
  683. DBG_HEAP_CNTRS;
  684. (VOID)DbgOpenFile(QUERY_FAIL_FILE, FALSE);
  685. #endif
  686. #if defined(DBGSVC) || defined(WINS_INTERACTIVE)
  687. //#if defined(DBGSVC) && !defined(WINS_INTERACTIVE)
  688. #ifdef DBG
  689. (VOID)time(&sDbgLastChkTime);
  690. (VOID)DbgOpenFile(WINSDBG_FILE, FALSE);
  691. #endif
  692. #endif
  693. //
  694. // Initialize the Counter that keeps track of the highest version
  695. // number registered by this server
  696. //
  697. WINS_ASSIGN_INT_TO_LI_M(NmsNmhMyMaxVersNo, 1);
  698. NmsRangeSize.QuadPart = NMS_RANGE_SIZE;
  699. NmsHalfRangeSize.QuadPart = NMS_HW_SIZE;
  700. NmsVersNoToStartFromNextTime.QuadPart = LiAdd(NmsNmhMyMaxVersNo, NmsRangeSize);
  701. NmsHighWaterMarkVersNo.QuadPart = LiAdd(NmsNmhMyMaxVersNo, NmsHalfRangeSize);
  702. //
  703. // The lowest version to start scavenging from
  704. //
  705. NmsScvMinScvVersNo = NmsNmhMyMaxVersNo;
  706. //
  707. // Initialize the global var. to be used to increment/decrement the
  708. // above counter by 1.
  709. //
  710. WINS_ASSIGN_INT_TO_LI_M(NmsNmhIncNo, 1);
  711. /*
  712. * Create Memory Heaps used by the Name Space Manager
  713. */
  714. CreateMem();
  715. /*
  716. * Allocate a TLS index so that each thread can set and get
  717. * thread specific info
  718. */
  719. WinsTlsIndex = TlsAlloc();
  720. if (WinsTlsIndex == 0xFFFFFFFF)
  721. {
  722. DBGPRINT1(ERR,
  723. "Init: Unable to allocate TLS index. Error = (%d)\n",
  724. GetLastError()
  725. );
  726. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  727. }
  728. //
  729. // Initialize the thread count to 1 (to account for this thread)
  730. //
  731. WinsThdPool.ThdCount = 1;
  732. //
  733. // Allocate an array of 100 slots to store version numbers
  734. //
  735. RplPullAllocVersNoArray( &pRplPullOwnerVersNo, RplPullMaxNoOfWins );
  736. //
  737. // Store local machine's ip address in NmsLocalAdd. We need to
  738. // do this before calling WinsCnfInitConfig so that we can
  739. // make sure that this WINS is not listed as its own partner
  740. // in the registry
  741. //
  742. if (ECommGetMyAdd(&NmsLocalAdd) != WINS_SUCCESS)
  743. {
  744. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_BAD_WINS_ADDRESS);
  745. return(WINS_FAILURE);
  746. }
  747. /*
  748. * Read the configuration information from the registry
  749. * into in-memory data structures
  750. */
  751. WinsCnfInitConfig();
  752. // if (fWinsCnfInitStatePaused)
  753. // {
  754. // NtClose(WinsCnfNbtHandle);
  755. // }
  756. //
  757. // Get machine information
  758. //
  759. GetMachineInfo();
  760. //
  761. // Update Status
  762. //
  763. /*
  764. * Initialize the Database Manager
  765. */
  766. if (NmsDbInit() != WINS_SUCCESS)
  767. {
  768. return(WINS_FAILURE);
  769. }
  770. #ifndef WINS_INTERACTIVE
  771. //
  772. // Though 3000 should be ok, let us be extra conservative and
  773. // specify 30000. Actually, if DNS is down, it takes around
  774. // 35 secs for timeout (rpc over tcpip may result in query to
  775. // WINS if query WINS for resolution check box is checked). So,
  776. // let us add another 30 secs for that for a total of 60000
  777. // Throw in another 30 secs for good measure to arrive at a grand
  778. // total of 120 secs.
  779. //
  780. ServiceStatus.dwWaitHint = 120000;
  781. ServiceStatus.dwCheckPoint++;
  782. UpdateStatus(); //inform the service control manager
  783. #endif
  784. //
  785. // NOTE: The value of NmsNmhMyMaxVersNo may have been changed by
  786. // NmsDbInit()
  787. //
  788. // If we did not find the version counter value for next time in
  789. // the registry or if the high water mark is lower than our
  790. // max. version number, adjust it and the next time start version
  791. // number and write it to the registry (since we are about to start
  792. // the worker threads).
  793. //
  794. if (!fWinsCnfReadNextTimeVersNo || LiLtr(NmsHighWaterMarkVersNo,
  795. NmsNmhMyMaxVersNo))
  796. {
  797. NmsVersNoToStartFromNextTime.QuadPart =
  798. LiAdd(NmsNmhMyMaxVersNo, NmsRangeSize);
  799. NmsHighWaterMarkVersNo.QuadPart =
  800. LiAdd(NmsNmhMyMaxVersNo, NmsHalfRangeSize);
  801. WinsCnfWriteReg(&fWinsCnfReadNextTimeVersNo);
  802. }
  803. /*
  804. * Create the two event variables used for termination
  805. */
  806. //
  807. // NmsTermEvt is signaled by this main thread to signal all those
  808. // WINS threads that have db session to wrap up their sessions and
  809. // terminate
  810. //
  811. WinsMscCreateEvt(
  812. TEXT("WinsTermEvt"),
  813. TRUE, //Manual Reset
  814. &NmsTermEvt
  815. );
  816. /*
  817. * NmsMainTermEvt -- This event is signaled by the service controller
  818. * or by another thread in the WINS server to request termination.
  819. */
  820. WinsMscCreateEvt(
  821. TEXT("WinsMainTermEvt"),
  822. FALSE, //Auto Reset
  823. &NmsMainTermEvt
  824. );
  825. /*
  826. * Do Static Initialization if required
  827. */
  828. if(WinsCnf.fStaticInit)
  829. {
  830. //
  831. // Do the initialization and deallocate the memory
  832. //
  833. if (WinsCnf.pStaticDataFile != NULL)
  834. {
  835. (VOID)WinsPrsDoStaticInit(
  836. WinsCnf.pStaticDataFile,
  837. WinsCnf.NoOfDataFiles,
  838. TRUE //do it asynchronously
  839. );
  840. //
  841. // No need to deallocate memory for data file.
  842. // It should have been freed by WinsPrsDoStaticInit
  843. //
  844. }
  845. }
  846. /*
  847. * Create the nbt request thread pool
  848. */
  849. //
  850. // If the user has not specified the number of threads, use the
  851. // processor count to determine the same, else use the value given
  852. // by user.
  853. //
  854. if (WinsCnf.MaxNoOfWrkThds == 0)
  855. {
  856. NoOfThds = WinsCnf.NoOfProcessors + 1;
  857. }
  858. else
  859. {
  860. NoOfThds = WinsCnf.MaxNoOfWrkThds == 1 ? 2 : WinsCnf.MaxNoOfWrkThds;
  861. }
  862. CreateNbtThdPool(
  863. NoOfThds,
  864. // WinsCnf.MaxNoOfWrkThds == 1 ? 2 : WinsCnf.MaxNoOfWrkThds,
  865. //WINSTHD_DEF_NO_NBT_THDS,
  866. NbtThdInitFn
  867. );
  868. /*
  869. *Initialize the name challenge manager
  870. */
  871. NmsChlInit();
  872. /*
  873. * Initialize the Timer Manager
  874. */
  875. WinsTmmInit();
  876. /*
  877. *Initialize the Replicator. Initialize it before initializing
  878. * the comm threads or the rpc threads. This is because, the
  879. * comm threads and the rpc threads can create the Push thread
  880. * if it is not-existent. fRplPushThdExists is set to TRUE or
  881. * FALSE by this function without the protection of a critical
  882. * section
  883. */
  884. ERplInit();
  885. /*
  886. *Initialize the Comm. subsystem
  887. */
  888. ECommInit();
  889. /*
  890. * Initialize the scavenger code
  891. */
  892. NmsScvInit();
  893. /*
  894. * All threads have been created.
  895. */
  896. // We can not mark state as steady state until all threads are in
  897. // steady state
  898. FUTURES("Mark state as STEADY STATE only after the above is true")
  899. //
  900. // Mark state as steady state. This is actually a PSEUDO steady
  901. // state since all the threads may not have initialized yet. This
  902. // will however do for rpc threads that need to know whether the
  903. // critical sections have been initialized or not
  904. //
  905. //
  906. // NOTE: there is no need to enter a critical section here even
  907. // though there are other threads (rpc threads) reading this since
  908. // if they find the value to be anything other than RUNNING
  909. // they will return a failure which is ok for the minute time window
  910. // where concurrent write and reads are going on
  911. //
  912. WinsCnf.State_e = WINSCNF_E_RUNNING;
  913. //
  914. // Do all RPC related initialization.
  915. //
  916. if (InitializeRpc() == FALSE)
  917. {
  918. DBGPRINT0(ERR, "Init: Rpc not initialized properly. Is Rpc service up\n");
  919. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_RPC_NOT_INIT);
  920. }
  921. NmsDbCloseTables();
  922. //
  923. // Log an informational message
  924. //
  925. WinsIntfSetTime(NULL, WINSINTF_E_WINS_START);
  926. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_WINS_OPERATIONAL);
  927. DBGPRINT0(DET, "WINS: Operational\n");
  928. return(WINS_SUCCESS);
  929. }
  930. VOID
  931. ENmsHandleMsg(
  932. IN PCOMM_HDL_T pDlgHdl,
  933. IN MSG_T pMsg,
  934. IN MSG_LEN_T MsgLen
  935. )
  936. /*++
  937. Routine Description:
  938. This function queues the message either on the nbt request queue or on
  939. the nbt response queue.
  940. Arguments:
  941. pDlgHdl - Dialogue handle
  942. pMsg - Ptr to message to process
  943. MsgLen - Message length
  944. Externals Used:
  945. None
  946. Called by:
  947. ParseMsg in comm.c
  948. Comments:
  949. None
  950. Return Value:
  951. None
  952. --*/
  953. {
  954. DWORD fRsp;
  955. BYTE Opcode = *(pMsg + 2);
  956. STATUS RetStat;
  957. /*
  958. * Check whether the message is a request or a response
  959. */
  960. fRsp = NMS_RESPONSE_MASK & Opcode;
  961. if (!fRsp)
  962. {
  963. if ((WinsCnf.State_e == WINSCNF_E_PAUSED) || fWinsCnfInitStatePaused)
  964. {
  965. //
  966. // Don't even let the queries go through since
  967. // the InitTimePaused state is meant for building
  968. // up the db while the backup handles the load
  969. // This way clients time out and try the backup.
  970. // If we let queries through, clients may get
  971. // back -ve query responses and will not go to
  972. // the backup for the name resolution
  973. //
  974. ECommFreeBuff(pMsg);
  975. ECommEndDlg(pDlgHdl);
  976. return;
  977. }
  978. DBGPRINT0(FLOW,
  979. "ENmsHandleMsg: Listener thread: queuing a work item\n");
  980. #if REG_N_QUERY_SEP > 0
  981. if (((NMS_OPCODE_MASK & Opcode) >> 3) == NMSMSGF_E_NAM_QUERY)
  982. {
  983. QueInsertNbtWrkItm(pDlgHdl, pMsg, MsgLen);
  984. #ifdef WINSDBG
  985. sReqQ++;
  986. #endif
  987. }
  988. else
  989. {
  990. RetStat = QueInsertOtherNbtWrkItm(pDlgHdl, pMsg, MsgLen);
  991. #ifdef WINSDBG
  992. sRegReqQ++;
  993. #endif
  994. }
  995. #else
  996. QueInsertNbtWrkItm(pDlgHdl, pMsg, MsgLen);
  997. sReqQ++;
  998. #endif
  999. }
  1000. else
  1001. {
  1002. DBGPRINT0(FLOW,
  1003. "UDP listener thread: queuing a response work item\n");
  1004. QueInsertChlRspWrkItm(pDlgHdl, pMsg, MsgLen);
  1005. #ifdef WINSDBG
  1006. sRsp++;
  1007. #endif
  1008. }
  1009. return;
  1010. }
  1011. VOID
  1012. CreateMem(
  1013. VOID
  1014. )
  1015. /*++
  1016. Routine Description:
  1017. This function creates the heap that is used for allocating work
  1018. items for the NBT work queues. It also creates a heap for general
  1019. allocation.
  1020. Arguments:
  1021. None
  1022. Externals Used:
  1023. GenBuffHeapHdl, QueBuffHeapHdl
  1024. Return Value:
  1025. None
  1026. Error Handling:
  1027. Called by:
  1028. Init
  1029. Side Effects:
  1030. Comments:
  1031. None
  1032. --*/
  1033. {
  1034. #ifdef WINSDBG
  1035. InitializeCriticalSection(&NmsHeapCrtSec);
  1036. #endif
  1037. /*
  1038. * Create heap for general allocation of memory
  1039. */
  1040. DBGPRINT0(HEAP_CRDL, "CreateMem: Gen. Buff Heap\n");
  1041. GenBuffHeapHdl = WinsMscHeapCreate(
  1042. 0, /*to have mutual exclusion */
  1043. GEN_INIT_BUFF_HEAP_SIZE
  1044. );
  1045. /*
  1046. * Create heap for allocating nbt work items
  1047. */
  1048. DBGPRINT0(HEAP_CRDL, "CreateMem: Que. Buff Heap\n");
  1049. QueBuffHeapHdl = WinsMscHeapCreate(
  1050. 0, /*to have mutual exclusion */
  1051. QUE_INIT_BUFF_HEAP_SIZE
  1052. );
  1053. /*
  1054. * Create heap for rpc use
  1055. */
  1056. DBGPRINT0(HEAP_CRDL, "CreateMem: Rpc. Buff Heap\n");
  1057. NmsRpcHeapHdl = WinsMscHeapCreate(
  1058. 0, /*to have mutual exclusion */
  1059. RPC_INIT_BUFF_HEAP_SIZE
  1060. );
  1061. //
  1062. // Let us set the flag looked at by WrapUp()
  1063. //
  1064. sfHeapsCreated = TRUE;
  1065. return;
  1066. }
  1067. STATUS
  1068. CreateNbtThdPool(
  1069. IN DWORD NoOfThds,
  1070. IN LPTHREAD_START_ROUTINE NbtThdInitFn
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. This function creates the nbt request thread pool
  1075. Arguments:
  1076. NoOfThds -- No. of threads to create
  1077. NbtThdInitFn -- Initialization function for the threads
  1078. Externals Used:
  1079. QueNbtWrkQueHd, sNbtThdEvtHdlArray
  1080. Called by:
  1081. Init
  1082. Comments:
  1083. None
  1084. Return Value:
  1085. Success status codes -- Function should never return for a normal
  1086. thread. It returns WINS_SUCCESS for an
  1087. overload thread
  1088. Error status codes -- WINS_FATAL_ERR
  1089. --*/
  1090. {
  1091. DWORD i; //counter for the number of threads
  1092. DWORD Error;
  1093. PLIST_ENTRY pHead;
  1094. #if REG_N_QUERY_SEP > 0
  1095. pHead = &QueOtherNbtWrkQueHd.Head;
  1096. /*
  1097. * Initialize the critical section that protects the
  1098. * nbt req. queue
  1099. */
  1100. InitializeCriticalSection(&QueOtherNbtWrkQueHd.CrtSec);
  1101. /*
  1102. * Initialize the listhead for the nbt request queue
  1103. */
  1104. InitializeListHead(pHead);
  1105. /*
  1106. * Create an auto-reset event for the nbt request queue
  1107. */
  1108. WinsMscCreateEvt(
  1109. NULL, //create without name
  1110. FALSE, //auto-reset var.
  1111. &QueOtherNbtWrkQueHd.EvtHdl
  1112. );
  1113. #endif
  1114. pHead = &QueNbtWrkQueHd.Head;
  1115. /*
  1116. * Initialize the critical section that protects the
  1117. * nbt req. queue
  1118. */
  1119. InitializeCriticalSection(&QueNbtWrkQueHd.CrtSec);
  1120. /*
  1121. * Initialize the listhead for the nbt request queue
  1122. */
  1123. InitializeListHead(pHead);
  1124. /*
  1125. * Create an auto-reset event for the nbt request queue
  1126. */
  1127. WinsMscCreateEvt(
  1128. NULL, //create without name
  1129. FALSE, //auto-reset var.
  1130. &QueNbtWrkQueHd.EvtHdl
  1131. );
  1132. /*
  1133. * Create an auto-reset event for the dynamic creation/deletion of
  1134. * Nbt threads.
  1135. */
  1136. WinsMscCreateEvt(
  1137. NULL, //create without name
  1138. FALSE, //auto-reset var.
  1139. &NmsCrDelNbtThdEvt
  1140. );
  1141. /*
  1142. * Initialize the array of handles on which each nbt thread will
  1143. * wait.
  1144. */
  1145. sNbtThdEvtHdlArray[0] = QueNbtWrkQueHd.EvtHdl; //work queue event
  1146. //var
  1147. sNbtThdEvtHdlArray[1] = NmsCrDelNbtThdEvt; //
  1148. sNbtThdEvtHdlArray[2] = NmsTermEvt; //termination event var
  1149. #if REG_N_QUERY_SEP > 0
  1150. /*
  1151. * Initialize the array of handles on which each nbt reg. thread will
  1152. * wait.
  1153. */
  1154. sOtherNbtThdEvtHdlArray[0] = QueOtherNbtWrkQueHd.EvtHdl; //work queue event
  1155. //var
  1156. sOtherNbtThdEvtHdlArray[1] = NmsTermEvt; //termination event var
  1157. #endif
  1158. /*
  1159. * Create the nbt request handling threads
  1160. */
  1161. for (i=0; i < NoOfThds -1; i++)
  1162. {
  1163. #if REG_N_QUERY_SEP > 0
  1164. DBGPRINT1(DET, "CreateNbtThdPool: Creating query thread no (%d)\n", i);
  1165. #else
  1166. DBGPRINT1(DET, "NbtThdInitFn: Creating worker thread no (%d)\n", i);
  1167. #endif
  1168. /*
  1169. Create an NBT req thread
  1170. */
  1171. WinsThdPool.NbtReqThds[i].ThdHdl = CreateThread(
  1172. NULL, /*def sec. attributes*/
  1173. 0, /*use default stack size*/
  1174. NbtThdInitFn,
  1175. NULL, /*no arg*/
  1176. 0, /*run it now*/
  1177. &WinsThdPool.NbtReqThds[i].ThdId
  1178. );
  1179. if (NULL == WinsThdPool.NbtReqThds[i].ThdHdl)
  1180. {
  1181. Error = GetLastError();
  1182. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_WRK_THD);
  1183. }
  1184. else
  1185. {
  1186. WinsThdPool.NbtReqThds[i].fTaken = TRUE;
  1187. NmsNoOfNbtThds++;
  1188. }
  1189. }
  1190. #if REG_N_QUERY_SEP > 0
  1191. DBGPRINT1(DET, "NbtThdInitFn: Creating reg/rel thread no (%d)\n", i);
  1192. /*
  1193. Create an NBT req thread
  1194. */
  1195. WinsThdPool.NbtReqThds[i].ThdHdl = CreateThread(
  1196. NULL, /*def sec. attributes*/
  1197. 0, /*use default stack size*/
  1198. OtherNbtThdInitFn,
  1199. NULL, /*no arg*/
  1200. 0, /*run it now*/
  1201. &WinsThdPool.NbtReqThds[i].ThdId
  1202. );
  1203. if (NULL == WinsThdPool.NbtReqThds[i].ThdHdl)
  1204. {
  1205. Error = GetLastError();
  1206. WINSEVT_LOG_M(Error, WINS_EVT_CANT_CREATE_WRK_THD);
  1207. }
  1208. else
  1209. {
  1210. WinsThdPool.NbtReqThds[i].fTaken = TRUE;
  1211. NmsNoOfNbtThds++;
  1212. }
  1213. #endif
  1214. /*
  1215. * if no thread could be created, there is something really wrong
  1216. */
  1217. if (NmsNoOfNbtThds == 0)
  1218. {
  1219. WINSEVT_LOG_M(Error, WINS_EVT_CANT_INIT);
  1220. return(WINS_FATAL_ERR);
  1221. }
  1222. WinsThdPool.ThdCount += NmsNoOfNbtThds;
  1223. return(WINS_SUCCESS);
  1224. }
  1225. DWORD
  1226. NbtThdInitFn(
  1227. IN LPVOID pThreadParam
  1228. )
  1229. /*++
  1230. Routine Description:
  1231. This function is the startup function of threads created
  1232. for the nbt request thread pool
  1233. Arguments:
  1234. pThreadParam - Input argument which if present indicates that this
  1235. is an overload thread
  1236. Externals Used:
  1237. sNbtThdEvtHdlArray
  1238. Called by:
  1239. CreateNbtThdPool
  1240. Comments:
  1241. None
  1242. Return Value:
  1243. Success status codes -- WINS_SUCCESS
  1244. Error status codes -- WINS_FAILURE
  1245. --*/
  1246. {
  1247. COMM_HDL_T DlgHdl;
  1248. MSG_T pMsg;
  1249. MSG_LEN_T MsgLen;
  1250. PNBT_REQ_WRK_ITM_T pWrkItm;
  1251. DWORD ArrInd; //Index of hdl in hdl array
  1252. try {
  1253. /*
  1254. * Initialize the thread with the database
  1255. */
  1256. NmsDbThdInit(WINS_E_NMSNMH);
  1257. #if REG_N_QUERY_SEP > 0
  1258. DBGMYNAME("Nbt Query Thread");
  1259. #else
  1260. DBGMYNAME("Nbt Thread");
  1261. #endif
  1262. //
  1263. // The worker thread is more important that all other threads.
  1264. //
  1265. // Set the priority of this thread to one level above what it is
  1266. // for WINS.
  1267. //
  1268. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  1269. /*
  1270. * if thread param is NON-NULL, then it means that this is
  1271. * an overload thread
  1272. */
  1273. if (pThreadParam != NULL)
  1274. {
  1275. //
  1276. //Exract the dlg handle, message and msglen from work item
  1277. //
  1278. pWrkItm = pThreadParam;
  1279. DlgHdl = pWrkItm->DlgHdl;
  1280. pMsg = pWrkItm->pMsg;
  1281. MsgLen = pWrkItm->MsgLen;
  1282. /*
  1283. * process the request
  1284. */
  1285. NmsMsgfProcNbtReq(
  1286. &DlgHdl,
  1287. pMsg,
  1288. MsgLen
  1289. );
  1290. /*
  1291. * Loop until there are no more requests to process in
  1292. * the NBT queue.
  1293. */
  1294. while(TRUE)
  1295. {
  1296. if ( QueRemoveNbtWrkItm(
  1297. &DlgHdl,
  1298. &pMsg,
  1299. &MsgLen) == WINS_NO_REQ
  1300. )
  1301. {
  1302. break;
  1303. }
  1304. else
  1305. {
  1306. NmsDbOpenTables(WINS_E_NMSNMH);
  1307. NmsMsgfProcNbtReq(
  1308. &DlgHdl,
  1309. pMsg,
  1310. MsgLen
  1311. );
  1312. NmsDbCloseTables();
  1313. }
  1314. }
  1315. }
  1316. else // this is a normal thread
  1317. {
  1318. LOOP:
  1319. try {
  1320. /*
  1321. *loop forever
  1322. */
  1323. while(TRUE)
  1324. {
  1325. /*
  1326. * Block until signaled
  1327. */
  1328. WinsMscWaitUntilSignaled(
  1329. sNbtThdEvtHdlArray,
  1330. sizeof(sNbtThdEvtHdlArray)/sizeof(HANDLE), //no of events
  1331. //in array
  1332. &ArrInd,
  1333. FALSE
  1334. );
  1335. if (ArrInd == 0)
  1336. {
  1337. /*
  1338. Loop until there are no more requests to process in
  1339. the NBT queue.
  1340. */
  1341. while(TRUE)
  1342. {
  1343. if (
  1344. QueRemoveNbtWrkItm(
  1345. &DlgHdl,
  1346. &pMsg,
  1347. &MsgLen) == WINS_NO_REQ
  1348. )
  1349. {
  1350. break;
  1351. }
  1352. else
  1353. {
  1354. #ifdef WINSDBG
  1355. ++sReqDq;
  1356. #endif
  1357. // DBGPRINT1(SPEC, "Nms: Dequeued Name Query Request no = (%d)\n",
  1358. // sReqDq);
  1359. DBGPRINT0(FLOW, "NBT thread: Dequeued a Request\n");
  1360. NmsDbOpenTables(WINS_E_NMSNMH);
  1361. NmsMsgfProcNbtReq(
  1362. &DlgHdl,
  1363. pMsg,
  1364. MsgLen
  1365. );
  1366. NmsDbCloseTables();
  1367. } // end of else
  1368. } // end of while (TRUE) for getting requests from the queue
  1369. } // end of if (signaled for name request handling)
  1370. else
  1371. {
  1372. //
  1373. // If signaled for creating/deleting threads, do so
  1374. //
  1375. if (ArrInd == 1)
  1376. {
  1377. CrDelNbtThd();
  1378. }
  1379. else
  1380. {
  1381. //
  1382. // If Array Index indicates termination event, terminate the
  1383. // the thread
  1384. //
  1385. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  1386. }
  1387. }
  1388. } // end of while (TRUE) (never ending loop)
  1389. } // end of inner try {..}
  1390. except(EXCEPTION_EXECUTE_HANDLER) {
  1391. DWORD ExcCode = GetExceptionCode();
  1392. DBGPRINTEXC("NbtThdInitFn: Nbt Thread \n");
  1393. //
  1394. // If ExcCode indicates NBT_ERR, it could mean that
  1395. // the main thread closed the netbt handle
  1396. //
  1397. if (ExcCode == WINS_EXC_NBT_ERR)
  1398. {
  1399. if (WinsCnf.State_e == WINSCNF_E_TERMINATING)
  1400. {
  1401. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  1402. }
  1403. else
  1404. {
  1405. //if (WinsCnf.State_e != WINSCNF_E_PAUSED)
  1406. {
  1407. WINSEVT_LOG_M(ExcCode, WINS_EVT_WRK_EXC);
  1408. }
  1409. }
  1410. }
  1411. else
  1412. {
  1413. WINSEVT_LOG_M(ExcCode, WINS_EVT_WRK_EXC);
  1414. }
  1415. }
  1416. goto LOOP;
  1417. } // end of else (this is a normal thread)
  1418. } // end of outer try block
  1419. except(EXCEPTION_EXECUTE_HANDLER) {
  1420. DBGPRINTEXC("NbtThdInitFn: Nbt Thread exiting abnormally\n");
  1421. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_WRK_ABNORMAL_SHUTDOWN);
  1422. //
  1423. // If NmsDbThdInit() results in an exception, it is possible
  1424. // that the session has not yet been started. Passing
  1425. // WINS_DB_SESSION_EXISTS however is ok
  1426. //
  1427. //
  1428. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  1429. }
  1430. /*
  1431. *Only an overload thread should reach this return
  1432. */
  1433. ASSERT(pThreadParam != NULL);
  1434. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  1435. return(WINS_SUCCESS);
  1436. }
  1437. #if REG_N_QUERY_SEP > 0
  1438. DWORD
  1439. OtherNbtThdInitFn(
  1440. IN LPVOID pThreadParam
  1441. )
  1442. /*++
  1443. Routine Description:
  1444. This function is the startup function of threads created
  1445. for the nbt request thread pool
  1446. Arguments:
  1447. pThreadParam - Input argument which if present indicates that this
  1448. is an overload thread
  1449. Externals Used:
  1450. sNbtThdEvtHdlArray
  1451. Called by:
  1452. CreateNbtThdPool
  1453. Comments:
  1454. None
  1455. Return Value:
  1456. Success status codes -- WINS_SUCCESS
  1457. Error status codes -- WINS_FAILURE
  1458. --*/
  1459. {
  1460. COMM_HDL_T DlgHdl;
  1461. MSG_T pMsg;
  1462. MSG_LEN_T MsgLen;
  1463. PNBT_REQ_WRK_ITM_T pWrkItm;
  1464. DWORD ArrInd; //Index of hdl in hdl array
  1465. try {
  1466. /*
  1467. * Initialize the thread with the database
  1468. */
  1469. NmsDbThdInit(WINS_E_NMSNMH);
  1470. DBGMYNAME("Nbt Reg Thread");
  1471. //
  1472. // The worker thread is more important that all other threads.
  1473. //
  1474. // Set the priority of this thread to one level above what it is
  1475. // for WINS.
  1476. //
  1477. // SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  1478. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  1479. /*
  1480. * if thread param is NON-NULL, then it means that this is
  1481. * an overload thread
  1482. */
  1483. if (pThreadParam != NULL)
  1484. {
  1485. //
  1486. //Exract the dlg handle, message and msglen from work item
  1487. //
  1488. pWrkItm = pThreadParam;
  1489. DlgHdl = pWrkItm->DlgHdl;
  1490. pMsg = pWrkItm->pMsg;
  1491. MsgLen = pWrkItm->MsgLen;
  1492. /*
  1493. * process the request
  1494. */
  1495. NmsMsgfProcNbtReq(
  1496. &DlgHdl,
  1497. pMsg,
  1498. MsgLen
  1499. );
  1500. /*
  1501. * Loop until there are no more requests to process in
  1502. * the NBT queue.
  1503. */
  1504. while(TRUE)
  1505. {
  1506. if ( QueRemoveOtherNbtWrkItm(
  1507. &DlgHdl,
  1508. &pMsg,
  1509. &MsgLen) == WINS_NO_REQ
  1510. )
  1511. {
  1512. break;
  1513. }
  1514. else
  1515. {
  1516. NmsDbOpenTables(WINS_E_NMSNMH);
  1517. NmsMsgfProcNbtReq(
  1518. &DlgHdl,
  1519. pMsg,
  1520. MsgLen
  1521. );
  1522. NmsDbCloseTables();
  1523. }
  1524. }
  1525. }
  1526. else // this is a normal thread
  1527. {
  1528. LOOP:
  1529. try {
  1530. /*
  1531. *loop forever
  1532. */
  1533. while(TRUE)
  1534. {
  1535. /*
  1536. * Block until signaled
  1537. */
  1538. WinsMscWaitUntilSignaled(
  1539. sOtherNbtThdEvtHdlArray,
  1540. sizeof(sOtherNbtThdEvtHdlArray)/sizeof(HANDLE), //no of events
  1541. //in array
  1542. &ArrInd,
  1543. FALSE
  1544. );
  1545. if (ArrInd == 0)
  1546. {
  1547. /*
  1548. Loop until there are no more requests to process in
  1549. the NBT queue.
  1550. */
  1551. while(TRUE)
  1552. {
  1553. if (
  1554. QueRemoveOtherNbtWrkItm(
  1555. &DlgHdl,
  1556. &pMsg,
  1557. &MsgLen) == WINS_NO_REQ
  1558. )
  1559. {
  1560. break;
  1561. }
  1562. else
  1563. {
  1564. #ifdef WINSDBG
  1565. ++sRegReqDq;
  1566. #endif
  1567. // DBGPRINT1(SPEC, "Nms: Dequeued Name Reg/Rel Request no = (%d)\n",
  1568. // sRegReqDq);
  1569. DBGPRINT0(FLOW, "NBT thread: Dequeued a Request\n");
  1570. NmsDbOpenTables(WINS_E_NMSNMH);
  1571. NmsMsgfProcNbtReq(
  1572. &DlgHdl,
  1573. pMsg,
  1574. MsgLen
  1575. );
  1576. NmsDbCloseTables();
  1577. } // end of else
  1578. } // end of while (TRUE) for getting requests from the queue
  1579. } // end of if (signaled for name request handling)
  1580. else
  1581. {
  1582. //
  1583. // If Array Index indicates termination event, terminate the
  1584. // the thread
  1585. //
  1586. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  1587. }
  1588. } // end of while (TRUE) (never ending loop)
  1589. } // end of inner try {..}
  1590. except(EXCEPTION_EXECUTE_HANDLER) {
  1591. DWORD ExcCode = GetExceptionCode();
  1592. DBGPRINTEXC("OtherNbtThdInitFn: Nbt Reg/Rel Thread \n");
  1593. //
  1594. // If ExcCode indicates NBT_ERR, it could mean that
  1595. // the main thread closed the netbt handle
  1596. //
  1597. if (ExcCode == WINS_EXC_NBT_ERR)
  1598. {
  1599. if (WinsCnf.State_e == WINSCNF_E_TERMINATING)
  1600. {
  1601. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  1602. }
  1603. else
  1604. {
  1605. //if (WinsCnf.State_e != WINSCNF_E_PAUSED)
  1606. {
  1607. WINSEVT_LOG_M(ExcCode, WINS_EVT_WRK_EXC);
  1608. }
  1609. }
  1610. }
  1611. }
  1612. goto LOOP;
  1613. } // end of else (this is a normal thread)
  1614. } // end of outer try block
  1615. except(EXCEPTION_EXECUTE_HANDLER) {
  1616. DBGPRINTEXC("NbtThdInitFn: Nbt Reg Thread exiting abnormally\n");
  1617. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_WRK_ABNORMAL_SHUTDOWN);
  1618. //
  1619. // If NmsDbThdInit() results in an exception, it is possible
  1620. // that the session has not yet been started. Passing
  1621. // WINS_DB_SESSION_EXISTS however is ok
  1622. //
  1623. //
  1624. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  1625. }
  1626. /*
  1627. *Only an overload thread should reach this return
  1628. */
  1629. ASSERT(pThreadParam != NULL);
  1630. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  1631. return(WINS_SUCCESS);
  1632. }
  1633. #endif
  1634. VOID
  1635. SignalWinsThds (
  1636. VOID
  1637. )
  1638. /*++
  1639. Routine Description:
  1640. This function is called to terminate all threads in the process.
  1641. Arguments:
  1642. None
  1643. Externals Used:
  1644. None
  1645. Return Value:
  1646. None
  1647. Error Handling:
  1648. Called by:
  1649. WinsMain()
  1650. Side Effects:
  1651. Comments:
  1652. None
  1653. --*/
  1654. {
  1655. time_t ThdTermStartTime;
  1656. DBGENTER("SignalWinsThds\n");
  1657. //
  1658. // Close the udp and tcp sockets
  1659. //
  1660. WinsCnf.State_e = WINSCNF_E_TERMINATING;
  1661. //
  1662. // Signal the manual-reset event variable NmsTermEvt. This
  1663. // should signal all threads that deal with the db
  1664. //
  1665. // makes sure to set the Nbt handle to NULL to avoid NtClose() to be called from ECommGetMyAdd
  1666. // on a closed handle - this would result in raising an exception. (bug #86768)
  1667. //
  1668. NtClose(WinsCnfNbtHandle);
  1669. WinsCnfNbtHandle = NULL;
  1670. SetEvent(NmsTermEvt);
  1671. #if USENETBT == 0
  1672. closesocket(CommUdpPortHandle);
  1673. #else
  1674. #if MCAST > 0
  1675. CommSendMcastMsg(COMM_MCAST_WINS_DOWN);
  1676. CommLeaveMcastGrp();
  1677. closesocket(CommUdpPortHandle);
  1678. #endif
  1679. #endif
  1680. //
  1681. // Just in case we are terminating before having created the socket
  1682. //
  1683. if (CommTcpPortHandle != INVALID_SOCKET)
  1684. {
  1685. CommDisc(CommTcpPortHandle, FALSE);
  1686. }
  1687. #define FIVE_MTS 300 //seconds
  1688. //
  1689. // This is an infinite loop.
  1690. //
  1691. (VOID)time(&ThdTermStartTime);
  1692. while(TRUE)
  1693. {
  1694. time_t CurrTime;
  1695. DWORD TrmThdCnt;
  1696. //
  1697. // If all threads that deal with the db have terminated
  1698. // break out of the loop.
  1699. //
  1700. // It is possible that WINS is terminating during
  1701. // initialization itself. The Counter is incremented
  1702. // in NmsDbThdInit() as each thread that has to deal with the
  1703. // db engine initializes itself with it.
  1704. //
  1705. // If NmsTotalTrmThdCnt is <=1 break. The count can go
  1706. // lower than 1 if a db thread is terminating without having
  1707. // incremented the above counter
  1708. //
  1709. EnterCriticalSection(&NmsTermCrtSec);
  1710. TrmThdCnt = NmsTotalTrmThdCnt;
  1711. LeaveCriticalSection(&NmsTermCrtSec);
  1712. if ((TrmThdCnt <= 1) || fNmsAbruptTerm)
  1713. {
  1714. break;
  1715. }
  1716. if (((CurrTime = time(NULL)) - ThdTermStartTime) < FIVE_MTS)
  1717. {
  1718. //
  1719. // Wait until signaled (when all threads have or are about
  1720. // to terminate)
  1721. //
  1722. DBGPRINT1(DET, "SignalWinsThds: Thd count left (%d)\n", TrmThdCnt);
  1723. WinsMscWaitInfinite(NmsMainTermEvt);
  1724. }
  1725. else
  1726. {
  1727. DBGPRINT1(ERR, "SignalWinsThds: Thd count left (%d); BREAKING OUT DUE TO ONE HOUR DELAY\n", TrmThdCnt);
  1728. WINSEVT_LOG_M(WINS_EVT_TERM_DUE_TIME_LMT, TrmThdCnt);
  1729. break;
  1730. }
  1731. }
  1732. //
  1733. // End the Db Session for this thread (main thread).
  1734. //
  1735. if (fNmsMainSessionActive)
  1736. {
  1737. NmsDbEndSession();
  1738. }
  1739. FUTURES("Check state of WINS. If Rpc has been initialized or maybe even")
  1740. FUTURES("otherwise, call RpcEpUnRegister")
  1741. DBGLEAVE("SignalWinsThds\n");
  1742. return;
  1743. } // SignalWinsThds()
  1744. VOID
  1745. UpdateStatus(
  1746. VOID
  1747. )
  1748. /*++
  1749. Routine Description:
  1750. This function updates the workstation service status with the Service
  1751. Controller.
  1752. Arguments:
  1753. None.
  1754. Return Value:
  1755. None
  1756. --*/
  1757. {
  1758. DWORD Status = NO_ERROR;
  1759. if (ServiceStatusHdl == (SERVICE_STATUS_HANDLE) 0) {
  1760. DBGPRINT0(ERR, "WINS Server: Cannot call SetServiceStatus, no status handle.\n");
  1761. return;
  1762. }
  1763. if (! SetServiceStatus(ServiceStatusHdl, &ServiceStatus))
  1764. {
  1765. Status = GetLastError();
  1766. DBGPRINT1(ERR, " WINS Server: SetServiceStatus error %lu\n", Status);
  1767. }
  1768. return;
  1769. } //UpdateStatus()
  1770. VOID
  1771. NmsServiceControlHandler(
  1772. IN DWORD Opcode
  1773. )
  1774. /*++
  1775. Routine Description:
  1776. This is the service control handler of the Wins service.
  1777. Arguments:
  1778. Opcode - Supplies a value which specifies the action for the
  1779. service to perform.
  1780. Return Value:
  1781. None.
  1782. --*/
  1783. {
  1784. BOOL fRet = FALSE;
  1785. // EnterCriticalSection(&sSvcCtrlCrtSec);
  1786. try {
  1787. switch (Opcode)
  1788. {
  1789. case SERVICE_CONTROL_SHUTDOWN:
  1790. //
  1791. // Backup can take a long time to execute. If the service
  1792. // controller kills us in the middle, it will mess up the
  1793. // backup. So, let us disable it.
  1794. //
  1795. fsBackupOnTerm = FALSE;
  1796. case SERVICE_CONTROL_STOP:
  1797. DBGPRINT1(DET, "NmsServiceControlHandler: %s Signal received\n", Opcode == SERVICE_CONTROL_STOP ? "STOP" : "SHUTDOWN");
  1798. if (ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING)
  1799. {
  1800. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  1801. ServiceStatus.dwCheckPoint = 1;
  1802. //
  1803. // We keep a high wait time (5 mts) to take care of the
  1804. // case where the replicator pull thread is busy trying
  1805. // to set up communication with partners that are not
  1806. // up. Tcpip stack takes around a minute and a half to come
  1807. // back in case of failure. Also, WINS might have to do
  1808. // backup on termination.
  1809. //
  1810. ServiceStatus.dwWaitHint = 300000;
  1811. //
  1812. // Send the status response.
  1813. //
  1814. UpdateStatus();
  1815. WINSEVT_LOG_INFO_M(WINS_SUCCESS, WINS_EVT_ORDERLY_SHUTDOWN);
  1816. //
  1817. // Signal the main thread
  1818. //
  1819. if (! SetEvent(NmsMainTermEvt))
  1820. {
  1821. //
  1822. // Problem with setting event to terminate Workstation
  1823. // service.
  1824. //
  1825. DBGPRINT1(ERR,
  1826. "Service Control Handler: Error signaling NmsMainTermEvt %lu\n",
  1827. GetLastError());
  1828. }
  1829. fRet = TRUE;
  1830. }
  1831. break;
  1832. case SERVICE_CONTROL_PAUSE:
  1833. if (WinsCnf.State_e == WINSCNF_E_RUNNING)
  1834. {
  1835. DBGPRINT0(DET,"NmsServiceControlHandler: Pausing WINS\n");
  1836. WinsCnf.State_e = WINSCNF_E_PAUSED;
  1837. // NtClose(WinsCnfNbtHandle);
  1838. // SndQueryToLocalNetbt();
  1839. //CommDisc(CommTcpPortHandle);
  1840. }
  1841. ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  1842. break;
  1843. case SERVICE_CONTROL_CONTINUE:
  1844. //
  1845. // If the state is paused as a result of a pause from the sc
  1846. // or if it is paused as a result of a registry directive,
  1847. // we need to unpause it
  1848. //
  1849. if (
  1850. (WinsCnf.State_e == WINSCNF_E_PAUSED)
  1851. ||
  1852. fWinsCnfInitStatePaused
  1853. )
  1854. {
  1855. //
  1856. // If paused as a result of sc directive, open nbt since
  1857. // we closed it earlier. Note: We can have a case where
  1858. // WINS was init time paused and then it got a pause from
  1859. // sc. The state would have then changed from RUNNING to
  1860. // PAUSED.
  1861. //
  1862. if (fWinsCnfInitStatePaused)
  1863. {
  1864. fWinsCnfInitStatePaused = FALSE;
  1865. }
  1866. // CommCreateUdpThd();
  1867. // CommCreateTcpThd();
  1868. WinsCnf.State_e = WINSCNF_E_RUNNING;
  1869. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  1870. }
  1871. break;
  1872. case SERVICE_CONTROL_INTERROGATE:
  1873. break;
  1874. //
  1875. // Service specific command
  1876. //
  1877. case WINS_ABRUPT_TERM:
  1878. fNmsAbruptTerm = TRUE;
  1879. //
  1880. // Signal the main thread
  1881. //
  1882. if (! SetEvent(NmsMainTermEvt))
  1883. {
  1884. //
  1885. // Problem with setting event to terminate Workstation
  1886. // service.
  1887. //
  1888. DBGPRINT1(ERR,
  1889. "Service Control Handler: Error signaling NmsMainTermEvt for abrupt termination. Error = %lu\n",
  1890. GetLastError());
  1891. }
  1892. fRet = TRUE;
  1893. break;
  1894. default:
  1895. break;
  1896. }
  1897. }
  1898. except(EXCEPTION_EXECUTE_HANDLER) {
  1899. DBGPRINTEXC("NmsServiceControlHandler");
  1900. }
  1901. // LeaveCriticalSection(&sSvcCtrlCrtSec);
  1902. if (!fRet)
  1903. {
  1904. //
  1905. // Send the status response.
  1906. //
  1907. UpdateStatus();
  1908. }
  1909. return;
  1910. } //NmsServiceControlHandler
  1911. VOID
  1912. Reinit(
  1913. WINSCNF_HDL_SIGNALED_E IndexOfHdlSignaled_e
  1914. )
  1915. /*++
  1916. Routine Description:
  1917. This function is called whenever the configuration of the WINS changes.
  1918. Arguments:
  1919. None
  1920. Externals Used:
  1921. WinsCnf
  1922. Return Value:
  1923. None
  1924. Error Handling:
  1925. Called by:
  1926. WinsMain
  1927. Side Effects:
  1928. Comments:
  1929. --*/
  1930. {
  1931. PWINSCNF_CNF_T pWinsCnf;
  1932. DBGENTER("Reinit\n");
  1933. try {
  1934. if (IndexOfHdlSignaled_e == WINSCNF_E_WINS_HDL)
  1935. {
  1936. // request notification for any subsequent changes (we have
  1937. // to request changes every time we get a notification if we
  1938. // want notification of further changes).
  1939. //
  1940. WinsCnfAskToBeNotified(WINSCNF_E_WINS_KEY);
  1941. //
  1942. // Maybe a key has been created or deleted
  1943. //
  1944. WinsCnfOpenSubKeys();
  1945. DBGLEAVE("Reinit\n");
  1946. return;
  1947. }
  1948. //
  1949. // If either PULL or PUSH information has changed, copy the
  1950. // read the new data from the registry and inform the
  1951. // replicator
  1952. //
  1953. if (IndexOfHdlSignaled_e == WINSCNF_E_PARTNERS_HDL)
  1954. {
  1955. WinsCnfAskToBeNotified(WINSCNF_E_PARTNERS_KEY);
  1956. //
  1957. // Allocate the WinsCnf structure
  1958. //
  1959. WinsMscAlloc(
  1960. sizeof(WINSCNF_CNF_T),
  1961. &pWinsCnf
  1962. );
  1963. //
  1964. // Read the Partner information
  1965. //
  1966. WinsCnfReadPartnerInfo(pWinsCnf);
  1967. //
  1968. // Copy some (not all) of the configuration information into
  1969. // the global WinsCnf structure. Sanity check of the
  1970. // parameters will be done by this function and the
  1971. // scavenger thread will be signaled if required.
  1972. //
  1973. WinsCnfCopyWinsCnf(WINS_E_RPLPULL, pWinsCnf);
  1974. //
  1975. // Send the reconfig message to the Pull thread
  1976. //
  1977. // Note: The PULL thread will deallocate memory pointed
  1978. // to be pWinsCnf when it gets done
  1979. //
  1980. ERplInsertQue(
  1981. WINS_E_WINSCNF,
  1982. QUE_E_CMD_CONFIG,
  1983. NULL, //no dlg handle
  1984. NULL, //no msg
  1985. 0, //msg len
  1986. pWinsCnf, //client ctx
  1987. pWinsCnf->MagicNo
  1988. );
  1989. DBGLEAVE("Reinit\n");
  1990. return;
  1991. }
  1992. //
  1993. // Parameters related to WINS's configuration (nothing to do with
  1994. // how it interacts with its PARTNERS) have changed. Let us read
  1995. // the new data and signal the scavenger thread
  1996. //
  1997. if (IndexOfHdlSignaled_e == WINSCNF_E_PARAMETERS_HDL)
  1998. {
  1999. WinsCnfAskToBeNotified(WINSCNF_E_PARAMETERS_KEY);
  2000. //
  2001. // Allocate the WinsCnf structure
  2002. //
  2003. WinsMscAlloc(
  2004. sizeof(WINSCNF_CNF_T),
  2005. &pWinsCnf
  2006. );
  2007. //
  2008. // Read the registry information
  2009. //
  2010. WinsCnfReadWinsInfo(pWinsCnf);
  2011. //
  2012. // Copy some of the information read in into WinsCnf.
  2013. //
  2014. WinsCnfCopyWinsCnf(WINS_E_WINSCNF, pWinsCnf);
  2015. WinsWorkerThdUpd(WinsCnf.MaxNoOfWrkThds);
  2016. //
  2017. // If the flag for doing STATIC initialization is set, do it
  2018. //
  2019. if (pWinsCnf->fStaticInit)
  2020. {
  2021. EnterCriticalSection(&WinsIntfCrtSec);
  2022. if (WinsIntfNoCncrntStaticInits >
  2023. WINSCNF_MAX_CNCRNT_STATIC_INITS)
  2024. {
  2025. DBGPRINT1(ERR, "Reinit: Too many concurrent STATIC initializations are going on (No = %d). Try later\n", WinsIntfNoCncrntStaticInits);
  2026. WINSEVT_LOG_M(WinsIntfNoCncrntStaticInits, WINS_EVT_TOO_MANY_STATIC_INITS);
  2027. LeaveCriticalSection(&WinsIntfCrtSec);
  2028. }
  2029. else
  2030. {
  2031. LeaveCriticalSection(&WinsIntfCrtSec);
  2032. (VOID)WinsPrsDoStaticInit(
  2033. pWinsCnf->pStaticDataFile,
  2034. pWinsCnf->NoOfDataFiles,
  2035. TRUE //do it asynchronously
  2036. );
  2037. //
  2038. // No need to deallocate memory for data file.
  2039. // It should have been freed by WinsPrsDoStaticInit
  2040. //
  2041. }
  2042. }
  2043. WinsMscDealloc(pWinsCnf);
  2044. //
  2045. // Signal the scavenger thread
  2046. //
  2047. FUTURES("Signal the scavenger thread only if parameters relevant to")
  2048. FUTURES("scavenging have changed. This requires some if tests.")
  2049. WinsMscSignalHdl(WinsCnf.CnfChgEvtHdl);
  2050. }
  2051. DBGLEAVE("Reinit\n");
  2052. return;
  2053. } // end of try ..
  2054. except (EXCEPTION_EXECUTE_HANDLER) {
  2055. DBGPRINTEXC("Reinit")
  2056. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RECONFIG_ERR);
  2057. }
  2058. DBGLEAVE("Reinit\n");
  2059. return;
  2060. }
  2061. #define USE_TCP
  2062. #define AUTO_BIND
  2063. BOOL
  2064. InitializeRpc(
  2065. VOID
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. This function is called to do all initialization necessary for
  2070. making WINS respond to rpc calls
  2071. Arguments:
  2072. None
  2073. Externals Used:
  2074. None
  2075. Return Value:
  2076. Success status codes -- TRUE
  2077. Error status codes -- FALSE
  2078. Error Handling:
  2079. Called by:
  2080. WinsMain
  2081. Side Effects:
  2082. Comments:
  2083. None
  2084. --*/
  2085. {
  2086. RPC_STATUS RpcStatus;
  2087. RPC_BINDING_VECTOR *pRpcBindingVector;
  2088. BOOL fBool;
  2089. DBGENTER("InitializeRpc\n");
  2090. #ifdef USE_TCP
  2091. #ifdef AUTO_BIND
  2092. //
  2093. // Specify the protocol sequence to use
  2094. //
  2095. RpcStatus = RpcServerUseProtseq(
  2096. TEXT("ncacn_ip_tcp"),
  2097. NMS_MAX_RPC_CALLS, //Max Calls
  2098. 0);
  2099. if (RpcStatus != RPC_S_OK)
  2100. {
  2101. DBGPRINT1(ERR, "Error: InitializeRpc: Tcp/Ip = RpcServerUseProtSeq = %u\n", RpcStatus );
  2102. return( FALSE );
  2103. }
  2104. RpcStatus = RpcServerUseProtseq(
  2105. TEXT("ncalrpc"),
  2106. NMS_MAX_RPC_CALLS, //Max Calls
  2107. NULL);
  2108. if (RpcStatus != RPC_S_OK)
  2109. {
  2110. DBGPRINT1(ERR, "Error: InitializeRpc: Local Rpc - RpcServerUseProtSeq = %u\n", RpcStatus );
  2111. return( FALSE );
  2112. }
  2113. FUTURES("Take this out to save on threads. Take it out when winsadmn is")
  2114. FUTURES("updated to work with just tcp/ip")
  2115. //
  2116. // Use Named pipes
  2117. //
  2118. RpcStatus = RpcServerUseProtseqEp(
  2119. TEXT("ncacn_np"),
  2120. NMS_MAX_RPC_CALLS, // maximum concurrent calls
  2121. WINS_NAMED_PIPE,
  2122. NULL//pSecurityDescriptor
  2123. );
  2124. if (RpcStatus != RPC_S_OK)
  2125. {
  2126. DBGPRINT1(ERR, "Error: InitializeRpc: Named Pipes - RpcServerUseProtSeq = %u\n", RpcStatus );
  2127. return( FALSE );
  2128. }
  2129. //
  2130. // Get the binding vector to use when registring self as end point
  2131. //
  2132. RpcStatus = RpcServerInqBindings(&pRpcBindingVector);
  2133. if (RpcStatus != RPC_S_OK)
  2134. {
  2135. DBGPRINT1(ERR, "InitializeRpc: RpcServerInqBindings = %u\n",
  2136. RpcStatus);
  2137. return( FALSE );
  2138. }
  2139. //
  2140. // Register end point(s) with the end point mapper
  2141. // RpcEpRegister instead of RpcEpRegisterNoReplace is used since
  2142. // it will replace a stale entry in the endpoint map database (left
  2143. // if the server stops running without calling RpcEpUnregister()).
  2144. // Using RpcEpRegister however means that only a single instance of
  2145. // the WINS server will run on a host. This is OK.
  2146. //
  2147. // A dynamic end-point expires when the server instance stops running.
  2148. //
  2149. FUTURES("From 541 onwards, one can replace the last parameter - Null string")
  2150. FUTURES("by a NULL")
  2151. RpcStatus = RpcEpRegister(
  2152. winsif_v1_0_s_ifspec,
  2153. pRpcBindingVector,
  2154. NULL,
  2155. TEXT("") );
  2156. if ( RpcStatus != RPC_S_OK)
  2157. {
  2158. DBGPRINT1( ERR, "InitializeRpc: RpcEpRegister = %u \n", RpcStatus);
  2159. return( FALSE );
  2160. }
  2161. RpcStatus = RpcEpRegister(
  2162. winsi2_v1_0_s_ifspec,
  2163. pRpcBindingVector,
  2164. NULL,
  2165. TEXT("") );
  2166. if ( RpcStatus != RPC_S_OK)
  2167. {
  2168. DBGPRINT1( ERR, "InitializeRpc: RpcEpRegister = %u \n", RpcStatus);
  2169. return( FALSE );
  2170. }
  2171. #else // AUTO_BIND
  2172. RpcStatus = RpcServerUseProtseqEp(
  2173. TEXT("ncacn_ip_tcp"),
  2174. NMS_MAX_RPC_CALLS, // maximum concurrent calls
  2175. WINS_SERVER_PORT,
  2176. 0
  2177. );
  2178. #endif // AUTO_BIND
  2179. #else
  2180. //
  2181. // Use Named pipes
  2182. //
  2183. RpcStatus = RpcServerUseProtseqEp(
  2184. TEXT("ncacn_np"),
  2185. NMS_MAX_RPC_CALLS, // maximum concurrent calls
  2186. WINS_NAMED_PIPE,
  2187. NULL
  2188. );
  2189. if ( RpcStatus != RPC_S_OK )
  2190. {
  2191. DBGPRINT0(ERR, "InitializeRpc: Cannot set server\n");
  2192. return(FALSE);
  2193. }
  2194. #endif
  2195. //
  2196. // Free the security descriptor
  2197. //
  2198. FUTURES("Currently there is a bug in rpc where they use the memory pointed")
  2199. FUTURES("by pSecurityDescriptor even after RpcServerUseProtSeq returns")
  2200. FUTURES("uncomment the following after the rpc bug is fixed - 4/7/94")
  2201. // WinsMscDealloc(pSecurityDescriptor);
  2202. //
  2203. // Register Interface Handle
  2204. //
  2205. RpcStatus = RpcServerRegisterIf(winsif_v1_0_s_ifspec, 0, 0);
  2206. if ( RpcStatus != RPC_S_OK )
  2207. {
  2208. DBGPRINT0(ERR, "InitializeRpc: Registration of winsif failed\n");
  2209. return(FALSE);
  2210. }
  2211. RpcStatus = RpcServerRegisterIf(winsi2_v1_0_s_ifspec, 0, 0);
  2212. if ( RpcStatus != RPC_S_OK )
  2213. {
  2214. DBGPRINT0(ERR, "InitializeRpc: Registration of winsi2 failed\n");
  2215. return(FALSE);
  2216. }
  2217. #if SECURITY > 0
  2218. //
  2219. // register authentication info (used for tcpip calls).
  2220. //
  2221. RpcStatus = RpcServerRegisterAuthInfo(
  2222. WINS_SERVER,
  2223. RPC_C_AUTHN_WINNT,
  2224. NULL, //use default encryption key acquisition method
  2225. NULL //since NULL was passed for function address
  2226. //above, NULL needs to be passed here for arg
  2227. );
  2228. if (RpcStatus != RPC_S_OK)
  2229. {
  2230. DBGPRINT0(ERR, "InitializeRpc: Cannot Register authentication info\n");
  2231. return(FALSE);
  2232. }
  2233. if (!InitSecurity())
  2234. {
  2235. return(FALSE);
  2236. }
  2237. #endif
  2238. //
  2239. // WINS is ready to process RPC calls. The maximum no. of RPC calls
  2240. // parameter (2nd) should not be less than that specified than any of
  2241. // the RPC calls before (RpcServerUseProtseq)
  2242. //
  2243. RpcStatus = RpcServerListen(
  2244. NMS_MIN_RPC_CALL_THDS,
  2245. NMS_MAX_RPC_CALLS,
  2246. TRUE
  2247. );
  2248. if ( RpcStatus != RPC_S_OK )
  2249. {
  2250. DBGPRINT0(ERR, "InitializeRpc: Listen failed\n");
  2251. return(FALSE);
  2252. }
  2253. DBGLEAVE("InitializeRpc\n");
  2254. return(TRUE);
  2255. }
  2256. BOOL
  2257. SecurityAllowedPathAddWins()
  2258. {
  2259. #define _WINS_CFG_KEY TEXT("System\\CurrentControlSet\\Services\\Wins")
  2260. #define SECURITY_ALLOWED_PATH_KEY TEXT("System\\CurrentControlSet\\Control\\SecurePipeServers\\winreg\\AllowedPaths")
  2261. #define ALLOWED_PATHS TEXT("Machine")
  2262. DWORD NTStatus, ValSize, ValTyp;
  2263. LPBYTE ValData;
  2264. LPWSTR NextPath;
  2265. HKEY hKey;
  2266. // Now openup the WINS regkey for remote lookup by readonly operators
  2267. NTStatus = RegOpenKeyEx(
  2268. HKEY_LOCAL_MACHINE,
  2269. SECURITY_ALLOWED_PATH_KEY,
  2270. 0,
  2271. KEY_ALL_ACCESS,
  2272. &hKey
  2273. );
  2274. if (!NT_SUCCESS(NTStatus)) {
  2275. DBGPRINT1(ERR, "SecurityAllowedPathAddWins: Could not open security allowed path key (%ld)\n", NTStatus);
  2276. return FALSE;
  2277. }
  2278. ValSize = 0;
  2279. NTStatus = RegQueryValueEx(
  2280. hKey,
  2281. ALLOWED_PATHS,
  2282. NULL,
  2283. &ValTyp,
  2284. NULL,
  2285. &ValSize
  2286. );
  2287. if (!NT_SUCCESS(NTStatus) || ValTyp != REG_MULTI_SZ) {
  2288. DBGPRINT1(ERR, "SecurityAllowedPathAddWins: Could not query allowed path value (%ld)\n", NTStatus);
  2289. return FALSE;
  2290. }
  2291. try {
  2292. ValSize += (wcslen(_WINS_CFG_KEY) + 1)* sizeof (WCHAR);
  2293. WinsMscAlloc(ValSize , &ValData);
  2294. NTStatus = RegQueryValueEx(
  2295. hKey,
  2296. ALLOWED_PATHS,
  2297. NULL,
  2298. &ValTyp,
  2299. ValData,
  2300. &ValSize
  2301. );
  2302. if (!NT_SUCCESS(NTStatus)){
  2303. DBGPRINT1(ERR, "SecurityAllowedPathAddWins: Could not query allowed path value (%ld)\n", NTStatus);
  2304. return FALSE;
  2305. }
  2306. // First check if WINS key is alreay there or not.
  2307. NextPath = (WCHAR *)ValData;
  2308. while (*NextPath != L'\0' && wcscmp(NextPath, _WINS_CFG_KEY)) {
  2309. NextPath += (wcslen(NextPath) + 1);
  2310. }
  2311. if (*NextPath == L'\0') {
  2312. // The WINS path is not there, so add it.
  2313. wcscpy(NextPath, _WINS_CFG_KEY);
  2314. NextPath += (wcslen(NextPath) + 1);
  2315. *NextPath = L'\0';
  2316. ValSize += (wcslen(_WINS_CFG_KEY) + 1)* sizeof (WCHAR);
  2317. NTStatus = RegSetValueEx(
  2318. hKey,
  2319. ALLOWED_PATHS,
  2320. 0,
  2321. ValTyp,
  2322. ValData,
  2323. ValSize
  2324. );
  2325. if (!NT_SUCCESS(NTStatus)){
  2326. DBGPRINT1(ERR, "SecurityAllowedPathAddWins: Could not set allowed path value (%ld)\n", NTStatus);
  2327. return FALSE;
  2328. }
  2329. }
  2330. } except (EXCEPTION_EXECUTE_HANDLER) {
  2331. DWORD ExcCode = GetExceptionCode();
  2332. DBGPRINT1(EXC, "SecurityAllowedPathAddWins: Got Exception (%x)\n", ExcCode);
  2333. WINSEVT_LOG_M(NTStatus, WINS_EVT_WINS_GRP_ERR);
  2334. }
  2335. return TRUE;
  2336. }
  2337. BOOL
  2338. InitSecurity()
  2339. /*++
  2340. Routine Description:
  2341. This function initializes the security descriptor and
  2342. InfoMapping for use by rpc functions
  2343. Arguments:
  2344. Externals Used:
  2345. None
  2346. Return Value:
  2347. None
  2348. Error Handling:
  2349. Called by:
  2350. Side Effects:
  2351. Comments:
  2352. None
  2353. --*/
  2354. {
  2355. NTSTATUS NTStatus;
  2356. DWORD SidSize = 0;
  2357. LPWSTR ReferencedDomainName = NULL;
  2358. DWORD ReferencedDomainNameSize = 0;
  2359. SID_NAME_USE SidUse;
  2360. DWORD AceCount;
  2361. BOOL Result;
  2362. NET_API_STATUS NetStatus;
  2363. PSID WinsSid = NULL;
  2364. GROUP_INFO_1 WinsGroupInfo = {
  2365. WinsMscGetString(WINS_USERS_GROUP_NAME),
  2366. WinsMscGetString(WINS_USERS_GROUP_DESCRIPTION)};
  2367. ACE_DATA AceData[5] = {
  2368. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  2369. WINS_CONTROL_ACCESS|WINS_QUERY_ACCESS, &LocalSystemSid},
  2370. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  2371. WINS_CONTROL_ACCESS|WINS_QUERY_ACCESS, &AliasAdminsSid},
  2372. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  2373. WINS_CONTROL_ACCESS|WINS_QUERY_ACCESS, &AliasAccountOpsSid},
  2374. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  2375. WINS_CONTROL_ACCESS|WINS_QUERY_ACCESS, &AliasSystemOpsSid},
  2376. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  2377. WINS_QUERY_ACCESS, &WinsSid}
  2378. };
  2379. AceCount = 4;
  2380. //
  2381. // Create sids
  2382. //
  2383. NTStatus = NetpCreateWellKnownSids(NULL);
  2384. if (!NT_SUCCESS(NTStatus))
  2385. {
  2386. DBGPRINT1(ERR, "InitSecurity: Could not create well known Sids. Status returned is (%d)\n", NTStatus);
  2387. WINSEVT_LOG_M(NTStatus, WINS_EVT_SEC_OBJ_ERR);
  2388. return(FALSE);
  2389. }
  2390. try {
  2391. // Add Wins ReadOnly operators group if it doesn't
  2392. // exist
  2393. NetStatus = NetLocalGroupAdd(
  2394. NULL,
  2395. 1,
  2396. (LPVOID)&WinsGroupInfo,
  2397. NULL
  2398. );
  2399. if (NERR_Success != NetStatus && NERR_GroupExists != NetStatus && ERROR_ALIAS_EXISTS != NetStatus) {
  2400. DBGPRINT1(ERR, "InitSecurity: NetGroupAdd Failed %ld \n",NetStatus);
  2401. WINSEVT_LOG_M(NTStatus, WINS_EVT_WINS_GRP_ERR);
  2402. }
  2403. // Lookup SID for WINS read only operators group
  2404. Result = LookupAccountName(
  2405. NULL,
  2406. WinsGroupInfo.grpi1_name,
  2407. WinsSid,
  2408. &SidSize,
  2409. ReferencedDomainName,
  2410. &ReferencedDomainNameSize,
  2411. &SidUse
  2412. );
  2413. if (!Result && (ERROR_INSUFFICIENT_BUFFER == GetLastError())) {
  2414. WinsMscAlloc(SidSize, &WinsSid);
  2415. WinsMscAlloc(ReferencedDomainNameSize*sizeof(WCHAR), &ReferencedDomainName);
  2416. Result = LookupAccountName(
  2417. NULL,
  2418. WinsGroupInfo.grpi1_name,
  2419. WinsSid,
  2420. &SidSize,
  2421. ReferencedDomainName,
  2422. &ReferencedDomainNameSize,
  2423. &SidUse
  2424. );
  2425. WinsMscDealloc(ReferencedDomainName);
  2426. if (!Result) {
  2427. DBGPRINT1(ERR, "InitSecurity: LookupAccountName Failed (%lx)\n", GetLastError());
  2428. WinsMscDealloc(WinsSid);
  2429. WINSEVT_LOG_M(NTStatus, WINS_EVT_WINS_GRP_ERR);
  2430. } else{
  2431. AceCount++;
  2432. DBGPRINT0(DET, "InitSecurity: LookupAccountName Succeded \n");
  2433. }
  2434. }else{
  2435. DBGPRINT1(ERR, "InitSecurity: LookupAccountName Failed (%lx)\n", GetLastError());
  2436. WINSEVT_LOG_M(NTStatus, WINS_EVT_WINS_GRP_ERR);
  2437. }
  2438. } except (EXCEPTION_EXECUTE_HANDLER) {
  2439. DWORD ExcCode = GetExceptionCode();
  2440. DBGPRINT1(EXC, "InitSecurity: Got Exception (%x)\n", ExcCode);
  2441. WINSEVT_LOG_M(NTStatus, WINS_EVT_WINS_GRP_ERR);
  2442. }
  2443. //
  2444. // Actually create the security descriptor.
  2445. //
  2446. NTStatus = NetpCreateSecurityObject(
  2447. AceData,
  2448. AceCount,
  2449. NULL, //LocalSystemSid,
  2450. NULL, //LocalSystemSid,
  2451. &NmsInfoMapping,
  2452. &pNmsSecurityDescriptor
  2453. );
  2454. if (!NT_SUCCESS(NTStatus))
  2455. {
  2456. DBGPRINT1(ERR, "InitSecurity: Could not create security descriptor. Status returned is (%d)\n", NTStatus);
  2457. WINSEVT_LOG_M(NTStatus, WINS_EVT_SEC_OBJ_ERR);
  2458. return(FALSE);
  2459. }
  2460. SecurityAllowedPathAddWins();
  2461. return(TRUE);
  2462. }
  2463. VOID
  2464. WrapUp(
  2465. DWORD ErrorCode,
  2466. BOOL fSvcSpecific
  2467. )
  2468. /*++
  2469. Routine Description:
  2470. This function is called to release all resources held by WINS
  2471. Arguments:
  2472. None
  2473. Externals Used:
  2474. None
  2475. Return Value:
  2476. None
  2477. Error Handling:
  2478. Called by:
  2479. Side Effects:
  2480. Comments:
  2481. None
  2482. --*/
  2483. {
  2484. static BOOL sfFirstTime = TRUE;
  2485. BOOL fWinsIniting = FALSE;
  2486. if (sfFirstTime)
  2487. {
  2488. sfFirstTime = FALSE;
  2489. }
  2490. else
  2491. {
  2492. return;
  2493. }
  2494. //
  2495. // Set flag if we are terminating during initialization. This is
  2496. // to avoid doing "backup on termination". Normally, we shouldn't
  2497. // have to skip the NmsDbBackup() call (it should simply return with
  2498. // success/error but this is another instance where we have to work
  2499. // around jet bugs. Currently (7/7/94) JetBackup simply hangs when
  2500. // called without a valid wins.mdb file being there.
  2501. //
  2502. fWinsIniting = (WinsCnf.State_e == WINSCNF_E_INITING);
  2503. /*
  2504. * signal all threads to do cleanup and exit gracefully
  2505. *
  2506. */
  2507. SignalWinsThds();
  2508. #ifdef WINSDBG
  2509. NmsPrintCtrs();
  2510. #endif
  2511. //
  2512. // Close all keys
  2513. //
  2514. WinsCnfCloseKeys();
  2515. //
  2516. // We are almost done. Let us check if we were told to backup
  2517. // on termination.
  2518. //
  2519. if (!fWinsIniting && (WinsCnf.pBackupDirPath != NULL) && WinsCnf.fDoBackupOnTerm && fsBackupOnTerm)
  2520. {
  2521. #ifndef WINS_INTERACTIVE
  2522. //
  2523. // Backup can take a while, so let us make sure that the
  2524. // service controller does not give up on us.
  2525. //
  2526. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  2527. ServiceStatus.dwCheckPoint = 1;
  2528. ServiceStatus.dwWaitHint = 120000; // 2 mts
  2529. UpdateStatus();
  2530. #endif
  2531. try {
  2532. (VOID)NmsDbBackup(WinsCnf.pBackupDirPath, NMSDB_FULL_BACKUP);
  2533. }
  2534. except(EXCEPTION_EXECUTE_HANDLER) {
  2535. DBGPRINTEXC("WrapUp: During NmsDbBackup\n");
  2536. }
  2537. }
  2538. /*
  2539. * Release all resources used by the system
  2540. * This will result in all data being flushed to disk
  2541. */
  2542. WinsWriterTerm();
  2543. NmsDbRelRes();
  2544. #if defined(DBGSVC) || defined(WINS_INTERACTIVE)
  2545. //#if defined(DBGSVC) && !defined(WINS_INTERACTIVE)
  2546. if (NmsDbgFileHdl != INVALID_HANDLE_VALUE)
  2547. {
  2548. (VOID)CloseHandle(NmsDbgFileHdl);
  2549. }
  2550. #endif
  2551. #if TEST_DATA > 0
  2552. if (NmsFileHdl != INVALID_HANDLE_VALUE)
  2553. {
  2554. if (!CloseHandle(NmsFileHdl))
  2555. {
  2556. DBGPRINT0(ERR, "WrapUp: Could not close output file\n");
  2557. }
  2558. }
  2559. #endif
  2560. #ifndef WINS_INTERACTIVE
  2561. //
  2562. // Tell the service controller that we stopped
  2563. //
  2564. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  2565. ServiceStatus.dwControlsAccepted = 0;
  2566. ServiceStatus.dwCheckPoint = 0;
  2567. ServiceStatus.dwWaitHint = 0;
  2568. ServiceStatus.dwServiceSpecificExitCode = ErrorCode;
  2569. ServiceStatus.dwWin32ExitCode = fSvcSpecific ? ERROR_SERVICE_SPECIFIC_ERROR : ErrorCode;
  2570. UpdateStatus();
  2571. #endif
  2572. return;
  2573. }
  2574. VOID
  2575. CrDelNbtThd(
  2576. VOID
  2577. )
  2578. /*++
  2579. Routine Description:
  2580. This function creates or deletes an Nbt threads.
  2581. Arguments:
  2582. None
  2583. Externals Used:
  2584. None
  2585. Return Value:
  2586. None
  2587. Error Handling:
  2588. Called by:
  2589. WinsUpdThdCnt
  2590. Side Effects:
  2591. Comments:
  2592. None
  2593. --*/
  2594. {
  2595. DWORD ThdId = GetCurrentThreadId();
  2596. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2597. try {
  2598. //
  2599. // If the existing number of threads is less than that desired, create
  2600. // the extra ones.
  2601. //
  2602. if (WinsIntfNoOfNbtThds > NmsNoOfNbtThds)
  2603. {
  2604. while(NmsNoOfNbtThds < WinsIntfNoOfNbtThds)
  2605. {
  2606. //
  2607. // Create an Nbt Thread
  2608. //
  2609. WinsThdPool.NbtReqThds[NmsNoOfNbtThds].ThdHdl = CreateThread(
  2610. NULL, /*def sec. attributes*/
  2611. 0, /*use default stack size*/
  2612. NbtThdInitFn,
  2613. NULL, /*no arg*/
  2614. 0, /*run it now*/
  2615. &WinsThdPool.NbtReqThds[NmsNoOfNbtThds].ThdId
  2616. );
  2617. WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_WRK_THD_CREATED);
  2618. if (NULL == WinsThdPool.NbtReqThds[NmsNoOfNbtThds].ThdHdl)
  2619. {
  2620. WINSEVT_LOG_M(GetLastError(),
  2621. WINS_EVT_CANT_CREATE_WRK_THD);
  2622. }
  2623. WinsThdPool.NbtReqThds[NmsNoOfNbtThds++].fTaken = TRUE;
  2624. DBGPRINT1(FLOW, "CrDelNbtThd: Created thread no = (%d) \n",
  2625. NmsNoOfNbtThds);
  2626. }
  2627. }
  2628. else
  2629. {
  2630. //
  2631. // If the count is less, terminate self after doing some
  2632. // cleanup. The count could be same too in case more than
  2633. // one rpc thread were invoked concurrently to create/delete
  2634. // the threads (i.e. a second rpc thread changes the count
  2635. // prior to this NBT thread looking at it)
  2636. //
  2637. if (WinsIntfNoOfNbtThds < NmsNoOfNbtThds)
  2638. {
  2639. DWORD i, n;
  2640. DBGPRINT0(FLOW, "CrDelNbtThd: EXITING\n");
  2641. //
  2642. // Find the slot for this thread
  2643. //
  2644. for (i = 0; i < NmsNoOfNbtThds; i++)
  2645. {
  2646. if (WinsThdPool.NbtReqThds[i].ThdId == ThdId)
  2647. {
  2648. break;
  2649. }
  2650. }
  2651. ASSERT(i < NmsNoOfNbtThds);
  2652. //
  2653. // Shift all successive filled slots one place down
  2654. //
  2655. for (n = i, i = i + 1 ; i <= NmsNoOfNbtThds; n++, i++)
  2656. {
  2657. WinsThdPool.NbtReqThds[n] =
  2658. WinsThdPool.NbtReqThds[i];
  2659. }
  2660. //
  2661. // Mark the last slot as empty
  2662. //
  2663. WinsThdPool.NbtReqThds[NmsNoOfNbtThds].fTaken = FALSE;
  2664. NmsNoOfNbtThds--;
  2665. //
  2666. // If the count is still less, signal the event again
  2667. //
  2668. if (WinsIntfNoOfNbtThds < NmsNoOfNbtThds)
  2669. {
  2670. WinsMscSignalHdl(NmsCrDelNbtThdEvt);
  2671. }
  2672. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2673. WINSEVT_LOG_INFO_D_M(WINS_SUCCESS,
  2674. WINS_EVT_WRK_THD_TERMINATED);
  2675. WinsMscTermThd(WINS_SUCCESS, WINS_DB_SESSION_EXISTS);
  2676. }
  2677. }
  2678. }
  2679. except(EXCEPTION_EXECUTE_HANDLER) {
  2680. DBGPRINTEXC("CrDelNbtThd");
  2681. }
  2682. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2683. return;
  2684. }
  2685. VOID
  2686. GetMachineInfo(
  2687. VOID
  2688. )
  2689. /*++
  2690. Routine Description:
  2691. This function gets information about the machine WINS is running on
  2692. Arguments:
  2693. NONE
  2694. Externals Used:
  2695. None
  2696. Return Value:
  2697. Success status codes --
  2698. Error status codes --
  2699. Error Handling:
  2700. Called by:
  2701. Side Effects:
  2702. Comments:
  2703. None
  2704. --*/
  2705. {
  2706. #define LOW_MEM_SIZE 8000000
  2707. #define MEDIUM_MEM_SIZE 12000000
  2708. #define LARGE_MEM_SIZE 16000000
  2709. #define SMALL_DB_BUFFER_COUNT 200
  2710. #define MEDIUM_DB_BUFFER_COUNT 400
  2711. #define LARGE_DB_BUFFER_COUNT 500
  2712. SYSTEM_INFO SystemInfo;
  2713. MEMORYSTATUS MemStatus;
  2714. BYTE Tmp[30], Tmp2[30], Tmp3[30];
  2715. WinsCnf.NoOfProcessors = 1;
  2716. WinsCnf.NoOfDbBuffers = SMALL_DB_BUFFER_COUNT;
  2717. GetSystemInfo(&SystemInfo);
  2718. if (SystemInfo.dwNumberOfProcessors != 0)
  2719. {
  2720. DBGPRINT1(DET, "GetMachineInfo: The number of processors are (%d)\n",
  2721. SystemInfo.dwNumberOfProcessors);
  2722. WinsCnf.NoOfProcessors = SystemInfo.dwNumberOfProcessors;
  2723. }
  2724. GlobalMemoryStatus(&MemStatus);
  2725. DBGPRINT2(DET, "Total Phys. Memory = (%d); Total Avail Phys Memory = (%d)\n",
  2726. MemStatus.dwTotalPhys, MemStatus.dwAvailPhys);
  2727. if (WinsCnf.LogDetailedEvts > 0)
  2728. {
  2729. WinsEvtLogDetEvt(TRUE, WINS_EVT_MACHINE_INFO,
  2730. NULL, __LINE__, "sss", _itoa((int)SystemInfo.dwNumberOfProcessors, Tmp, 10),
  2731. _itoa((int)MemStatus.dwTotalPhys, Tmp2, 10),
  2732. _itoa((int)MemStatus.dwAvailPhys, Tmp3, 10));
  2733. }
  2734. if ((MemStatus.dwAvailPhys >= MEDIUM_MEM_SIZE) &&
  2735. (MemStatus.dwAvailPhys < LARGE_MEM_SIZE))
  2736. {
  2737. WinsCnf.NoOfDbBuffers = MEDIUM_DB_BUFFER_COUNT;
  2738. }
  2739. else
  2740. {
  2741. if (MemStatus.dwAvailPhys >= LARGE_MEM_SIZE)
  2742. {
  2743. WinsCnf.NoOfDbBuffers = LARGE_DB_BUFFER_COUNT;
  2744. }
  2745. else
  2746. {
  2747. WinsCnf.NoOfDbBuffers = SMALL_DB_BUFFER_COUNT;
  2748. }
  2749. }
  2750. return;
  2751. }
  2752. VOID
  2753. ENmsWinsUpdateStatus(
  2754. DWORD MSecsToWait
  2755. )
  2756. {
  2757. #ifndef WINS_INTERACTIVE
  2758. ServiceStatus.dwWaitHint = MSecsToWait;
  2759. ServiceStatus.dwCheckPoint++;
  2760. UpdateStatus(); //inform the service control manager
  2761. #endif
  2762. return;
  2763. }
  2764. #if TEST_DATA > 0 || defined(DBGSVC)
  2765. BOOL
  2766. DbgOpenFile(
  2767. LPTSTR pFileNm,
  2768. BOOL fReopen
  2769. )
  2770. /*++
  2771. Routine Description:
  2772. Arguments:
  2773. Externals Used:
  2774. None
  2775. Return Value:
  2776. Success status codes --
  2777. Error status codes --
  2778. Error Handling:
  2779. Called by:
  2780. NmsChkDbgFileSize
  2781. Side Effects:
  2782. Comments:
  2783. Don't use DBGPRINTF in this function, else stack overflow would result.
  2784. --*/
  2785. {
  2786. SECURITY_ATTRIBUTES SecAtt;
  2787. DWORD HowToCreate;
  2788. HANDLE *pTmpHdl;
  2789. int BytesWritten;
  2790. char str[200];
  2791. SecAtt.nLength = sizeof(SecAtt);
  2792. SecAtt.lpSecurityDescriptor = NULL; //use default security descriptor
  2793. SecAtt.bInheritHandle = FALSE; //actually don't care
  2794. if (!lstrcmp(pFileNm, WINSDBG_FILE))
  2795. {
  2796. HowToCreate = CREATE_ALWAYS;
  2797. pTmpHdl = &NmsDbgFileHdl;
  2798. if (fReopen)
  2799. {
  2800. if (!DeleteFile(WINSDBG_FILE_BK))
  2801. {
  2802. DWORD Error;
  2803. Error = GetLastError();
  2804. if (Error != ERROR_FILE_NOT_FOUND)
  2805. {
  2806. IF_DBG(ERR)
  2807. {
  2808. sprintf(str, "DbgOpenFile: Could not delete the backup file. Error = (%d). Dbg file will not be truncated\n", Error);
  2809. WriteFile(NmsDbgFileHdl, str, strlen(str), &BytesWritten, NULL);
  2810. }
  2811. WinsEvtLogDetEvt(TRUE, WINS_EVT_COULD_NOT_DELETE_FILE,
  2812. TEXT("nms.c"), __LINE__, "ud", WINSDBG_FILE_BK, Error);
  2813. return(FALSE);
  2814. }
  2815. }
  2816. //--ft: fix #20801: don't use NmsDbgFileHdl once the handle is closed
  2817. if (NmsDbgFileHdl != NULL)
  2818. {
  2819. CloseHandle(NmsDbgFileHdl);
  2820. NmsDbgFileHdl = NULL;
  2821. if (!MoveFile(WINSDBG_FILE, WINSDBG_FILE_BK))
  2822. return (FALSE);
  2823. }
  2824. }
  2825. }
  2826. else
  2827. {
  2828. HowToCreate = TRUNCATE_EXISTING;
  2829. pTmpHdl = &NmsFileHdl; //for wins.rec
  2830. }
  2831. //
  2832. // Open the file for reading and position self to start of the
  2833. // file
  2834. //
  2835. *pTmpHdl = CreateFile(
  2836. pFileNm,
  2837. GENERIC_WRITE,
  2838. FILE_SHARE_READ,
  2839. &SecAtt,
  2840. HowToCreate,
  2841. FILE_ATTRIBUTE_NORMAL,
  2842. 0 //ignored ?? check
  2843. );
  2844. if (*pTmpHdl == INVALID_HANDLE_VALUE)
  2845. {
  2846. #ifndef UNICODE
  2847. IF_DBG(ERR)
  2848. {
  2849. sprintf(str, "DbgOpen: Could not open %s (Error = %d)\n", pFileNm, GetLastError());
  2850. WriteFile(NmsDbgFileHdl, str, strlen(str), &BytesWritten, NULL);
  2851. }
  2852. #else
  2853. #ifdef WINSDBG
  2854. IF_DBG(ERR)
  2855. {
  2856. wprintf(L"DbgOpen: Could not open %s (Error = %d)\n", pFileNm, GetLastError());
  2857. }
  2858. #endif
  2859. #endif
  2860. return(FALSE);
  2861. }
  2862. return(TRUE);
  2863. }
  2864. #define LIMIT_OPEN_FAILURES 3
  2865. #if defined(DBGSVC)
  2866. VOID
  2867. NmsChkDbgFileSz(
  2868. VOID
  2869. )
  2870. /*++
  2871. Routine Description:
  2872. Arguments:
  2873. Externals Used:
  2874. None
  2875. Return Value:
  2876. Success status codes --
  2877. Error status codes --
  2878. Error Handling:
  2879. Called by:
  2880. Side Effects:
  2881. Comments:
  2882. NOTE NOTE: Do not put a DBGPRINT statement inside this function, otherwise
  2883. infinite recursion will occur.
  2884. --*/
  2885. {
  2886. DWORD FileSize;
  2887. time_t CurrTime;
  2888. BOOL fOpened = FALSE;
  2889. static DWORD sFailureNo = 0;
  2890. int BytesWritten;
  2891. char str[200];
  2892. return;
  2893. //
  2894. // We check every half hour. If the size has become more than
  2895. // that allowed, move wins.dbg to wins.bak and reopen it
  2896. //
  2897. if (time(&CurrTime) > (sDbgLastChkTime + DBG_TIME_INTVL_FOR_CHK))
  2898. {
  2899. //
  2900. // Is the log file too big?
  2901. //
  2902. EnterCriticalSection(&sDbgCrtSec);
  2903. try {
  2904. IF_DBG(DET)
  2905. {
  2906. sprintf(str, "NmsChkDbgFileSz: Getting File Size\n");
  2907. WriteFile(NmsDbgFileHdl, str, strlen(str), &BytesWritten, NULL);
  2908. }
  2909. FileSize = GetFileSize( NmsDbgFileHdl, NULL );
  2910. if ( FileSize == 0xFFFFFFFF )
  2911. {
  2912. IF_DBG(ERR)
  2913. {
  2914. sprintf(str, "NmsChkDbgFileSize: Cannot GetFileSize %ld\n", GetLastError() );
  2915. WriteFile(NmsDbgFileHdl, str, strlen(str), &BytesWritten, NULL);
  2916. }
  2917. return;
  2918. }
  2919. else
  2920. {
  2921. if ( FileSize > DBG_FILE_MAX_SIZE )
  2922. {
  2923. IF_DBG(ERR)
  2924. {
  2925. sprintf(str, "NmsChkDbgFileSz: REOPEN A NEW DEBUG FILE\n");
  2926. WriteFile(NmsDbgFileHdl, str, strlen(str), &BytesWritten, NULL);
  2927. }
  2928. fOpened = DbgOpenFile( WINSDBG_FILE, TRUE );
  2929. }
  2930. }
  2931. //
  2932. // if the new file could not be opened (it could be because another
  2933. // thread was writing to it), then we want to retry again (upto
  2934. // a certain limit)
  2935. //
  2936. //
  2937. if (fOpened)
  2938. {
  2939. sFailureNo = 0;
  2940. sDbgLastChkTime = CurrTime;
  2941. }
  2942. else
  2943. {
  2944. if (++sFailureNo > LIMIT_OPEN_FAILURES)
  2945. {
  2946. sFailureNo = 0;
  2947. sDbgLastChkTime = CurrTime;
  2948. }
  2949. }
  2950. }
  2951. except(EXCEPTION_EXECUTE_HANDLER) {
  2952. }
  2953. LeaveCriticalSection(&sDbgCrtSec);
  2954. }
  2955. return;
  2956. }
  2957. #endif
  2958. #endif
  2959. #ifdef WINSDBG
  2960. VOID
  2961. NmsPrintCtrs(
  2962. VOID
  2963. )
  2964. {
  2965. static LPBYTE pTypeOfUpd[2] = {"INSERT", "REPLACE"};
  2966. static LPBYTE pTypeOfRec[4] = {"UNIQUE", "NORM GRP", "SPEC GRP", "MH"};
  2967. static LPBYTE pStateOfRec[3] = {"ACTIVE", "RELEASE", "TOMBSTONE"};
  2968. static LPBYTE pIndexUpd[2] = {"REFRESH", "UPDATE"};
  2969. DWORD h, i,j,k,n;
  2970. LPDWORD pNoOfUpd;
  2971. DWORD TotalUpd, GTotalUpd = 0;
  2972. DWORD TotalIndexUpd, GTotalIndexUpd = 0;
  2973. BOOL fDef = FALSE;
  2974. DBGPRINT4(HEAP_CNTRS, "WrapUp Summary\n\
  2975. \t# Udp Alloc/Free: (%d/%d)\n \
  2976. \t# Gen Alloc/Free: (%d/%d)\n",
  2977. NmsUdpHeapAlloc, NmsUdpHeapFree, NmsGenHeapAlloc, NmsGenHeapFree);
  2978. DBGPRINT2(HEAP_CNTRS, "\
  2979. \t# Udp Dlg Alloc/Free: (%d/%d)\n",
  2980. NmsUdpDlgHeapAlloc, NmsUdpDlgHeapFree);
  2981. DBGPRINT4(HEAP_CNTRS, "\
  2982. \t# Chl Alloc/Free: (%d/%d)\n \
  2983. \t# Assoc Alloc/Free: (%d/%d)\n",
  2984. NmsChlHeapAlloc, NmsChlHeapFree,NmsAssocHeapAlloc, NmsAssocHeapFree);
  2985. DBGPRINT4(HEAP_CNTRS, "\
  2986. \t# Que Alloc/Free: (%d/%d)\n \
  2987. \t# RplWrkItm Alloc/Free: (%d/%d)\n",
  2988. NmsQueHeapAlloc, NmsQueHeapFree,
  2989. NmsRplWrkItmHeapAlloc, NmsRplWrkItmHeapFree);
  2990. DBGPRINT4(HEAP_CNTRS, "\
  2991. \t# Tmm Alloc/Free: (%d/%d)\n\
  2992. \t# Catch All Alloc/Free: (%d/%d)\n",
  2993. NmsTmmHeapAlloc, NmsTmmHeapFree,NmsCatchAllHeapAlloc, NmsCatchAllHeapFree);
  2994. DBGPRINT4(HEAP_CNTRS, "\
  2995. \t# Dlg Alloc/Free: (%d/%d)\n\
  2996. \t# Tcp Msg Alloc/Free: (%d/%d)\n",
  2997. NmsDlgHeapAlloc, NmsDlgHeapFree,
  2998. NmsTcpMsgHeapAlloc, NmsTcpMsgHeapFree);
  2999. DBGPRINT2(HEAP_CNTRS, "\
  3000. \t# Rpc Alloc/Free: (%d/%d)\n",
  3001. NmsRpcHeapAlloc, NmsRpcHeapFree);
  3002. DBGPRINT3(HEAP_CNTRS, "\n\n \
  3003. \t# of Heap Allocs for List = (%d)\n \
  3004. \t# of Heap Creates = (%d)\n \
  3005. \t# of Heap Destroys = (%d)\n",
  3006. NmsHeapAllocForList, NmsHeapCreate, NmsHeapDestroy);
  3007. DBGPRINT2(HEAP_CNTRS, "\nOther counters\n\n\
  3008. \t# of Dgrms recd\t(%d)\n\
  3009. \t# of repeat dgrms recd\t(%d)\n",
  3010. CommNoOfDgrms,
  3011. CommNoOfRepeatDgrms);
  3012. DBGPRINT4(HEAP_CNTRS, "\
  3013. \t# of Chl req. queued by Nbt and Rpl(%d, %d)/Dequeued Chl req\t(%d)\n\
  3014. \t# of Queued Chl req at Hd. of List\t(%d)\n",
  3015. NmsChlNoOfReqNbt, NmsChlNoOfReqRpl,
  3016. NmsChlNoReqDequeued,
  3017. NmsChlNoReqAtHdOfList);
  3018. DBGPRINT3(HEAP_CNTRS, "\
  3019. \t# of Dequeued Chl req with no rsp\t(%d)\n\
  3020. \t# of Dequeud inv. resp\t(%d)\n\
  3021. \t# of Dequeued Chl rsp\t(%d)\n",
  3022. NmsChlNoNoRsp,
  3023. NmsChlNoInvRsp,
  3024. NmsChlNoRspDequeued);
  3025. #if REG_N_QUERY_SEP > 0
  3026. DBGPRINT3(HEAP_CNTRS, " \
  3027. \t# of reg requests queued by udp thread (%d)\n\
  3028. \t# of query requests queued by udp thread (%d)\n\
  3029. \t# of chl. responses queued by udp thread (%d)\n",
  3030. sRegReqQ, sReqQ, sRsp);
  3031. DBGPRINT4(HEAP_CNTRS, " \
  3032. \t# of reg requests dequeued by worker threads (%d)\n\
  3033. \t# of query requests dequeued by worker threads (%d)\n\
  3034. \t# of tcp connections (%d)\n\
  3035. \t# chl. Responses dropped: (%d)\n", sRegReqDq, sReqDq, CommConnCount, NmsChlNoRspDropped);
  3036. #else
  3037. DBGPRINT2(HEAP_CNTRS, " \
  3038. \t# of requests deqeued by worker threads (%d)\n\
  3039. \t# Responses dropped: (%d)\n", sReqDq, NmsChlNoRspDropped);
  3040. #endif
  3041. DBGPRINT0(UPD_CNTRS, "---UPDATE COUNTERS SUMMARY------\n");
  3042. for (n=0; n<WINS_NO_OF_CLIENTS; n++)
  3043. {
  3044. switch(n)
  3045. {
  3046. case(WINS_E_NMSNMH):
  3047. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3048. DBGPRINT0(UPD_CNTRS, "NMSNMH counters\n");
  3049. break;
  3050. case(WINS_E_NMSSCV):
  3051. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3052. DBGPRINT0(UPD_CNTRS, "NMSSCV counters\n");
  3053. break;
  3054. case(WINS_E_NMSCHL):
  3055. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3056. DBGPRINT0(UPD_CNTRS, "NMSCHL counters\n");
  3057. break;
  3058. case(WINS_E_RPLPULL):
  3059. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3060. DBGPRINT0(UPD_CNTRS, "RPLPULL counters\n");
  3061. break;
  3062. case(WINS_E_WINSRPC):
  3063. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3064. DBGPRINT0(UPD_CNTRS, "WINSRPC counters\n");
  3065. break;
  3066. default:
  3067. fDef = TRUE;
  3068. break;
  3069. }
  3070. if (fDef)
  3071. {
  3072. fDef = FALSE;
  3073. continue;
  3074. }
  3075. TotalUpd = 0;
  3076. TotalIndexUpd = 0;
  3077. for (j=0; j<2; j++)
  3078. {
  3079. for (k=0;k<4;k++)
  3080. {
  3081. for(i=0;i<3;i++)
  3082. {
  3083. for(h=0;h<2;h++)
  3084. {
  3085. pNoOfUpd = &NmsUpdCtrs[n][j][k][i][h];
  3086. if (*pNoOfUpd != 0)
  3087. {
  3088. DBGPRINT4(UPD_CNTRS, "%s - %s - %s - %s\t", pIndexUpd[h], pTypeOfUpd[j], pTypeOfRec[k], pStateOfRec[i]);
  3089. DBGPRINT1(UPD_CNTRS, "%d\n", *pNoOfUpd);
  3090. if (h==1)
  3091. {
  3092. TotalIndexUpd += *pNoOfUpd;
  3093. GTotalIndexUpd += *pNoOfUpd;
  3094. }
  3095. TotalUpd += *pNoOfUpd;
  3096. GTotalUpd += *pNoOfUpd;
  3097. }
  3098. }
  3099. }
  3100. }
  3101. }
  3102. DBGPRINT1(UPD_CNTRS, "TOTAL INDEX UPDATES = (%d)\n", TotalIndexUpd);
  3103. DBGPRINT1(UPD_CNTRS, "TOTAL UPDATES = (%d)\n", TotalUpd);
  3104. }
  3105. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3106. DBGPRINT1(UPD_CNTRS, "GRAND TOTAL INDEX UPDATES = (%d)\n", GTotalIndexUpd);
  3107. DBGPRINT1(UPD_CNTRS, "GRAND TOTAL UPDATES = (%d)\n", GTotalUpd);
  3108. DBGPRINT0(UPD_CNTRS, "-------------------------------------\n");
  3109. DBGPRINT5(UPD_CNTRS, "\
  3110. \t# of AddVersReq (%d)\n\
  3111. \t# of SndEntReq (%d)\n\
  3112. \t# of UpdNtfReq (%d)\n\
  3113. \t# of UpdVerfsReq (%d)\n\
  3114. \t# of InvReq (%d)\n",
  3115. NmsCtrs.RplPushCtrs.NoAddVersReq,
  3116. NmsCtrs.RplPushCtrs.NoSndEntReq,
  3117. NmsCtrs.RplPushCtrs.NoUpdNtfReq,
  3118. NmsCtrs.RplPushCtrs.NoUpdVersReq,
  3119. NmsCtrs.RplPushCtrs.NoInvReq );
  3120. DBGPRINT0(UPD_CNTRS, "---UPDATE COUNTERS SUMMARY------\n");
  3121. DBGPRINT0(HEAP_CNTRS, "----------Counters Summary End--------------\n\n");
  3122. return;
  3123. }
  3124. #endif