Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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