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.

4186 lines
119 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. winsintf.c
  5. Abstract:
  6. This module contains the RPC interface to the WINS server
  7. Functions:
  8. R_WinsRecordAction
  9. R_WinsStatus
  10. R_WinsTrigger
  11. R_WinsDoStaticInit
  12. R_WinsGetDbRecs
  13. R_WinsDelDbRecs
  14. R_WinsSetProcPriority
  15. WinsRecordAction
  16. GetWinsStatus
  17. WinsTrigger
  18. WinsDoStaticInit
  19. WinsDoScavenging
  20. WinsGetDbRecs
  21. WinsDelDbRecs
  22. WinsSetProcPriority
  23. sGetVersNo
  24. GetConfig
  25. GetStatistics
  26. Portability:
  27. This module is portable
  28. Author:
  29. Pradeep Bahl (PradeepB) Mar-1993
  30. Revision History:
  31. Modification date Person Description of modification
  32. ----------------- ------- ----------------------------
  33. --*/
  34. /*
  35. * Includes
  36. */
  37. #include <time.h>
  38. #include "wins.h"
  39. #include <lmerr.h>
  40. #include <lmcons.h> //defines NET_API_STATUS
  41. #include <secobj.h>
  42. #include <rpcutil.h> //for NetpRevertToSelf
  43. #include <rpcndr.h>
  44. #include "winsif.h"
  45. #include "winsi2.h"
  46. #include "winsintf.h"
  47. #include "comm.h"
  48. #include "winsque.h"
  49. #include "nms.h"
  50. #include "nmsnmh.h"
  51. #include "nmsmsgf.h"
  52. #include "nmsdb.h"
  53. #include "nmsscv.h"
  54. #include "rpl.h"
  55. #include "rplpull.h"
  56. #include "winscnf.h"
  57. #include "winsevt.h"
  58. #include "winsmsc.h"
  59. #include "winsprs.h"
  60. #include "winstmm.h"
  61. #ifdef WINSDBG
  62. #include "winbasep.h"
  63. #endif
  64. /*
  65. * Local Macro Declarations
  66. */
  67. #if SECURITY > 0
  68. #define CHK_ACCESS_LEVEL_M(_access) { \
  69. if (!sfBS) \
  70. { \
  71. NET_API_STATUS NetStatus; \
  72. NetStatus = NetpAccessCheckAndAudit( \
  73. WINS_SERVER, \
  74. WINS_SERVER, \
  75. pNmsSecurityDescriptor, \
  76. _access, \
  77. &NmsInfoMapping \
  78. ); \
  79. if (NetStatus != NERR_Success) \
  80. { \
  81. DBGPRINT1(ERR, "The Caller of the rpc function does not have the required permissions. NetSTatus is (%d)\n", NetStatus); \
  82. WINSEVT_LOG_M(NetStatus, WINS_EVT_NO_PERM);\
  83. return(NetStatus); \
  84. } \
  85. } \
  86. }
  87. #else
  88. #define CHK_ACCESS_LEVEL_M()
  89. #endif
  90. #define INC_RPC_DB_COUNT_NCHK_M { \
  91. EnterCriticalSection(&NmsTermCrtSec); \
  92. NmsTotalTrmThdCnt++; \
  93. LeaveCriticalSection(&NmsTermCrtSec); \
  94. }
  95. #define INC_RPC_DB_COUNT_M { \
  96. if (WinsCnf.State_e != WINSCNF_E_TERMINATING) \
  97. { \
  98. INC_RPC_DB_COUNT_NCHK_M; \
  99. } \
  100. else \
  101. { \
  102. return(WINSINTF_FAILURE); \
  103. } \
  104. }
  105. #define DEC_RPC_DB_COUNT_M { \
  106. EnterCriticalSection(&NmsTermCrtSec); \
  107. if (--NmsTotalTrmThdCnt == 1) \
  108. { \
  109. DBGPRINT0(FLOW, "RPC thread: Signaling the main thread\n");\
  110. SetEvent(NmsMainTermEvt); \
  111. } \
  112. LeaveCriticalSection(&NmsTermCrtSec); \
  113. }
  114. /*
  115. * Local Typedef Declarations
  116. */
  117. /*
  118. * Global Variable Definitions
  119. */
  120. WINSINTF_STAT_T WinsIntfStat = {0};
  121. DWORD WinsIntfNoOfNbtThds;
  122. DWORD WinsIntfNoCncrntStaticInits = 0;
  123. //DWORD WinsIntfNoOfRpcThds = 0;
  124. CRITICAL_SECTION WinsIntfCrtSec;
  125. CRITICAL_SECTION WinsIntfPotentiallyLongCrtSec;
  126. CRITICAL_SECTION WinsIntfNoOfUsersCrtSec; //extern in nms.h
  127. /*
  128. * Local Variable Definitions
  129. */
  130. STATIC BOOL sfBS = FALSE;
  131. //
  132. // Time interval between reflushing of the 1B cache
  133. //
  134. #define THREE_MTS 180
  135. //
  136. // Used by WinsGetBrowserNames
  137. //
  138. DOM_CACHE_T sDomCache = { 0, NULL, 0, 0, NULL, FALSE};
  139. /*
  140. * Local Function Prototype Declarations
  141. */
  142. DWORD
  143. GetWinsStatus(
  144. IN WINSINTF_CMD_E Cmd_e,
  145. OUT LPVOID pResults,
  146. BOOL fNew
  147. );
  148. STATIC
  149. DWORD
  150. sGetVersNo(
  151. LPVOID pResults
  152. );
  153. STATIC
  154. DWORD
  155. GetStatistics(
  156. LPVOID pResults,
  157. BOOL fNew
  158. );
  159. STATIC
  160. DWORD
  161. GetConfig(
  162. LPVOID pResults,
  163. BOOL fNew,
  164. BOOL fAllMaps
  165. );
  166. VOID
  167. LogClientInfo(
  168. RPC_BINDING_HANDLE ClientHdl,
  169. BOOL fAbruptTerm
  170. );
  171. STATIC
  172. STATUS
  173. PackageRecs(
  174. PRPL_REC_ENTRY2_T pBuff,
  175. DWORD BuffLen,
  176. DWORD NoOfRecs,
  177. PWINSINTF_RECS_T pRecs
  178. );
  179. //
  180. // Function definitions start here
  181. //
  182. DWORD
  183. R_WinsCheckAccess(
  184. WINSIF2_HANDLE ServerHdl,
  185. DWORD *Access
  186. )
  187. {
  188. NET_API_STATUS NetStatus;
  189. *Access = WINS_NO_ACCESS;
  190. NetStatus = NetpAccessCheckAndAudit(
  191. WINS_SERVER,
  192. WINS_SERVER,
  193. pNmsSecurityDescriptor,
  194. WINS_CONTROL_ACCESS,
  195. &NmsInfoMapping
  196. );
  197. if (NERR_Success == NetStatus) {
  198. *Access = WINS_CONTROL_ACCESS;
  199. return WINSINTF_SUCCESS;
  200. }
  201. NetStatus = NetpAccessCheckAndAudit(
  202. WINS_SERVER,
  203. WINS_SERVER,
  204. pNmsSecurityDescriptor,
  205. WINS_QUERY_ACCESS,
  206. &NmsInfoMapping
  207. );
  208. if (NERR_Success == NetStatus) {
  209. *Access = WINS_QUERY_ACCESS;
  210. return WINSINTF_SUCCESS;
  211. }
  212. return WINSINTF_SUCCESS;
  213. }
  214. DWORD
  215. R_WinsRecordAction(
  216. PWINSINTF_RECORD_ACTION_T *ppRecAction
  217. )
  218. /*++
  219. Routine Description:
  220. This function is called to insert/update/delete a record
  221. Arguments:
  222. pRecAction - Record Information
  223. Externals Used:
  224. None
  225. Return Value:
  226. Success status codes --
  227. Error status codes --
  228. Error Handling:
  229. Called by:
  230. Side Effects:
  231. Comments:
  232. None
  233. --*/
  234. {
  235. DWORD Status = WINSINTF_FAILURE;
  236. PERF("Use & and || logic")
  237. if (*ppRecAction == NULL)
  238. {
  239. return(Status);
  240. }
  241. if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
  242. {
  243. if (WINSINTF_E_QUERY == (*ppRecAction)->Cmd_e) {
  244. CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
  245. } else {
  246. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  247. }
  248. INC_RPC_DB_COUNT_NCHK_M;
  249. try {
  250. Status = WinsRecordAction(ppRecAction);
  251. }
  252. finally {
  253. DEC_RPC_DB_COUNT_M;
  254. }
  255. }
  256. return(Status);
  257. }
  258. DWORD
  259. R_WinsStatusWHdl (
  260. WINSIF_HANDLE pWinsHdl,
  261. WINSINTF_CMD_E Cmd_e,
  262. PWINSINTF_RESULTS_NEW_T pResults
  263. )
  264. {
  265. return(R_WinsStatusNew(Cmd_e, pResults));
  266. }
  267. DWORD
  268. R_WinsStatus (
  269. // LPTSTR pWinsAddStr,
  270. WINSINTF_CMD_E Cmd_e,
  271. PWINSINTF_RESULTS_T pResults
  272. )
  273. {
  274. DWORD Status = WINSINTF_FAILURE;
  275. //
  276. // Make sure that the WINS is in steady state
  277. //
  278. PERF("Use & and || logic")
  279. if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
  280. {
  281. CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
  282. Status = GetWinsStatus(/*pWinsAddStr,*/Cmd_e, pResults, FALSE);
  283. }
  284. return(Status);
  285. }
  286. DWORD
  287. R_WinsStatusNew (
  288. WINSINTF_CMD_E Cmd_e,
  289. PWINSINTF_RESULTS_NEW_T pResults
  290. )
  291. {
  292. DWORD Status = WINSINTF_FAILURE;
  293. //
  294. // Make sure that the WINS is in steady state
  295. //
  296. PERF("Use & and || logic")
  297. if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
  298. {
  299. CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
  300. Status = GetWinsStatus(Cmd_e, pResults, TRUE);
  301. }
  302. return(Status);
  303. }
  304. DWORD
  305. R_WinsTrigger (
  306. PWINSINTF_ADD_T pWinsAdd,
  307. WINSINTF_TRIG_TYPE_E TrigType_e
  308. )
  309. {
  310. DWORD Status = WINSINTF_FAILURE;
  311. PERF("Use & and || logic")
  312. if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
  313. {
  314. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  315. Status = WinsTrigger(pWinsAdd, TrigType_e);
  316. }
  317. return(Status);
  318. }
  319. DWORD
  320. R_WinsDoStaticInit (
  321. LPWSTR pDataFilePath,
  322. DWORD fDel
  323. )
  324. {
  325. DWORD Status;
  326. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  327. EnterCriticalSection(&WinsIntfCrtSec);
  328. //
  329. // The admin tool can go haywire and create a lot of threads. Limit it
  330. // to a certain max value. The value will be incremented and decremented
  331. // by the thread doing the STATIC initialization.
  332. //
  333. if (WinsIntfNoCncrntStaticInits > WINSCNF_MAX_CNCRNT_STATIC_INITS)
  334. {
  335. LeaveCriticalSection(&WinsIntfCrtSec);
  336. DBGPRINT1(ERR, "R_WinsDoStaticInit: Too many concurrent STATIC inits. No is (%d)\n", WinsIntfNoCncrntStaticInits);
  337. WINSEVT_LOG_D_M(WinsIntfNoCncrntStaticInits, WINS_EVT_TOO_MANY_STATIC_INITS);
  338. return(WINSINTF_TOO_MANY_STATIC_INITS);
  339. }
  340. LeaveCriticalSection(&WinsIntfCrtSec);
  341. Status = WinsDoStaticInit(pDataFilePath, fDel);
  342. return(Status);
  343. }
  344. DWORD
  345. R_WinsDoScavenging (
  346. VOID
  347. )
  348. {
  349. DWORD Status;
  350. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  351. INC_RPC_DB_COUNT_M;
  352. try {
  353. Status = WinsDoScavenging();
  354. }
  355. finally {
  356. DEC_RPC_DB_COUNT_M;
  357. }
  358. return(Status);
  359. }
  360. DWORD
  361. R_WinsDoScavengingNew (
  362. PWINSINTF_SCV_REQ_T pScvReq
  363. )
  364. {
  365. DWORD Status;
  366. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  367. INC_RPC_DB_COUNT_M;
  368. try {
  369. Status = WinsDoScavengingNew(pScvReq);
  370. }
  371. finally {
  372. DEC_RPC_DB_COUNT_M;
  373. }
  374. return(Status);
  375. }
  376. DWORD
  377. R_WinsGetDbRecs (
  378. PWINSINTF_ADD_T pWinsAdd,
  379. WINSINTF_VERS_NO_T MinVersNo,
  380. WINSINTF_VERS_NO_T MaxVersNo,
  381. PWINSINTF_RECS_T pRecs
  382. )
  383. {
  384. DWORD Status;
  385. CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
  386. INC_RPC_DB_COUNT_M;
  387. try {
  388. #if 0
  389. #ifdef WINSDBG
  390. PVOID pCallersAdd, pCallersCaller;
  391. RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
  392. DbgPrint("Callers Address = (%x)\nCallersCaller = (%x)\n", pCallersAdd, pCallersCaller);
  393. #endif
  394. #endif
  395. Status = WinsGetDbRecs(pWinsAdd, MinVersNo, MaxVersNo, pRecs);
  396. }
  397. finally {
  398. DEC_RPC_DB_COUNT_M;
  399. }
  400. return(Status);
  401. }
  402. DWORD
  403. R_WinsGetDbRecsByName (
  404. PWINSINTF_ADD_T pWinsAdd,
  405. DWORD Location,
  406. LPBYTE pName,
  407. DWORD NameLen,
  408. DWORD NoOfRecsDesired,
  409. DWORD fStaticOnly,
  410. PWINSINTF_RECS_T pRecs
  411. )
  412. {
  413. DWORD Status;
  414. CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
  415. INC_RPC_DB_COUNT_M;
  416. try {
  417. #if 0
  418. #ifdef WINSDBG
  419. PVOID pCallersAdd, pCallersCaller;
  420. RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
  421. #endif
  422. #endif
  423. Status = WinsGetDbRecsByName(pWinsAdd, Location, pName, NameLen, NoOfRecsDesired,
  424. fStaticOnly, pRecs);
  425. }
  426. finally {
  427. DEC_RPC_DB_COUNT_M;
  428. }
  429. return(Status);
  430. }
  431. DWORD
  432. R_WinsDeleteWins(
  433. PWINSINTF_ADD_T pWinsAdd
  434. )
  435. {
  436. DWORD Status;
  437. //LogClientInfo();
  438. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  439. INC_RPC_DB_COUNT_M;
  440. try {
  441. Status = WinsDeleteWins(pWinsAdd);
  442. }
  443. finally {
  444. DEC_RPC_DB_COUNT_M;
  445. }
  446. return(Status);
  447. }
  448. DWORD
  449. R_WinsTerm (
  450. handle_t ClientHdl,
  451. short fAbruptTerm
  452. )
  453. {
  454. DWORD Status;
  455. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  456. Status = WinsTerm(ClientHdl, fAbruptTerm);
  457. LogClientInfo(ClientHdl, fAbruptTerm);
  458. return(Status);
  459. }
  460. DWORD
  461. R_WinsBackup (
  462. LPBYTE pBackupPath,
  463. short fIncremental
  464. )
  465. {
  466. DWORD Status = WINSINTF_FAILURE;
  467. BYTE BackupPath[WINS_MAX_FILENAME_SZ + sizeof(WINS_BACKUP_DIR_ASCII)];
  468. #if 0
  469. (VOID)WinsMscConvertUnicodeStringToAscii(pBackupPath, BackupPath, WINS_MAX_FILENAME_SZ);
  470. #endif
  471. FUTURES("expensive. Change idl prototype to pass length")
  472. if (strlen(pBackupPath) > WINS_MAX_FILENAME_SZ)
  473. {
  474. return(Status);
  475. }
  476. //
  477. // Make sure that the WINS is in steady state
  478. //
  479. PERF("Use & and || logic")
  480. if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
  481. {
  482. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  483. INC_RPC_DB_COUNT_NCHK_M;
  484. WinsLogAdminEvent( WINS_EVT_ADMIN_BACKUP_INITIATED, 0 );
  485. try {
  486. strcpy(BackupPath, pBackupPath);
  487. strcat(BackupPath, WINS_BACKUP_DIR_ASCII);
  488. if (CreateDirectoryA(BackupPath, NULL) || ((Status = GetLastError()) ==
  489. ERROR_ALREADY_EXISTS))
  490. {
  491. Status = WinsBackup(BackupPath, fIncremental);
  492. }
  493. }
  494. finally {
  495. DEC_RPC_DB_COUNT_M;
  496. }
  497. }
  498. return(Status);
  499. }
  500. DWORD
  501. R_WinsDelDbRecs(
  502. IN PWINSINTF_ADD_T pAdd,
  503. IN WINSINTF_VERS_NO_T MinVersNo,
  504. IN WINSINTF_VERS_NO_T MaxVersNo
  505. )
  506. {
  507. DWORD Status = WINSINTF_FAILURE;
  508. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  509. INC_RPC_DB_COUNT_M;
  510. try {
  511. Status = WinsDelDbRecs(pAdd, MinVersNo, MaxVersNo);
  512. }
  513. finally {
  514. DEC_RPC_DB_COUNT_M;
  515. }
  516. return(Status);
  517. }
  518. DWORD
  519. R_WinsTombstoneDbRecs(
  520. IN WINSIF2_HANDLE ServerHdl,
  521. IN PWINSINTF_ADD_T pWinsAdd,
  522. IN WINSINTF_VERS_NO_T MinVersNo,
  523. IN WINSINTF_VERS_NO_T MaxVersNo
  524. )
  525. {
  526. DWORD Status = WINSINTF_FAILURE;
  527. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  528. INC_RPC_DB_COUNT_M;
  529. try {
  530. Status = WinsTombstoneDbRecs(pWinsAdd, MinVersNo, MaxVersNo);
  531. }
  532. finally {
  533. DEC_RPC_DB_COUNT_M;
  534. }
  535. return(Status);
  536. }
  537. DWORD
  538. R_WinsPullRange(
  539. IN PWINSINTF_ADD_T pAdd,
  540. IN PWINSINTF_ADD_T pOwnerAdd,
  541. IN WINSINTF_VERS_NO_T MinVersNo,
  542. IN WINSINTF_VERS_NO_T MaxVersNo
  543. )
  544. {
  545. DWORD Status = WINSINTF_FAILURE;
  546. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  547. Status = WinsPullRange(pAdd, pOwnerAdd, MinVersNo, MaxVersNo);
  548. return(Status);
  549. }
  550. DWORD
  551. R_WinsSetPriorityClass(
  552. IN WINSINTF_PRIORITY_CLASS_E PriorityClass
  553. )
  554. {
  555. DWORD Status = WINSINTF_FAILURE;
  556. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  557. Status = WinsSetPriorityClass(PriorityClass);
  558. return(Status);
  559. }
  560. DWORD
  561. R_WinsResetCounters(
  562. VOID
  563. )
  564. {
  565. DWORD Status = WINSINTF_FAILURE;
  566. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  567. Status = WinsResetCounters();
  568. return(Status);
  569. }
  570. DWORD
  571. R_WinsWorkerThdUpd(
  572. DWORD NewNoOfNbtThds
  573. )
  574. {
  575. DWORD Status = WINSINTF_FAILURE;
  576. CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
  577. Status = WinsWorkerThdUpd(NewNoOfNbtThds);
  578. return(Status);
  579. }
  580. DWORD
  581. R_WinsGetNameAndAdd(
  582. PWINSINTF_ADD_T pWinsAdd,
  583. LPBYTE pUncName
  584. )
  585. {
  586. DWORD Status = WINSINTF_FAILURE;
  587. //CHK_ACCESS_LEVEL_M();
  588. Status = WinsGetNameAndAdd(pWinsAdd, pUncName);
  589. return(Status);
  590. }
  591. DWORD
  592. R_WinsGetBrowserNames_Old(
  593. PWINSINTF_BROWSER_NAMES_T pNames
  594. )
  595. {
  596. return(WINSINTF_FAILURE);
  597. }
  598. DWORD
  599. R_WinsGetBrowserNames(
  600. WINSIF_HANDLE pWinsHdl,
  601. PWINSINTF_BROWSER_NAMES_T pNames
  602. )
  603. {
  604. DWORD Status = WINSINTF_FAILURE;
  605. static DWORD sNoOfReq = 0;
  606. //
  607. // Allow access to anybody. We don't check access here since
  608. // browser running as a service has zero access when it goes
  609. // on the network (It goes under the null account -- CliffVDyke 4/15/94)
  610. //
  611. INC_RPC_DB_COUNT_M;
  612. EnterCriticalSection(&WinsIntfPotentiallyLongCrtSec);
  613. try {
  614. if (sNoOfReq++ < NMS_MAX_BROWSER_RPC_CALLS)
  615. {
  616. Status = WinsGetBrowserNames((PWINSINTF_BIND_DATA_T)pWinsHdl,pNames);
  617. }
  618. else
  619. {
  620. pNames->EntriesRead = 0;
  621. pNames->pInfo = NULL;
  622. Status = WINSINTF_FAILURE;
  623. }
  624. } // end of try
  625. finally {
  626. sNoOfReq--;
  627. //
  628. // increment the user count.
  629. //
  630. EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
  631. sDomCache.NoOfUsers++;
  632. LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
  633. LeaveCriticalSection(&WinsIntfPotentiallyLongCrtSec);
  634. DEC_RPC_DB_COUNT_M;
  635. }
  636. return(Status);
  637. }
  638. DWORD
  639. R_WinsSetFlags (
  640. DWORD fFlags
  641. )
  642. {
  643. DWORD Status = WINSINTF_SUCCESS;
  644. Status = WinsSetFlags(fFlags);
  645. return(Status);
  646. }
  647. DWORD
  648. WinsSetFlags (
  649. DWORD fFlags
  650. )
  651. {
  652. DWORD Status = WINSINTF_SUCCESS;
  653. #ifdef WINSDBG
  654. DWORD DbgFlagsStore = WinsDbg;
  655. SYSTEMTIME SystemTime;
  656. BOOL sHaveProcessHeapHdl = FALSE;
  657. HANDLE PrHeapHdl;
  658. typedef struct _HEAP_INFO_T {
  659. HANDLE HeapHdl;
  660. LPBYTE cstrHeapType;
  661. } HEAP_INFO_T, *PHEAP_INFO_T;
  662. #define PRINT_TIME_OF_DUMP_M(SystemTime, Str) {DBGPRINT5(SPEC, "Activity: %s done on %d/%d at %d.%d \n", Str, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute); }
  663. #endif
  664. //sfBS = fFlags & WINSINTF_BS;
  665. DBGPRINT2(ERR, "WinsSetFlags: NmsDbDelDelDataRecs = (%d)\nNmsDbDelQueryNUpdRecs = (%d)\n", NmsDbDelDelDataRecs, NmsDbDelQueryNUpdRecs);
  666. #ifdef WINSDBG
  667. if (!sHaveProcessHeapHdl)
  668. {
  669. PrHeapHdl = GetProcessHeap();
  670. }
  671. GetSystemTime(&SystemTime);
  672. WinsDbg |= DBG_SPEC;
  673. if (fFlags & WINSINTF_MEMORY_INFO_DUMP)
  674. {
  675. MEMORYSTATUS Mem;
  676. static SIZE_T sLTVmUsed = 0;
  677. SIZE_T VmUsed;
  678. DBGPRINT0(SPEC, "\n\n------------------MEMORY USAGE INFO-----------------\n\n");
  679. GlobalMemoryStatus(&Mem);
  680. VmUsed = Mem.dwTotalVirtual - Mem.dwAvailVirtual;
  681. DBGPRINT2(SPEC, "VM used = (%d)\nDiff. from last time = (%d)\n", VmUsed,
  682. VmUsed - sLTVmUsed);
  683. sLTVmUsed = VmUsed;
  684. }
  685. EnterCriticalSection(&WinsCnfCnfCrtSec);
  686. try {
  687. if (fFlags & WINSINTF_HEAP_INFO_DUMP)
  688. {
  689. HEAP_INFO_T HeapHdls[] = {
  690. CommUdpBuffHeapHdl, "Udp Buff Heap",
  691. CommUdpDlgHeapHdl, "Udp Dlg Heap",
  692. CommAssocDlgHeapHdl, "Tcp Dlg Heap",
  693. CommAssocTcpMsgHeapHdl, "Tcp Msg Heap",
  694. GenBuffHeapHdl, "General Heap",
  695. QueBuffHeapHdl, "Que Wrk. Item Heap",
  696. NmsChlHeapHdl, "Chl Req/Resp Heap",
  697. CommAssocAssocHeapHdl, "Assoc. Msg Heap",
  698. RplWrkItmHeapHdl, "Rpl Wrk Itm Heap",
  699. NmsRpcHeapHdl, "Rpc Buff Heap",
  700. WinsTmmHeapHdl, "Tmm Buff Heap",
  701. (LPHANDLE)NULL, NULL
  702. };
  703. static SIZE_T sDiffLTHeapTotalANF[sizeof(HeapHdls)/sizeof(HEAP_INFO_T)] = {0};
  704. static SIZE_T sHeapTotalANF[sizeof(HeapHdls)/sizeof(HEAP_INFO_T)] = {0};
  705. SIZE_T Size2;
  706. static SIZE_T sTotalAllocNFree = 0;
  707. static SIZE_T LastTimeTotalAllocNFree = 0;
  708. // NTSTATUS Status;
  709. HANDLE HeapHdl;
  710. DWORD i, n;
  711. DWORD dwNumberOfHeaps;
  712. PHANDLE pPrHeaps;
  713. HEAP_SUMMARY heapSummary;
  714. PRINT_TIME_OF_DUMP_M(SystemTime, "HEAP DUMP");
  715. dwNumberOfHeaps = GetProcessHeaps(0, NULL);
  716. Size2 = sizeof(*pPrHeaps) * dwNumberOfHeaps;
  717. pPrHeaps = WinsMscHeapAlloc( NmsRpcHeapHdl, (ULONG)Size2);
  718. dwNumberOfHeaps = GetProcessHeaps(dwNumberOfHeaps, pPrHeaps);
  719. DBGPRINT1(SPEC, "No Of Heaps is (%d)\n", dwNumberOfHeaps);
  720. DBGPRINT1(SPEC, "Process default heap handle is (%p)\n", PrHeapHdl);
  721. LastTimeTotalAllocNFree = sTotalAllocNFree;
  722. sTotalAllocNFree = 0;
  723. heapSummary.cb = sizeof(HEAP_SUMMARY);
  724. for (i=0; i< dwNumberOfHeaps; i++)
  725. {
  726. DBGPRINT0(SPEC, "----------Heap Info--------------------------\n");
  727. DBGPRINT0(SPEC, "Heap -- ");
  728. HeapHdl = pPrHeaps[i];
  729. for (n = 0; HeapHdls[n].HeapHdl != NULL; n++)
  730. {
  731. if (HeapHdl == HeapHdls[n].HeapHdl)
  732. {
  733. DBGPRINT1(SPEC, "%s\n", HeapHdls[n].cstrHeapType);
  734. break;
  735. }
  736. }
  737. if (HeapHdls[n].HeapHdl == NULL)
  738. {
  739. DBGPRINT0(SPEC, "Catch all Heap\n");
  740. }
  741. DBGPRINT1(SPEC, "Heap Hdl = (%p)\n", HeapHdl);
  742. if (HeapSummary(HeapHdl, 0, &heapSummary))
  743. {
  744. DBGPRINT2(SPEC,"Total Allocated = (%d)\nTotalFree = (%d)\n",
  745. heapSummary.cbAllocated, heapSummary.cbCommitted - heapSummary.cbAllocated);
  746. }
  747. else
  748. {
  749. DBGPRINT0(SPEC,"COULD NOT GET HEAP INFO\n");
  750. continue;
  751. }
  752. sDiffLTHeapTotalANF[n] = heapSummary.cbCommitted - sHeapTotalANF[n];
  753. sHeapTotalANF[n] = heapSummary.cbCommitted;
  754. sTotalAllocNFree += sHeapTotalANF[n];
  755. DBGPRINT1(SPEC, "Size allocated from RpcHeap is (%d)\n", Size2);
  756. } // end of for looping over process heaps
  757. DBGPRINT0(SPEC, "\n----------Heap Info End --------------------------\n");
  758. WinsMscHeapFree(NmsRpcHeapHdl, pPrHeaps);
  759. for (n = 0; HeapHdls[n].HeapHdl != NULL; n++)
  760. {
  761. DBGPRINT3(SPEC, "%s -- Total AllocNFree = (%d); Diff from Last time = (%d)\n",
  762. HeapHdls[n].cstrHeapType, sHeapTotalANF[n],
  763. sDiffLTHeapTotalANF[n]
  764. );
  765. }
  766. DBGPRINT2(SPEC, "\nTotal Process AllocNFree = (%d)\nDiff from last time = (%d)\n\n", sTotalAllocNFree, sTotalAllocNFree - LastTimeTotalAllocNFree);
  767. if (WinsDbg & (DBG_HEAP_CNTRS | DBG_UPD_CNTRS))
  768. {
  769. NmsPrintCtrs();
  770. }
  771. }
  772. if (fFlags & WINSINTF_QUE_ITEMS_DUMP)
  773. {
  774. typedef struct _QUE_INFO_T {
  775. PQUE_HD_T pQueHd;
  776. LPBYTE cstrQueType;
  777. } QUE_INFO_T, *PQUE_INFO_T;
  778. QUE_INFO_T Queues[] = {
  779. &QueNbtWrkQueHd, "Nbt Query Que",
  780. &QueOtherNbtWrkQueHd, "Nbt Reg. Que",
  781. &QueRplPullQueHd, "Pull Thd Que", //Pull requests
  782. &QueRplPushQueHd, "Push Thd Que", //Push requests
  783. &QueNmsNrcqQueHd, "Chl Nbt Req. Msg Que", //Chl req fr nbt thds
  784. &QueNmsRrcqQueHd, "Chl req. from Pull thd Que",
  785. &QueNmsCrqQueHd, "Chl rsp from UDP thd Que",
  786. &QueWinsTmmQueHd, "Timer Queue",
  787. &QueInvalidQueHd, "Invalid Que"
  788. };
  789. PQUE_INFO_T pQueInfo = Queues;
  790. PRINT_TIME_OF_DUMP_M(SystemTime, "WORK ITEM DUMP");
  791. DBGPRINT0(SPEC, "----------Count of Wrk items-----------\n");
  792. for (; pQueInfo->pQueHd != &QueInvalidQueHd; pQueInfo++)
  793. {
  794. PLIST_ENTRY pTmp;
  795. DWORD NoOfWrkItms = 0;
  796. pTmp = &pQueInfo->pQueHd->Head;
  797. EnterCriticalSection(&pQueInfo->pQueHd->CrtSec);
  798. // NoOfWrkItms = pQueInfo->pQueHd->NoOfEntries;
  799. //#if 0
  800. while (pTmp->Flink != &pQueInfo->pQueHd->Head)
  801. {
  802. NoOfWrkItms++;
  803. pTmp = pTmp->Flink;
  804. }
  805. //#endif
  806. LeaveCriticalSection(&pQueInfo->pQueHd->CrtSec);
  807. DBGPRINT2(SPEC, "Que = (%s) has (%d) wrk items\n",
  808. pQueInfo->cstrQueType,
  809. NoOfWrkItms
  810. );
  811. }
  812. DBGPRINT0(SPEC, "----------Count of Wrk items End-----------\n");
  813. }
  814. } // end of try
  815. finally {
  816. if (AbnormalTermination())
  817. {
  818. DBGPRINT0(SPEC, "WinsSetFlags terminated abnormally\n");
  819. }
  820. WinsDbg = DbgFlagsStore;
  821. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  822. } //end of finally { }
  823. #endif
  824. return(Status);
  825. }
  826. DWORD
  827. WinsBackup (
  828. LPBYTE pBackupPath,
  829. short fIncremental
  830. )
  831. {
  832. DWORD RetVal = WINS_FAILURE;
  833. try {
  834. #if 0
  835. RetVal = NmsDbBackup(pBackupPath, fIncremental ? NMSDB_INCREMENTAL_BACKUP :
  836. NMSDB_FULL_BACKUP);
  837. #endif
  838. //
  839. // Always do full backup until Jet is solid enough in doing incremental
  840. // backups. Ian does not seem very sure about how robust it is currently.
  841. // (7/6/94)
  842. //
  843. RetVal = NmsDbBackup(pBackupPath, NMSDB_FULL_BACKUP);
  844. }
  845. except(EXCEPTION_EXECUTE_HANDLER) {
  846. DBGPRINTEXC("WinsBackup");
  847. #if 0
  848. DBGPRINT2(ERR, "WinsBackup: Could not do %s backup to dir (%s)\n", fIncremental ? "INCREMENTAL" : "FULL", pBackupPath);
  849. DBGPRINT1(ERR, "WinsBackup: Could not do full backup to dir (%s)\n", pBackupPath);
  850. #endif
  851. WinsEvtLogDetEvt(FALSE, WINS_EVT_BACKUP_ERR, NULL, __LINE__, "s", pBackupPath);
  852. }
  853. if (RetVal != WINS_SUCCESS)
  854. {
  855. #if 0
  856. RetVal = fIncremental ? WINSINTF_INC_BACKUP_FAILED : WINSINTF_FULL_BACKUP_FAILED;
  857. #endif
  858. RetVal = WINSINTF_FULL_BACKUP_FAILED;
  859. }
  860. else
  861. {
  862. RetVal = WINSINTF_SUCCESS;
  863. }
  864. return(RetVal);
  865. }
  866. DWORD
  867. WinsTerm (
  868. handle_t ClientHdl,
  869. short fAbruptTerm
  870. )
  871. {
  872. DBGPRINT1(FLOW, "WINS TERMINATED %s BY ADMINISTRATOR\n", fAbruptTerm ? "ABRUPTLY" : "GRACEFULLY");
  873. UNREFERENCED_PARAMETER(ClientHdl);
  874. if (fAbruptTerm)
  875. {
  876. fNmsAbruptTerm = TRUE;
  877. WinsMscSignalHdl(NmsMainTermEvt);
  878. ExitProcess(WINS_SUCCESS);
  879. // EnterCriticalSection(&NmsTermCrtSec);
  880. // NmsTotalTrmThdCnt = 0; //force the count to less than 0
  881. // LeaveCriticalSection(&NmsTermCrtSec);
  882. }
  883. WinsMscSignalHdl(NmsMainTermEvt);
  884. return(WINSINTF_SUCCESS);
  885. }
  886. DWORD
  887. WinsRecordAction(
  888. PWINSINTF_RECORD_ACTION_T *ppRecAction
  889. )
  890. /*++
  891. Routine Description:
  892. This function is called to register, query, release a name
  893. Arguments:
  894. pRecAction - Info about the operation to do and the name to insert,
  895. query or release
  896. Externals Used:
  897. None
  898. Return Value:
  899. Success status codes -- WINSINTF_SUCCESS
  900. Error status codes -- WINSINTF_FAILURE
  901. Error Handling:
  902. Called by:
  903. R_WinsRecordAction()
  904. Side Effects:
  905. Comments:
  906. None
  907. --*/
  908. {
  909. STATUS RetStat;
  910. RPL_REC_ENTRY_T Rec;
  911. NMSDB_STAT_INFO_T StatInfo;
  912. NMSMSGF_CNT_ADD_T CntAdd;
  913. DWORD i, n;
  914. BOOL fSwapped = FALSE;
  915. PWINSINTF_RECORD_ACTION_T pRecAction = *ppRecAction;
  916. NmsDbThdInit(WINS_E_WINSRPC);
  917. NmsDbOpenTables(WINS_E_WINSRPC);
  918. DBGMYNAME("RPC-WinsRecordAction");
  919. try {
  920. CntAdd.NoOfAdds = 1;
  921. CntAdd.Add[0].AddTyp_e = pRecAction->Add.Type;
  922. CntAdd.Add[0].AddLen = pRecAction->Add.Len;
  923. CntAdd.Add[0].Add.IPAdd = pRecAction->Add.IPAdd;
  924. //
  925. // Check to see if it is a PDC name (0x1B in the 16th byte). Do this only
  926. // if the name is atleast 16 bytes long. Winscl or some other tool may
  927. // send a shorter name. Netbt will never send a shorter name.
  928. //
  929. if ((pRecAction->NameLen >= (WINS_MAX_NS_NETBIOS_NAME_LEN - 1)) && (*(pRecAction->pName + 15) == 0x1B))
  930. {
  931. WINS_SWAP_BYTES_M(pRecAction->pName, pRecAction->pName + 15);
  932. fSwapped = TRUE;
  933. }
  934. //
  935. // just in case the admin. tool is screwing up and passing us an invalid
  936. // name length, adjust the length.
  937. //
  938. if (pRecAction->NameLen > WINS_MAX_NAME_SZ)
  939. {
  940. pRecAction->NameLen = WINS_MAX_NAME_SZ - 1;
  941. }
  942. //
  943. // Terminate name with NULL, just in case user didn't do it.
  944. //
  945. *(pRecAction->pName + pRecAction->NameLen) = (TCHAR)NULL;
  946. switch(pRecAction->Cmd_e)
  947. {
  948. case(WINSINTF_E_INSERT):
  949. if (pRecAction->TypOfRec_e == WINSINTF_E_UNIQUE)
  950. {
  951. RetStat = NmsNmhNamRegInd(
  952. NULL, //no dialogue handle
  953. (LPBYTE)pRecAction->pName,
  954. pRecAction->NameLen + 1, //to include the ending //0 byte. See GetName()
  955. //in nmsmsgf.c
  956. CntAdd.Add,
  957. pRecAction->NodeTyp,
  958. NULL,
  959. 0,
  960. 0,
  961. FALSE, //it is a name reg (nor a ref)
  962. pRecAction->fStatic,
  963. TRUE // administrative action
  964. );
  965. }
  966. else // the record is a group or multihomed
  967. {
  968. if (
  969. (pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED )
  970. ||
  971. (pRecAction->TypOfRec_e == WINSINTF_E_SPEC_GROUP )
  972. )
  973. {
  974. for (i = 0; i < pRecAction->NoOfAdds; i++)
  975. {
  976. //
  977. // pAdd is a unique pointer and so can be
  978. // NULL. We however do not protect oureelves
  979. // here for the following reasons
  980. //
  981. // - the call can only be executed by Admins
  982. // on this machine and through tools
  983. // that MS provides that do not pass pAdd as
  984. // NULL. The rpc call is not published
  985. //
  986. // - AV will be caught and a failure returned.
  987. // No harm done.
  988. //
  989. CntAdd.Add[i].AddTyp_e =
  990. (pRecAction->pAdd + i)->Type;
  991. CntAdd.Add[i].AddLen =
  992. (pRecAction->pAdd + i)->Len;
  993. CntAdd.Add[i].Add.IPAdd =
  994. (pRecAction->pAdd + i)->IPAdd;
  995. }
  996. CntAdd.NoOfAdds = pRecAction->NoOfAdds;
  997. }
  998. RetStat= NmsNmhNamRegGrp(
  999. NULL, //no dialogue handle
  1000. (LPBYTE)pRecAction->pName,
  1001. pRecAction->NameLen + 1,
  1002. &CntAdd,
  1003. 0, //node type (not used)
  1004. NULL,
  1005. 0,
  1006. 0,
  1007. pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED ? NMSDB_MULTIHOMED_ENTRY : (NMSDB_IS_IT_SPEC_GRP_NM_M(pRecAction->pName) || (pRecAction->TypOfRec_e == WINSINTF_E_NORM_GROUP) ? NMSDB_NORM_GRP_ENTRY : NMSDB_SPEC_GRP_ENTRY),
  1008. FALSE, //it is a name reg (nor a ref)
  1009. pRecAction->fStatic,
  1010. TRUE // administrative action
  1011. );
  1012. }
  1013. break;
  1014. case(WINSINTF_E_RELEASE):
  1015. if (
  1016. (pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED)
  1017. ||
  1018. (pRecAction->TypOfRec_e == WINSINTF_E_SPEC_GROUP)
  1019. )
  1020. {
  1021. if (pRecAction->pAdd != NULL)
  1022. {
  1023. CntAdd.Add[0].AddTyp_e = pRecAction->pAdd->Type;
  1024. CntAdd.Add[0].AddLen = pRecAction->pAdd->Len;
  1025. CntAdd.Add[0].Add.IPAdd = pRecAction->pAdd->IPAdd;
  1026. }
  1027. }
  1028. RetStat = NmsNmhNamRel(
  1029. NULL, //no dialogue handle
  1030. (LPBYTE)pRecAction->pName,
  1031. pRecAction->NameLen + 1,
  1032. CntAdd.Add,
  1033. pRecAction->TypOfRec_e ==
  1034. WINSINTF_E_UNIQUE ? FALSE : TRUE,
  1035. NULL,
  1036. 0,
  1037. 0,
  1038. TRUE // administrative action
  1039. );
  1040. break;
  1041. case(WINSINTF_E_QUERY):
  1042. //
  1043. // Anybody can query a record. We don't have any security
  1044. // for plain queries. Therefore somebody can cause a leak
  1045. // by making calls with pAdd pointing to allocated memory.
  1046. // Let us free that memory and proceed. We can return
  1047. // failure also but let us cover for our legit caller's
  1048. // mistakes. Currently, the only known callers of this
  1049. // function are winsmon, winscl, winsadmn (NT 4 and before)
  1050. // and wins snapin.
  1051. //
  1052. if (pRecAction->pAdd != NULL)
  1053. {
  1054. midl_user_free(pRecAction->pAdd);
  1055. }
  1056. RetStat = NmsNmhNamQuery(
  1057. NULL, //no dialogue handle
  1058. (LPBYTE)pRecAction->pName,
  1059. pRecAction->NameLen + 1,
  1060. NULL,
  1061. 0,
  1062. 0,
  1063. TRUE, // administrative action
  1064. &StatInfo
  1065. );
  1066. if (RetStat == WINS_SUCCESS)
  1067. {
  1068. pRecAction->TypOfRec_e = StatInfo.EntTyp;
  1069. pRecAction->OwnerId = StatInfo.OwnerId;
  1070. pRecAction->State_e =
  1071. (WINSINTF_STATE_E)StatInfo.EntryState_e;
  1072. pRecAction->TimeStamp = StatInfo.TimeStamp;
  1073. if (
  1074. NMSDB_ENTRY_UNIQUE_M(StatInfo.EntTyp)
  1075. ||
  1076. NMSDB_ENTRY_NORM_GRP_M(StatInfo.EntTyp)
  1077. )
  1078. {
  1079. pRecAction->NoOfAdds = 0;
  1080. pRecAction->pAdd = NULL;
  1081. pRecAction->Add.IPAdd =
  1082. StatInfo.NodeAdds.Mem[0].Add.Add.IPAdd;
  1083. pRecAction->Add.Type =
  1084. (UCHAR) StatInfo.NodeAdds.Mem[0].Add.AddTyp_e;
  1085. pRecAction->Add.Len =
  1086. StatInfo.NodeAdds.Mem[0].Add.AddLen;
  1087. }
  1088. else
  1089. {
  1090. PNMSDB_WINS_STATE_E pWinsState_e;
  1091. PCOMM_ADD_T pAdd;
  1092. PVERS_NO_T pStartVersNo;
  1093. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  1094. try {
  1095. if (StatInfo.NodeAdds.NoOfMems > 0)
  1096. {
  1097. pRecAction->NoOfAdds = StatInfo.NodeAdds.NoOfMems * 2;
  1098. pRecAction->pAdd = midl_user_allocate(pRecAction->NoOfAdds * sizeof(WINSINTF_ADD_T));
  1099. }
  1100. else
  1101. {
  1102. pRecAction->NoOfAdds = 0;
  1103. pRecAction->pAdd = NULL;
  1104. }
  1105. for (
  1106. n = 0, i = 0;
  1107. n < (StatInfo.NodeAdds.NoOfMems) && n < WINSINTF_MAX_MEM; n++
  1108. )
  1109. {
  1110. RPL_FIND_ADD_BY_OWNER_ID_M(
  1111. StatInfo.NodeAdds.Mem[n].OwnerId,
  1112. pAdd,
  1113. pWinsState_e,
  1114. pStartVersNo
  1115. );
  1116. (pRecAction->pAdd + i++)->IPAdd = pAdd->Add.IPAdd;
  1117. (pRecAction->pAdd + i++)->IPAdd =
  1118. StatInfo.NodeAdds.Mem[n].Add.Add.IPAdd;
  1119. }
  1120. }
  1121. except(EXCEPTION_EXECUTE_HANDLER) {
  1122. DWORD ExcCode = GetExceptionCode();
  1123. WINSEVT_LOG_M(ExcCode, WINS_EVT_RPC_EXC);
  1124. DBGPRINT1(EXC, "WinsRecordAction: Got Exception (%x)\n", ExcCode);
  1125. }
  1126. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  1127. }
  1128. pRecAction->NodeTyp = StatInfo.NodeTyp;
  1129. pRecAction->VersNo = StatInfo.VersNo;
  1130. pRecAction->fStatic = StatInfo.fStatic;
  1131. }
  1132. else
  1133. {
  1134. pRecAction->NoOfAdds = 0;
  1135. pRecAction->pAdd = NULL;
  1136. }
  1137. break;
  1138. case(WINSINTF_E_MODIFY):
  1139. //
  1140. // Note: Currently, the administrator can not change the
  1141. // address in the record
  1142. //
  1143. time((time_t *)&Rec.NewTimeStamp);
  1144. //
  1145. // If the record type is wrong, return a failure
  1146. //
  1147. if (pRecAction->TypOfRec_e > WINSINTF_E_MULTIHOMED)
  1148. {
  1149. RetStat = WINS_FAILURE;
  1150. break;
  1151. }
  1152. //
  1153. // If the state specified is wrong, return a failure
  1154. //
  1155. if (pRecAction->State_e > WINSINTF_E_DELETED)
  1156. {
  1157. RetStat = WINS_FAILURE;
  1158. break;
  1159. }
  1160. NMSDB_SET_ENTRY_TYPE_M(Rec.Flag, pRecAction->TypOfRec_e);
  1161. NMSDB_SET_NODE_TYPE_M(Rec.Flag, pRecAction->NodeTyp);
  1162. NMSDB_SET_STDYN_M(Rec.Flag, pRecAction->fStatic);
  1163. //
  1164. // Fall through
  1165. //
  1166. case(WINSINTF_E_DELETE):
  1167. NMSDB_SET_STATE_M(Rec.Flag, pRecAction->State_e)
  1168. Rec.pName = pRecAction->pName;
  1169. Rec.NameLen = pRecAction->NameLen + 1;
  1170. //
  1171. // NOTE:
  1172. // The index on the name address table was set to
  1173. // the clustered index column (as required by this function)
  1174. // in NmsDbThdInit()
  1175. //
  1176. RetStat = NmsDbQueryNUpdIfMatch(
  1177. &Rec,
  1178. THREAD_PRIORITY_NORMAL,
  1179. FALSE, //don't change priority to
  1180. //normal
  1181. WINS_E_WINSRPC //ensures no matching
  1182. //of timestamps
  1183. );
  1184. if (RetStat == WINS_SUCCESS)
  1185. {
  1186. DBGPRINT1(DET, "WinsRecordAction: Record (%s) deleted\n",
  1187. Rec.pName);
  1188. FUTURES("use macros defined in winsevt.h. Change to warning")
  1189. if (WinsCnf.LogDetailedEvts > 0)
  1190. {
  1191. WinsEvtLogDetEvt(TRUE, WINS_EVT_REC_DELETED, NULL, __LINE__, "s", Rec.pName);
  1192. }
  1193. }
  1194. break;
  1195. default:
  1196. RetStat = WINS_FAILURE;
  1197. break;
  1198. }
  1199. } // end of try
  1200. except(EXCEPTION_EXECUTE_HANDLER) {
  1201. DWORD ExcCode = GetExceptionCode();
  1202. WINSEVT_LOG_M(ExcCode, WINS_EVT_RPC_EXC);
  1203. DBGPRINT1(EXC, "WinsRecordAction: Got Exception (%x)\n", ExcCode);
  1204. }
  1205. if (fSwapped)
  1206. {
  1207. WINS_SWAP_BYTES_M(pRecAction->pName, pRecAction->pName + 15);
  1208. }
  1209. //
  1210. // Let us end the session
  1211. //
  1212. NmsDbCloseTables();
  1213. NmsDbEndSession();
  1214. if (RetStat == WINS_SUCCESS)
  1215. {
  1216. RetStat = WINSINTF_SUCCESS;
  1217. }
  1218. else
  1219. {
  1220. if (pRecAction->Cmd_e == WINSINTF_E_QUERY)
  1221. {
  1222. RetStat = WINSINTF_REC_NOT_FOUND;
  1223. }
  1224. else
  1225. {
  1226. RetStat = WINSINTF_FAILURE;
  1227. }
  1228. }
  1229. return(RetStat);
  1230. }
  1231. DWORD
  1232. GetWinsStatus(
  1233. IN WINSINTF_CMD_E Cmd_e,
  1234. OUT LPVOID pResults,
  1235. BOOL fNew
  1236. )
  1237. /*++
  1238. Routine Description:
  1239. This function is called to get the information pertaining to WINS
  1240. Refer WINSINTF_RESULTS_T data structure to see what information
  1241. is retrieved
  1242. Arguments:
  1243. Cmd_e - Command to execute
  1244. pResults - Info. retrieved
  1245. Externals Used:
  1246. None
  1247. Return Value:
  1248. Success status codes -- WINSINTF_SUCCESS
  1249. Error status codes -- WINSINTF_FAILURE
  1250. Error Handling:
  1251. Called by:
  1252. R_WinsStatus()
  1253. Side Effects:
  1254. Comments:
  1255. None
  1256. --*/
  1257. {
  1258. DWORD RetVal = WINSINTF_FAILURE;
  1259. switch(Cmd_e)
  1260. {
  1261. case(WINSINTF_E_ADDVERSMAP):
  1262. if (fNew)
  1263. {
  1264. break;
  1265. }
  1266. RetVal = sGetVersNo(pResults);
  1267. break;
  1268. case(WINSINTF_E_CONFIG):
  1269. RetVal = GetConfig(pResults, fNew, FALSE);
  1270. break;
  1271. case(WINSINTF_E_CONFIG_ALL_MAPS):
  1272. RetVal = GetConfig(pResults, fNew, TRUE);
  1273. break;
  1274. case(WINSINTF_E_STAT):
  1275. RetVal = GetStatistics(pResults, fNew);
  1276. break;
  1277. default:
  1278. DBGPRINT1(ERR, "WinsStatus: Weird: Bad RPC Status command = (%D) \n", Cmd_e);
  1279. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_BAD_RPC_STATUS_CMD);
  1280. break;
  1281. }
  1282. return(RetVal);
  1283. }
  1284. DWORD
  1285. WinsTrigger(
  1286. PWINSINTF_ADD_T pWinsAdd,
  1287. WINSINTF_TRIG_TYPE_E TrigType_e
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. This function is called to send a trigger to a remote WINS so that
  1292. it may pull the latest information from it
  1293. Arguments:
  1294. pWinsAdd - Address of WINS to send a Push update notification to
  1295. Externals Used:
  1296. None
  1297. Return Value:
  1298. Success status codes -- WINSINTF_SUCCESS
  1299. Error status codes -- WINSINTF_FAILURE
  1300. Error Handling:
  1301. Called by:
  1302. R_WinsTrigger
  1303. Side Effects:
  1304. Comments:
  1305. A Trigger is sent to a remote WINS only if it is specified
  1306. under the PULL/PUSH subkey of the PARTNERS key in the registry
  1307. --*/
  1308. {
  1309. PRPL_CONFIG_REC_T pPnr;
  1310. DWORD RetCode = WINSINTF_SUCCESS;
  1311. BOOL fRplPnr = FALSE;
  1312. QUE_CMD_TYP_E CmdType_e;
  1313. DBGENTER("WinsTrigger\n");
  1314. //
  1315. // Enter the critical sections guarded by WinsCnfCnfCrtSec and
  1316. // NmsNmhNamRegCrtSec. There is no danger of deadlock because we
  1317. // always enter the two critical sections in the following sequence
  1318. //
  1319. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1320. PERF("Do we need to enter the following critical section")
  1321. // EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1322. try {
  1323. if (
  1324. (TrigType_e == WINSINTF_E_PUSH)
  1325. ||
  1326. (TrigType_e == WINSINTF_E_PUSH_PROP)
  1327. )
  1328. {
  1329. DBGPRINT1(DET, "WinsTrigger. Send Push trigger to (%x)\n",
  1330. pWinsAdd->IPAdd);
  1331. CmdType_e = (TrigType_e == WINSINTF_E_PUSH ?
  1332. QUE_E_CMD_SND_PUSH_NTF :
  1333. QUE_E_CMD_SND_PUSH_NTF_PROP);
  1334. pPnr = WinsCnf.PushInfo.pPushCnfRecs;
  1335. }
  1336. else // it is a pull trigger
  1337. {
  1338. DBGPRINT1(DET, "WinsTrigger. Send Pull trigger to (%x)\n",
  1339. pWinsAdd->IPAdd);
  1340. CmdType_e = QUE_E_CMD_REPLICATE;
  1341. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  1342. }
  1343. if (WinsCnf.fRplOnlyWCnfPnrs)
  1344. {
  1345. if (pPnr != NULL)
  1346. {
  1347. //
  1348. // Search for the Cnf record for the WINS we want to
  1349. // send the PUSH notification to/Replicate with.
  1350. //
  1351. for (
  1352. ;
  1353. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  1354. &&
  1355. !fRplPnr;
  1356. // no third expression
  1357. )
  1358. {
  1359. DBGPRINT1(DET, "WinsTrigger. Comparing with (%x)\n",
  1360. pPnr->WinsAdd.Add.IPAdd);
  1361. //
  1362. // Check if this is the one we want
  1363. //
  1364. if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->IPAdd)
  1365. {
  1366. //
  1367. // We are done. Set the fRplPnr flag to TRUE so that
  1368. // we break out of the loop.
  1369. //
  1370. // Note: Don't use break since that would cause
  1371. // a search for a 'finally' block
  1372. //
  1373. fRplPnr = TRUE;
  1374. //
  1375. // Make it 0, so that we always try to establish
  1376. // a connection. Otherwise, pull thread may not
  1377. // try if it has already exhausted the number of
  1378. // retries
  1379. //
  1380. pPnr->RetryCount = 0;
  1381. continue; //so that we can break out
  1382. }
  1383. //
  1384. // Get the next record that follows this one sequentially
  1385. //
  1386. pPnr = WinsCnfGetNextRplCnfRec(
  1387. pPnr,
  1388. RPL_E_IN_SEQ //seq. traversal
  1389. );
  1390. } // end of for
  1391. } // end of if (pPnr != 0)
  1392. } // end of if (fRplOnlyWCnfPnrs)
  1393. else
  1394. {
  1395. //
  1396. // Allocate from the general heap because that is what
  1397. // is used by the replicator.
  1398. //
  1399. WinsMscAlloc(RPL_CONFIG_REC_SIZE, &pPnr);
  1400. COMM_INIT_ADD_M(&pPnr->WinsAdd, pWinsAdd->IPAdd);
  1401. pPnr->MagicNo = 0;
  1402. pPnr->RetryCount = 0;
  1403. pPnr->LastCommFailTime = 0;
  1404. pPnr->PushNtfTries = 0;
  1405. fRplPnr = TRUE;
  1406. //
  1407. // We want the buffer to be deallocated by the PULL thread
  1408. //
  1409. pPnr->fTemp = TRUE;
  1410. }
  1411. //
  1412. // If replication needs to be done
  1413. //
  1414. if (fRplPnr)
  1415. {
  1416. //
  1417. // Call RplInsertQue to insert the push request to
  1418. // the Pull Thread
  1419. //
  1420. ERplInsertQue(
  1421. WINS_E_WINSRPC,
  1422. CmdType_e,
  1423. NULL, //no Dlg Hdl
  1424. NULL, //no msg is there
  1425. 0, //msg length
  1426. pPnr, //client context
  1427. pPnr->MagicNo
  1428. );
  1429. }
  1430. } // end of try block
  1431. except (EXCEPTION_EXECUTE_HANDLER) {
  1432. DWORD ExcCode = GetExceptionCode();
  1433. DBGPRINT1(EXC, "WinsTrigger: Got Exception (%x)\n", ExcCode);
  1434. WINSEVT_LOG_D_M(ExcCode, WINS_EVT_PUSH_TRIGGER_EXC);
  1435. RetCode = WINSINTF_FAILURE;
  1436. }
  1437. //
  1438. // Leave the critical section guarded by NmsNmhNamRegCrtSec.
  1439. //
  1440. // LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1441. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1442. //
  1443. // if replication was allowed only with configured partners and
  1444. // there was no WINS with the address specified by the client,
  1445. // return failure
  1446. //
  1447. if (!fRplPnr)
  1448. {
  1449. RetCode = WINSINTF_RPL_NOT_ALLOWED;
  1450. }
  1451. DBGLEAVE("WinsTrigger\n");
  1452. return(RetCode);
  1453. }
  1454. DWORD
  1455. sGetVersNo(
  1456. LPVOID pResultsA
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. This function returns with the highest version number of records
  1461. owned by a particular WINS
  1462. Arguments:
  1463. Externals Used:
  1464. None
  1465. Return Value:
  1466. Success status codes -- WINSINTF_SUCCESS
  1467. Error status codes -- WINSINTF_FAILURE
  1468. Error Handling:
  1469. Called by:
  1470. Side Effects:
  1471. Comments:
  1472. None
  1473. --*/
  1474. {
  1475. COMM_ADD_T WinsAdd;
  1476. DWORD OwnerId;
  1477. STATUS RetStat;
  1478. VERS_NO_T VersNo;
  1479. BOOL fAllocNew = FALSE;
  1480. PWINSINTF_RESULTS_T pResults = pResultsA;
  1481. WinsAdd.AddLen = sizeof(COMM_IP_ADD_T);
  1482. WinsAdd.AddTyp_e = COMM_ADD_E_TCPUDPIP;
  1483. WinsAdd.Add.IPAdd = pResults->AddVersMaps[0].Add.IPAdd;
  1484. RetStat = RplFindOwnerId(
  1485. &WinsAdd,
  1486. &fAllocNew, //don't assign if not there
  1487. &OwnerId,
  1488. WINSCNF_E_IGNORE_PREC,
  1489. WINSCNF_LOW_PREC
  1490. );
  1491. if(RetStat != WINS_SUCCESS)
  1492. {
  1493. return(WINSINTF_FAILURE);
  1494. }
  1495. if (OwnerId == 0)
  1496. {
  1497. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1498. NMSNMH_DEC_VERS_NO_M(NmsNmhMyMaxVersNo, VersNo);
  1499. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1500. pResults->AddVersMaps[0].VersNo = VersNo;
  1501. }
  1502. else
  1503. {
  1504. EnterCriticalSection(&RplVersNoStoreCrtSec);
  1505. try {
  1506. pResults->AddVersMaps[0].VersNo =
  1507. (pRplPullOwnerVersNo+OwnerId)->VersNo;
  1508. }
  1509. except(EXCEPTION_EXECUTE_HANDLER) {
  1510. DBGPRINTEXC("sGetVersNo");
  1511. }
  1512. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  1513. }
  1514. return(WINSINTF_SUCCESS);
  1515. }
  1516. DWORD
  1517. GetConfig(
  1518. OUT LPVOID pResultsA,
  1519. IN BOOL fNew,
  1520. IN BOOL fAllMaps
  1521. )
  1522. /*++
  1523. Routine Description:
  1524. This function returns with configuration information
  1525. and counter info related to replication
  1526. Arguments:
  1527. pResults - has the information retrieved
  1528. Externals Used:
  1529. None
  1530. Return Value:
  1531. Success status codes -- WINSINTF_SUCCESS
  1532. Error status codes -- WINSINTF_FAILURE
  1533. Error Handling:
  1534. Called by:
  1535. GetWinsStatus()
  1536. Side Effects:
  1537. Comments:
  1538. None
  1539. --*/
  1540. {
  1541. PNMSDB_WINS_STATE_E pWinsState_e;
  1542. PCOMM_ADD_T pWinsAdd;
  1543. PVERS_NO_T pStartVersNo;
  1544. DWORD i, n;
  1545. VERS_NO_T MyMaxVersNo;
  1546. PWINSINTF_ADD_VERS_MAP_T pAddVersMaps, pAddVersMapsStore;
  1547. PWINSINTF_RESULTS_T pResults = pResultsA;
  1548. PWINSINTF_RESULTS_NEW_T pResultsN = pResultsA;
  1549. BOOL fDel;
  1550. VERS_NO_T VersNoForDelRec;
  1551. if (fAllMaps)
  1552. {
  1553. fDel = FALSE;
  1554. VersNoForDelRec.HighPart = MAXLONG;
  1555. VersNoForDelRec.LowPart = MAXULONG;
  1556. }
  1557. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1558. MyMaxVersNo = NmsNmhMyMaxVersNo;
  1559. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1560. if (fNew)
  1561. {
  1562. pResultsN->pAddVersMaps =
  1563. midl_user_allocate(NmsDbNoOfOwners * sizeof(WINSINTF_ADD_VERS_MAP_T));
  1564. pAddVersMaps = pResultsN->pAddVersMaps;
  1565. }
  1566. else
  1567. {
  1568. pAddVersMaps = pResults->AddVersMaps;
  1569. }
  1570. pAddVersMapsStore = pAddVersMaps;
  1571. //
  1572. // First extract the timeouts and Non-remote WINS information
  1573. // from the WinsCnf global var. We enter the WinsCnfCnfCrtSec
  1574. // since we need to synchronize with the thread doing the
  1575. // reinitialization (Main thread)
  1576. //
  1577. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1578. if (!fNew)
  1579. {
  1580. pResults->RefreshInterval = WinsCnf.RefreshInterval;
  1581. pResults->TombstoneInterval = WinsCnf.TombstoneInterval;
  1582. pResults->TombstoneTimeout = WinsCnf.TombstoneTimeout;
  1583. pResults->VerifyInterval = WinsCnf.VerifyInterval;
  1584. pResults->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
  1585. pResults->NoOfWorkerThds = NmsNoOfNbtThds;
  1586. }
  1587. else
  1588. {
  1589. pResultsN->RefreshInterval = WinsCnf.RefreshInterval;
  1590. pResultsN->TombstoneInterval = WinsCnf.TombstoneInterval;
  1591. pResultsN->TombstoneTimeout = WinsCnf.TombstoneTimeout;
  1592. pResultsN->VerifyInterval = WinsCnf.VerifyInterval;
  1593. pResultsN->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
  1594. pResultsN->NoOfWorkerThds = NmsNoOfNbtThds;
  1595. }
  1596. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1597. //
  1598. // Enter two critical sections in sequence. No danger of deadlock
  1599. // here. The only other thread that takes both these critical section
  1600. // is the RplPush thread. It takes these in the same order (See
  1601. // HandleVersMapReq())
  1602. //
  1603. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  1604. EnterCriticalSection(&RplVersNoStoreCrtSec);
  1605. try {
  1606. NONPORT("Change when using different address family")
  1607. for (
  1608. i=0, n = 0;
  1609. i < NmsDbNoOfOwners;
  1610. i++
  1611. )
  1612. {
  1613. if (!fNew && (i == WINSINTF_MAX_NO_RPL_PNRS))
  1614. {
  1615. break;
  1616. }
  1617. //
  1618. // if the record is deleted in the in-memory table, it
  1619. // means that there are no records for it in the
  1620. // database
  1621. //
  1622. if ((pNmsDbOwnAddTbl+i)->WinsState_e == NMSDB_E_WINS_DELETED)
  1623. {
  1624. //
  1625. // if only active mappings are sought, skip this
  1626. // entry
  1627. //
  1628. if (!fAllMaps)
  1629. {
  1630. continue;
  1631. }
  1632. else
  1633. {
  1634. fDel = TRUE;
  1635. }
  1636. }
  1637. //
  1638. // Find address corresponding to the owner id.
  1639. //
  1640. RPL_FIND_ADD_BY_OWNER_ID_M(i, pWinsAdd, pWinsState_e,
  1641. pStartVersNo);
  1642. //
  1643. // It is possible for NmsDbNoOfOwners to be more than the
  1644. // number of initialized RplPullVersNoTbl entries. When
  1645. // we reach a NULL entry, we break out of the loop.
  1646. //
  1647. if (pWinsAdd != NULL)
  1648. {
  1649. pAddVersMaps->Add.Type = WINSINTF_TCP_IP;
  1650. pAddVersMaps->Add.Len = pWinsAdd->AddLen;
  1651. pAddVersMaps->Add.IPAdd = pWinsAdd->Add.IPAdd;
  1652. pAddVersMaps++->VersNo = (fDel == FALSE) ? (pRplPullOwnerVersNo+i)->VersNo : VersNoForDelRec;
  1653. }
  1654. else
  1655. {
  1656. break;
  1657. }
  1658. if (fDel)
  1659. {
  1660. fDel = FALSE;
  1661. }
  1662. n++;
  1663. } // end of for ..
  1664. //
  1665. // Since RplPullOwnerVersNo[0] may be out of date, let us get
  1666. // get the uptodate value
  1667. //
  1668. NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
  1669. pAddVersMapsStore->VersNo
  1670. );
  1671. if (fNew)
  1672. {
  1673. pResultsN->NoOfOwners = n;
  1674. }
  1675. else
  1676. {
  1677. pResults->NoOfOwners = n;
  1678. }
  1679. NOTE("Wins Mib agent relies on the first entry being that of the local WINS")
  1680. NOTE("See WinsMib.c -- EnumAddKeys")
  1681. #if 0
  1682. //
  1683. // Since RplPullOwnerVersNo[0] may be out of date, let us get
  1684. // get the uptodate value
  1685. //
  1686. NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
  1687. pResults->AddVersMaps[0].VersNo
  1688. );
  1689. #endif
  1690. }
  1691. except(EXCEPTION_EXECUTE_HANDLER) {
  1692. DBGPRINTEXC("GetConfig");
  1693. //
  1694. // log a message
  1695. //
  1696. }
  1697. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  1698. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  1699. return(WINSINTF_SUCCESS);
  1700. }
  1701. DWORD
  1702. GetStatistics(
  1703. LPVOID pResultsA,
  1704. BOOL fNew
  1705. )
  1706. /*++
  1707. Routine Description:
  1708. This function returns with the highest version number of records
  1709. owned by a particular WINS
  1710. Arguments:
  1711. Externals Used:
  1712. None
  1713. Return Value:
  1714. Success status codes -- WINSINTF_SUCCESS
  1715. Error status codes -- WINSINTF_FAILURE
  1716. Error Handling:
  1717. Called by:
  1718. Side Effects:
  1719. Comments:
  1720. None
  1721. --*/
  1722. {
  1723. PRPL_CONFIG_REC_T pPnr;
  1724. PWINSINTF_RPL_COUNTERS_T pPnrData;
  1725. DWORD i;
  1726. PWINSINTF_RESULTS_T pResults = pResultsA;
  1727. PWINSINTF_RESULTS_NEW_T pResultsN = pResultsA;
  1728. ASSERT(pResults != NULL);
  1729. //
  1730. // If client passed us a non-null pRplPnr, then we return failure
  1731. // so as to avoid a memory leak.
  1732. //
  1733. if (!fNew)
  1734. {
  1735. if (pResults->WinsStat.pRplPnrs != NULL)
  1736. {
  1737. return(WINSINTF_FAILURE);
  1738. }
  1739. }
  1740. else
  1741. {
  1742. if (pResultsN->WinsStat.pRplPnrs != NULL)
  1743. {
  1744. return(WINSINTF_FAILURE);
  1745. }
  1746. }
  1747. //
  1748. // Copy the counters
  1749. //
  1750. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1751. if (!fNew)
  1752. {
  1753. pResults->WinsStat.Counters = WinsIntfStat.Counters;
  1754. FUTURES("Get rid of of the following two fields")
  1755. pResults->WinsStat.Counters.NoOfQueries =
  1756. WinsIntfStat.Counters.NoOfSuccQueries +
  1757. WinsIntfStat.Counters.NoOfFailQueries;
  1758. pResults->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
  1759. + WinsIntfStat.Counters.NoOfFailRel;
  1760. }
  1761. else
  1762. {
  1763. pResultsN->WinsStat.Counters = WinsIntfStat.Counters;
  1764. FUTURES("Get rid of of the following two fields")
  1765. pResultsN->WinsStat.Counters.NoOfQueries =
  1766. WinsIntfStat.Counters.NoOfSuccQueries +
  1767. WinsIntfStat.Counters.NoOfFailQueries;
  1768. pResultsN->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
  1769. + WinsIntfStat.Counters.NoOfFailRel;
  1770. }
  1771. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1772. //
  1773. // Copy the TimeStamps and replication specific counters
  1774. //
  1775. EnterCriticalSection(&WinsIntfCrtSec);
  1776. {
  1777. PWINSINTF_STAT_T pWinsStat = (fNew) ? &(pResultsN->WinsStat) : &(pResults->WinsStat);
  1778. TIME_ZONE_INFORMATION tzInfo;
  1779. GetTimeZoneInformation(&tzInfo);
  1780. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.WinsStartTime), &(pWinsStat->TimeStamps.WinsStartTime));
  1781. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPScvTime), &(pWinsStat->TimeStamps.LastPScvTime));
  1782. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATScvTime), &(pWinsStat->TimeStamps.LastATScvTime));
  1783. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastTombScvTime), &(pWinsStat->TimeStamps.LastTombScvTime));
  1784. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastVerifyScvTime), &(pWinsStat->TimeStamps.LastVerifyScvTime));
  1785. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastInitDbTime), &(pWinsStat->TimeStamps.LastInitDbTime));
  1786. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPRplTime), &(pWinsStat->TimeStamps.LastPRplTime));
  1787. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATRplTime), &(pWinsStat->TimeStamps.LastATRplTime));
  1788. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastNTRplTime), &(pWinsStat->TimeStamps.LastNTRplTime));
  1789. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastACTRplTime), &(pWinsStat->TimeStamps.LastACTRplTime));
  1790. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.CounterResetTime), &(pWinsStat->TimeStamps.CounterResetTime));
  1791. }
  1792. LeaveCriticalSection(&WinsIntfCrtSec);
  1793. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1794. try {
  1795. DWORD NoOfPnrs;
  1796. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  1797. if (!fNew)
  1798. {
  1799. NoOfPnrs = pResults->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
  1800. }
  1801. else
  1802. {
  1803. NoOfPnrs = pResultsN->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
  1804. }
  1805. //
  1806. // If no. of push pnrs (pnrs under the pull key) is > 0
  1807. //
  1808. if (NoOfPnrs > 0)
  1809. {
  1810. if (!fNew)
  1811. {
  1812. pPnrData = pResults->WinsStat.pRplPnrs =
  1813. midl_user_allocate(pResults->WinsStat.NoOfPnrs *
  1814. sizeof(WINSINTF_RPL_COUNTERS_T));
  1815. }
  1816. else
  1817. {
  1818. pPnrData = pResultsN->WinsStat.pRplPnrs =
  1819. midl_user_allocate(pResultsN->WinsStat.NoOfPnrs *
  1820. sizeof(WINSINTF_RPL_COUNTERS_T));
  1821. }
  1822. PERF("remove one of the expressions in the test condition of the if statement")
  1823. for (
  1824. i = 0;
  1825. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  1826. &&
  1827. i < NoOfPnrs;
  1828. pPnrData++, i++
  1829. )
  1830. {
  1831. pPnrData->Add.IPAdd = pPnr->WinsAdd.Add.IPAdd;
  1832. (VOID)InterlockedExchange(
  1833. &pPnrData->NoOfRpls, pPnr->NoOfRpls);
  1834. (VOID)InterlockedExchange(
  1835. &pPnrData->NoOfCommFails,
  1836. pPnr->NoOfCommFails
  1837. );
  1838. //
  1839. // Get the next record that follows this one sequentially
  1840. //
  1841. pPnr = WinsCnfGetNextRplCnfRec(
  1842. pPnr,
  1843. RPL_E_IN_SEQ //seq. traversal
  1844. );
  1845. }
  1846. }
  1847. else
  1848. {
  1849. if (!fNew)
  1850. {
  1851. pResults->WinsStat.pRplPnrs = NULL;
  1852. }
  1853. else
  1854. {
  1855. pResultsN->WinsStat.pRplPnrs = NULL;
  1856. }
  1857. }
  1858. }
  1859. except(EXCEPTION_EXECUTE_HANDLER) {
  1860. DBGPRINTEXC("GetStatistics");
  1861. //
  1862. // log a message
  1863. //
  1864. }
  1865. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1866. GetConfig(pResultsA, fNew, FALSE);
  1867. return(WINSINTF_SUCCESS);
  1868. } // GetStatistics
  1869. DWORD
  1870. WinsDoStaticInit(
  1871. LPWSTR pDataFilePath,
  1872. DWORD fDel
  1873. )
  1874. /*++
  1875. Routine Description:
  1876. This function does the STATIC initialization of WINS
  1877. Arguments:
  1878. pDataFilePath - Path to the data file or NULL
  1879. Externals Used:
  1880. None
  1881. Return Value:
  1882. Success status codes -- WINSINTF_SUCCESS
  1883. Error status codes -- WINSINTF_FAILURE
  1884. Error Handling:
  1885. Called by:
  1886. R_WinsDoStaticInit
  1887. Side Effects:
  1888. Comments:
  1889. None
  1890. --*/
  1891. {
  1892. WINSCNF_CNF_T WinsCnf;
  1893. STATUS RetStat = WINS_SUCCESS;
  1894. //
  1895. // If no path has been specified, take the values from the registry
  1896. //
  1897. if (pDataFilePath == NULL)
  1898. {
  1899. //
  1900. // Read the DataFiles info information
  1901. //
  1902. // This function will return with either the name of the default
  1903. // file to read or one or more files specified under the
  1904. // Parameters\Datafiles key of WINS
  1905. //
  1906. (VOID)WinsCnfGetNamesOfDataFiles(&WinsCnf);
  1907. }
  1908. else
  1909. {
  1910. FUTURES("expensive. Change idl prototype to pass length")
  1911. if (lstrlen(pDataFilePath) >= WINS_MAX_FILENAME_SZ)
  1912. {
  1913. return(WINSINTF_STATIC_INIT_FAILED);
  1914. }
  1915. //
  1916. // Set time of data initialization
  1917. //
  1918. WinsIntfSetTime(NULL, WINSINTF_E_INIT_DB);
  1919. WinsMscAlloc(WINSCNF_FILE_INFO_SZ, &WinsCnf.pStaticDataFile);
  1920. lstrcpy(WinsCnf.pStaticDataFile->FileNm, pDataFilePath);
  1921. WinsCnf.pStaticDataFile->StrType = REG_EXPAND_SZ;
  1922. WinsCnf.NoOfDataFiles = 1;
  1923. }
  1924. //
  1925. // If Static initialization fails, it will be logged.
  1926. // This function does not return an error code
  1927. //
  1928. if ((RetStat = WinsPrsDoStaticInit(
  1929. WinsCnf.pStaticDataFile,
  1930. WinsCnf.NoOfDataFiles,
  1931. FALSE //do it synchronously
  1932. )) == WINS_SUCCESS)
  1933. {
  1934. if ((pDataFilePath != NULL) && fDel)
  1935. {
  1936. if (!DeleteFile(pDataFilePath))
  1937. {
  1938. DWORD Error;
  1939. Error = GetLastError();
  1940. if (Error != ERROR_FILE_NOT_FOUND)
  1941. {
  1942. DBGPRINT1(ERR, "DbgOpenFile: Could not delete the data file. Error = (%d). Dbg file will not be truncated\n", Error);
  1943. WinsEvtLogDetEvt(FALSE, WINS_EVT_COULD_NOT_DELETE_FILE,
  1944. TEXT("winsintf.c"), __LINE__, "ud", pDataFilePath, Error);
  1945. RetStat = Error;
  1946. }
  1947. }
  1948. }
  1949. }
  1950. return (RetStat == WINS_SUCCESS ? WINSINTF_SUCCESS : WINSINTF_STATIC_INIT_FAILED);
  1951. }
  1952. DWORD
  1953. WinsDoScavenging(
  1954. VOID
  1955. )
  1956. /*++
  1957. Routine Description:
  1958. This function starts the scavenging cycle
  1959. Arguments:
  1960. None
  1961. Externals Used:
  1962. None
  1963. Return Value:
  1964. Success status codes -- WINSINTF_SUCCESS
  1965. Error status codes -- exception from WinsMscSignalHdl
  1966. Error Handling:
  1967. Called by:
  1968. R_WinsDoScavenging
  1969. Side Effects:
  1970. Comments:
  1971. None
  1972. --*/
  1973. {
  1974. PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
  1975. pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
  1976. pWrkItm->Opcode_e = WINSINTF_E_SCV_GENERAL;
  1977. pWrkItm->CmdTyp_e = QUE_E_CMD_SCV_ADMIN;
  1978. pWrkItm->fForce = 0;
  1979. pWrkItm->Age = 1; //should not be zero since zero implies
  1980. //consistency check on all replicas.
  1981. WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
  1982. QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
  1983. return (WINSINTF_SUCCESS);
  1984. }
  1985. DWORD
  1986. WinsDoScavengingNew(
  1987. PWINSINTF_SCV_REQ_T pScvReq
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. This function starts the scavenging cycle
  1992. Arguments:
  1993. None
  1994. Externals Used:
  1995. None
  1996. Return Value:
  1997. Success status codes -- WINSINTF_SUCCESS
  1998. Error status codes -- exception from WinsMscSignalHdl
  1999. Error Handling:
  2000. Called by:
  2001. R_WinsDoScavenging
  2002. Side Effects:
  2003. Comments:
  2004. None
  2005. --*/
  2006. {
  2007. PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
  2008. pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
  2009. pWrkItm->Opcode_e = pScvReq->Opcode_e;
  2010. pWrkItm->Age = pScvReq->Age;
  2011. pWrkItm->fForce = pScvReq->fForce;
  2012. if (WINSINTF_E_SCV_GENERAL == pWrkItm->Opcode_e ) {
  2013. WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
  2014. } else {
  2015. WinsLogAdminEvent( WINS_EVT_ADMIN_CCCHECK_INITIATED, 0);
  2016. }
  2017. QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
  2018. return (WINSINTF_SUCCESS);
  2019. }
  2020. DWORD
  2021. WinsGetDbRecs (
  2022. PWINSINTF_ADD_T pWinsAdd,
  2023. WINSINTF_VERS_NO_T MinVersNo,
  2024. WINSINTF_VERS_NO_T MaxVersNo,
  2025. PWINSINTF_RECS_T pRecs
  2026. )
  2027. /*++
  2028. Routine Description:
  2029. This function returns with all the records (that can fit into the
  2030. buffer passed) owned by a WINS in the local db of this WINS.
  2031. Arguments:
  2032. Externals Used:
  2033. None
  2034. Return Value:
  2035. Success status codes --
  2036. Error status codes --
  2037. Error Handling:
  2038. Called by:
  2039. Side Effects:
  2040. Comments:
  2041. None
  2042. --*/
  2043. {
  2044. COMM_ADD_T Address;
  2045. PRPL_REC_ENTRY_T pBuff = NULL;
  2046. LPVOID pStartBuff;
  2047. DWORD BuffLen;
  2048. DWORD NoOfRecs;
  2049. PWINSINTF_RECORD_ACTION_T pRow;
  2050. DWORD i;
  2051. DWORD ind;
  2052. //VERS_NO_T MinVersNo = {0,0};
  2053. DWORD EntType;
  2054. PWINSTHD_TLS_T pTls;
  2055. //ULONG Status;
  2056. BOOL fExcRaised = FALSE;
  2057. // PVOID pCallersAdd, pCallersCaller;
  2058. // RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
  2059. DBGENTER("WinsGetDbRecs\n");
  2060. if (LiLtr(MaxVersNo, MinVersNo))
  2061. {
  2062. return(WINSINTF_FAILURE);
  2063. }
  2064. Address.AddTyp_e = pWinsAdd->Type;
  2065. Address.AddLen = pWinsAdd->Len;
  2066. //
  2067. // snmp agent can pass a 0 for the address to ask for all records
  2068. // owned by the local wins.
  2069. //
  2070. if (pWinsAdd->IPAdd == 0)
  2071. {
  2072. Address.AddTyp_e = NmsLocalAdd.AddTyp_e;
  2073. Address.AddLen = NmsLocalAdd.AddLen;
  2074. Address.Add.IPAdd = NmsLocalAdd.Add.IPAdd;
  2075. }
  2076. else
  2077. {
  2078. Address.AddTyp_e = pWinsAdd->Type;
  2079. Address.AddLen = pWinsAdd->Len;
  2080. Address.Add.IPAdd = pWinsAdd->IPAdd;
  2081. }
  2082. //
  2083. // initialize this thread with the db engine
  2084. //
  2085. NmsDbThdInit(WINS_E_WINSRPC);
  2086. NmsDbOpenTables(WINS_E_WINSRPC);
  2087. DBGMYNAME("RPC-WinsGetDbRecs");
  2088. PERF("The caller can pass the number of records for which space has been")
  2089. PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
  2090. PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
  2091. PERF("more records than are necessary")
  2092. GET_TLS_M(pTls);
  2093. try {
  2094. NmsDbGetDataRecs(
  2095. WINS_E_WINSRPC,
  2096. 0, //not used
  2097. MinVersNo,
  2098. MaxVersNo,
  2099. 0, //not used
  2100. LiEqlZero(MinVersNo) && LiEqlZero(MaxVersNo) ? TRUE : FALSE,
  2101. FALSE, //not used
  2102. NULL, //must be NULL since we are not doing
  2103. //scavenging of clutter
  2104. &Address,
  2105. FALSE, //dynamic + static records are wanted
  2106. //#if RPL_TYPE
  2107. WINSCNF_RPL_DEFAULT_TYPE,
  2108. //#endif
  2109. &pBuff,
  2110. &BuffLen,
  2111. &NoOfRecs
  2112. );
  2113. i = 0;
  2114. pStartBuff = pBuff;
  2115. //
  2116. // If there are records to send back and the client has specified
  2117. // a buffer for them, insert the records
  2118. //
  2119. if (NoOfRecs > 0)
  2120. {
  2121. //
  2122. // Allocate memory for the no of records
  2123. //
  2124. pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
  2125. //
  2126. // If memory can not be allocate, an exception will be returned
  2127. // by midl_user_alloc
  2128. //
  2129. pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
  2130. // DBGPRINT1(DET, "WinsGetDbRecs: Address of memory for records is (%d)\n", pRecs->pRow);
  2131. #if 0
  2132. pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
  2133. if (Status != RPC_S_OK)
  2134. {
  2135. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2136. }
  2137. #endif
  2138. pRow = pRecs->pRow;
  2139. for (; i<NoOfRecs; i++)
  2140. {
  2141. //
  2142. // Initialize so that we don't get "enum wrong" error.
  2143. //
  2144. pRow->Cmd_e = WINSINTF_E_QUERY;
  2145. //
  2146. // the name retrieved has NULL as the last character. This
  2147. // We need to pass a name without this NULL.
  2148. //
  2149. pRow->NameLen = pBuff->NameLen;
  2150. if (*pBuff->pName == 0x1B)
  2151. {
  2152. WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
  2153. }
  2154. pRow->pName = midl_user_allocate(pRow->NameLen + 1);
  2155. //DBGPRINT2(DET, "WinsGetDbRecs: Address of name = (%s) is (%d) \n", pBuff->pName, pRow->pName);
  2156. #if 0
  2157. pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
  2158. if (Status != RPC_S_OK)
  2159. {
  2160. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2161. }
  2162. #endif
  2163. WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,
  2164. pRow->NameLen);
  2165. WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
  2166. EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
  2167. pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
  2168. ? WINSINTF_E_UNIQUE :
  2169. (NMSDB_ENTRY_NORM_GRP_M(EntType) ?
  2170. WINSINTF_E_NORM_GROUP :
  2171. (NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
  2172. WINSINTF_E_SPEC_GROUP :
  2173. WINSINTF_E_MULTIHOMED));
  2174. if (
  2175. (pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
  2176. (pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
  2177. )
  2178. {
  2179. PWINSINTF_ADD_T pAdd;
  2180. DWORD No;
  2181. if (pBuff->NoOfAdds > 0)
  2182. {
  2183. pRow->NoOfAdds = pBuff->NoOfAdds * 2;
  2184. //
  2185. // Each member is comprised of two addresses,
  2186. // first address is that of the owner WINS, second
  2187. // address is that of the node registered
  2188. //
  2189. pRow->pAdd =
  2190. // RpcSmAllocate(
  2191. midl_user_allocate(
  2192. (unsigned int)(pRow->NoOfAdds)
  2193. *
  2194. sizeof(WINSINTF_ADD_T)//,
  2195. // &Status
  2196. );
  2197. //DBGPRINT2(DET, "WinsGetDbRecs: Address of ip address for name = (%s) is (%d) \n", pRow->pName, pRow->pAdd);
  2198. #if 0
  2199. if (Status != RPC_S_OK)
  2200. {
  2201. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2202. }
  2203. #endif
  2204. for (
  2205. No= 0, ind= 0, pAdd = pRow->pAdd;
  2206. No < (pRow->NoOfAdds/2);
  2207. No++
  2208. )
  2209. {
  2210. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
  2211. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  2212. pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
  2213. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
  2214. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  2215. pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
  2216. }
  2217. WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
  2218. }
  2219. }
  2220. else
  2221. {
  2222. pRow->NoOfAdds = 0;
  2223. pRow->pAdd = NULL;
  2224. pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
  2225. pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
  2226. pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
  2227. }
  2228. pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
  2229. pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
  2230. pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
  2231. pRow->VersNo = pBuff->VersNo;
  2232. pRow->TimeStamp = pBuff->TimeStamp;
  2233. pRow++;
  2234. pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
  2235. PERF("Do the addition above the for loop and store in a var. Use var. here")
  2236. } // end of for loop
  2237. } //end of if block
  2238. else
  2239. {
  2240. pRecs->pRow = NULL;
  2241. }
  2242. } // end of try
  2243. except(EXCEPTION_EXECUTE_HANDLER) {
  2244. DBGPRINTEXC("WinsGetDbRecs");
  2245. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  2246. fExcRaised = TRUE;
  2247. }
  2248. pRecs->TotalNoOfRecs = NoOfRecs;
  2249. //
  2250. // Deallocate the buffer allocated by NmsDbGetDataRecs
  2251. //
  2252. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  2253. WinsMscHeapDestroy(pTls->HeapHdl);
  2254. if (!fExcRaised)
  2255. {
  2256. pRecs->NoOfRecs = i;
  2257. }
  2258. else
  2259. {
  2260. // RpcSmFree(pRecs->pRow);
  2261. midl_user_free(pRecs->pRow);
  2262. pRecs->NoOfRecs = 0;
  2263. }
  2264. //
  2265. // Let us end the session
  2266. //
  2267. NmsDbCloseTables();
  2268. NmsDbEndSession();
  2269. DBGLEAVE("WinsGetDbRecs\n");
  2270. return (WINSINTF_SUCCESS);
  2271. }
  2272. VOID
  2273. WinsIntfSetTime(
  2274. OUT PSYSTEMTIME pTime,
  2275. IN WINSINTF_TIME_TYPE_E TimeType_e
  2276. )
  2277. /*++
  2278. Routine Description:
  2279. This function is called to set the the time in the WINSINTF_STAT_T
  2280. structure
  2281. Arguments:
  2282. pTime - Local Time (returned)
  2283. TimeType_e - The activity for which the time has to be stored
  2284. Externals Used:
  2285. None
  2286. Return Value:
  2287. NONE
  2288. Error Handling:
  2289. Called by:
  2290. Side Effects:
  2291. Comments:
  2292. None
  2293. --*/
  2294. {
  2295. SYSTEMTIME SysTime;
  2296. PSYSTEMTIME pSysTime = &SysTime;
  2297. GetSystemTime(pSysTime);
  2298. EnterCriticalSection(&WinsIntfCrtSec);
  2299. switch(TimeType_e)
  2300. {
  2301. case(WINSINTF_E_WINS_START):
  2302. WinsIntfStat.TimeStamps.WinsStartTime = *pSysTime;
  2303. break;
  2304. case(WINSINTF_E_PLANNED_SCV):
  2305. WinsIntfStat.TimeStamps.LastPScvTime = *pSysTime;
  2306. break;
  2307. case(WINSINTF_E_ADMIN_TRIG_SCV):
  2308. WinsIntfStat.TimeStamps.LastATScvTime = *pSysTime;
  2309. break;
  2310. case(WINSINTF_E_TOMBSTONES_SCV):
  2311. WinsIntfStat.TimeStamps.LastTombScvTime = *pSysTime;
  2312. break;
  2313. case(WINSINTF_E_VERIFY_SCV):
  2314. WinsIntfStat.TimeStamps.LastVerifyScvTime = *pSysTime;
  2315. break;
  2316. case(WINSINTF_E_INIT_DB):
  2317. WinsIntfStat.TimeStamps.LastInitDbTime = *pSysTime;
  2318. break;
  2319. case(WINSINTF_E_PLANNED_PULL):
  2320. WinsIntfStat.TimeStamps.LastPRplTime = *pSysTime;
  2321. break;
  2322. case(WINSINTF_E_ADMIN_TRIG_PULL):
  2323. WinsIntfStat.TimeStamps.LastATRplTime = *pSysTime;
  2324. break;
  2325. case(WINSINTF_E_NTWRK_TRIG_PULL):
  2326. WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
  2327. break;
  2328. case(WINSINTF_E_UPDCNT_TRIG_PULL):
  2329. WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
  2330. break;
  2331. case(WINSINTF_E_ADDCHG_TRIG_PULL):
  2332. WinsIntfStat.TimeStamps.LastACTRplTime = *pSysTime;
  2333. break;
  2334. case(WINSINTF_E_COUNTER_RESET):
  2335. WinsIntfStat.TimeStamps.CounterResetTime = *pSysTime;
  2336. break;
  2337. default:
  2338. DBGPRINT1(EXC, "WinsIntfSetTime: Weird Timestamp type = (%d)\n", TimeType_e);
  2339. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  2340. break;
  2341. }
  2342. LeaveCriticalSection(&WinsIntfCrtSec);
  2343. if (pTime)
  2344. {
  2345. TIME_ZONE_INFORMATION tzInfo;
  2346. GetTimeZoneInformation(&tzInfo);
  2347. SystemTimeToTzSpecificLocalTime(&tzInfo, pSysTime, pTime);
  2348. }
  2349. return;
  2350. }
  2351. DWORD
  2352. WinsDelDbRecs(
  2353. IN PWINSINTF_ADD_T pAdd,
  2354. IN WINSINTF_VERS_NO_T MinVersNo,
  2355. IN WINSINTF_VERS_NO_T MaxVersNo
  2356. )
  2357. /*++
  2358. Routine Description:
  2359. This func. deletes a specified range of records belonging to a
  2360. particular owner
  2361. Arguments:
  2362. Externals Used:
  2363. None
  2364. Return Value:
  2365. Success status codes -- WINSINTF_SUCCESS
  2366. Error status codes -- WINSINTF_FAILURE
  2367. Error Handling:
  2368. Called by:
  2369. R_WinsDelDbRecs
  2370. Side Effects:
  2371. Comments:
  2372. None
  2373. --*/
  2374. {
  2375. COMM_ADD_T Address;
  2376. DWORD RetVal = WINSINTF_SUCCESS;
  2377. DWORD dwOwnerId;
  2378. BOOL fAllocNew = FALSE;
  2379. Address.AddTyp_e = pAdd->Type;
  2380. Address.AddLen = pAdd->Len;
  2381. Address.Add.IPAdd = pAdd->IPAdd;
  2382. //
  2383. // initialize this thread with the db engine
  2384. //
  2385. NmsDbThdInit(WINS_E_WINSRPC);
  2386. NmsDbOpenTables(WINS_E_WINSRPC);
  2387. DBGMYNAME("RPC-WinsDelDbRecs");
  2388. if (RplFindOwnerId(
  2389. &Address,
  2390. &fAllocNew, //do not allocate an entry if not
  2391. //present
  2392. &dwOwnerId,
  2393. WINSCNF_E_IGNORE_PREC,
  2394. WINSCNF_LOW_PREC
  2395. ) != WINS_SUCCESS)
  2396. {
  2397. DBGPRINT0(DET, "WinsDelDataRecs: WINS is not in the owner-add mapping table\n");
  2398. RetVal = WINSINTF_FAILURE;
  2399. }
  2400. else
  2401. {
  2402. if (NmsDbDelDataRecs(
  2403. dwOwnerId,
  2404. MinVersNo,
  2405. MaxVersNo,
  2406. TRUE, //enter critical section
  2407. FALSE //no fragmented deletion
  2408. ) != WINS_SUCCESS)
  2409. {
  2410. RetVal = WINSINTF_FAILURE;
  2411. }
  2412. }
  2413. //
  2414. // Let us end the session
  2415. //
  2416. NmsDbCloseTables();
  2417. NmsDbEndSession();
  2418. return(RetVal);
  2419. }
  2420. DWORD
  2421. WinsTombstoneDbRecs(
  2422. IN PWINSINTF_ADD_T pAdd,
  2423. IN WINSINTF_VERS_NO_T MinVersNo,
  2424. IN WINSINTF_VERS_NO_T MaxVersNo
  2425. )
  2426. /*++
  2427. Routine Description:
  2428. This func. tombstones a specified range of records belonging to a
  2429. particular owner
  2430. Arguments:
  2431. Externals Used:
  2432. None
  2433. Return Value:
  2434. Success status codes -- WINSINTF_SUCCESS
  2435. Error status codes -- WINSINTF_FAILURE
  2436. Error Handling:
  2437. Called by:
  2438. R_WinsTombstoneDbRecs
  2439. Side Effects:
  2440. Comments:
  2441. None
  2442. --*/
  2443. {
  2444. DWORD RetVal = WINSINTF_SUCCESS;
  2445. COMM_ADD_T Address;
  2446. DWORD dwOwnerId;
  2447. BOOL fAllocNew = FALSE;
  2448. Address.AddTyp_e = pAdd->Type;
  2449. Address.AddLen = pAdd->Len;
  2450. Address.Add.IPAdd = pAdd->IPAdd;
  2451. //
  2452. // initialize this thread with the db engine
  2453. //
  2454. NmsDbThdInit(WINS_E_WINSRPC);
  2455. NmsDbOpenTables(WINS_E_WINSRPC);
  2456. DBGMYNAME("RPC-WinsTombstoneDbRecs");
  2457. if (RplFindOwnerId(
  2458. &Address,
  2459. &fAllocNew, //do not allocate an entry if not
  2460. //present
  2461. &dwOwnerId,
  2462. WINSCNF_E_IGNORE_PREC,
  2463. WINSCNF_LOW_PREC
  2464. ) != WINS_SUCCESS)
  2465. {
  2466. DBGPRINT0(DET, "WinsTombstoneDataRecs: WINS is not in the owner-add mapping table\n");
  2467. RetVal = WINSINTF_FAILURE;
  2468. }else if(NmsDbTombstoneDataRecs(
  2469. dwOwnerId,
  2470. MinVersNo,
  2471. MaxVersNo
  2472. ) != WINS_SUCCESS)
  2473. {
  2474. RetVal = WINSINTF_FAILURE;
  2475. }
  2476. // Let us end the session
  2477. NmsDbCloseTables();
  2478. NmsDbEndSession();
  2479. return(RetVal);
  2480. }
  2481. DWORD
  2482. WinsPullRange(
  2483. IN PWINSINTF_ADD_T pWinsAdd,
  2484. IN PWINSINTF_ADD_T pOwnerAdd,
  2485. IN WINSINTF_VERS_NO_T MinVersNo,
  2486. IN WINSINTF_VERS_NO_T MaxVersNo
  2487. )
  2488. /*++
  2489. Routine Description:
  2490. This function is called to pull a range of records owned by a particular
  2491. WINS server from another WINS server.
  2492. Arguments:
  2493. Externals Used:
  2494. None
  2495. Return Value:
  2496. Success status codes --
  2497. Error status codes --
  2498. Error Handling:
  2499. Called by:
  2500. Side Effects:
  2501. Comments:
  2502. None
  2503. --*/
  2504. {
  2505. PWINSINTF_PULL_RANGE_INFO_T pPullRangeInfo;
  2506. PRPL_CONFIG_REC_T pPnr;
  2507. BOOL fRplPnr = FALSE;
  2508. DWORD RetCode = WINSINTF_SUCCESS;
  2509. //
  2510. // if the minimum version number is > than the max version number
  2511. // return a failure code
  2512. //
  2513. if (LiGtr(MinVersNo, MaxVersNo))
  2514. {
  2515. return(WINSINTF_FAILURE);
  2516. }
  2517. //
  2518. // Enter the critical sections guarded by WinsCnfCnfCrtSec and
  2519. // NmsNmhNamRegCrtSec. There is no danger of deadlock because we
  2520. // always enter the two critical sections in the following sequence
  2521. //
  2522. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2523. PERF("Do we need to enter the following critical section")
  2524. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  2525. try {
  2526. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  2527. //
  2528. // If we are allowed to pull only from configured partners,
  2529. // let us try to find the config record of the partner
  2530. //
  2531. if (WinsCnf.fRplOnlyWCnfPnrs)
  2532. {
  2533. if (pPnr != NULL)
  2534. {
  2535. //
  2536. // Search for the Cnf record for the WINS we want to
  2537. // send the PULL RANGE request to.
  2538. //
  2539. for (
  2540. ;
  2541. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  2542. &&
  2543. !fRplPnr;
  2544. // no third expression
  2545. )
  2546. {
  2547. //
  2548. // Check if this is the one we want
  2549. //
  2550. if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->IPAdd)
  2551. {
  2552. //
  2553. // We are done. Set the fRplPnr flag to TRUE so that
  2554. // we break out of the loop.
  2555. //
  2556. fRplPnr = TRUE;
  2557. //
  2558. // Make it 0, so that we always try to establish
  2559. // a connection. Otherwise, pull thread may not
  2560. // try if it has already exhausted the number of
  2561. // retries
  2562. //
  2563. pPnr->RetryCount = 0;
  2564. continue; //so that we can break out
  2565. }
  2566. //
  2567. // Get the next record that follows this one sequentially
  2568. //
  2569. pPnr = WinsCnfGetNextRplCnfRec(
  2570. pPnr,
  2571. RPL_E_IN_SEQ //seq. traversal
  2572. );
  2573. } // end of for
  2574. } // end of if (pPnr != 0)
  2575. } // end of if (fRplOnlyWCnfPnrs)
  2576. else
  2577. {
  2578. pPnr = WinsMscHeapAlloc( NmsRpcHeapHdl, RPL_CONFIG_REC_SIZE);
  2579. COMM_INIT_ADD_M(&pPnr->WinsAdd, pWinsAdd->IPAdd);
  2580. pPnr->MagicNo = 0;
  2581. pPnr->RetryCount = 0;
  2582. pPnr->LastCommFailTime = 0;
  2583. pPnr->PushNtfTries = 0;
  2584. fRplPnr = TRUE;
  2585. //
  2586. // We want the buffer to be deallocated by the PULL thread
  2587. //
  2588. pPnr->fTemp = TRUE;
  2589. //#if RPL_TYPE
  2590. //
  2591. // We need to pull according to the RplType for the pull pnrs
  2592. //
  2593. pPnr->RplType = WinsCnf.PullInfo.RplType;
  2594. //#endif
  2595. }
  2596. if (fRplPnr)
  2597. {
  2598. pPullRangeInfo = WinsMscHeapAlloc(
  2599. NmsRpcHeapHdl,
  2600. sizeof(WINSINTF_PULL_RANGE_INFO_T)
  2601. );
  2602. #if 0
  2603. WinsMscAlloc(sizeof(WINSINTF_PULL_RANGE_INFO_T),
  2604. &pPullRangeInfo);
  2605. #endif
  2606. pPullRangeInfo->pPnr = pPnr;
  2607. pPullRangeInfo->OwnAdd = *pOwnerAdd;
  2608. pPullRangeInfo->MinVersNo = MinVersNo;
  2609. pPullRangeInfo->MaxVersNo = MaxVersNo;
  2610. //
  2611. // Call RplInsertQue to insert the push request to
  2612. // the Pull Thread
  2613. //
  2614. ERplInsertQue(
  2615. WINS_E_WINSRPC,
  2616. QUE_E_CMD_PULL_RANGE,
  2617. NULL, //no Dlg Hdl
  2618. NULL, //no msg is there
  2619. 0, //msg length
  2620. pPullRangeInfo, //client context
  2621. pPnr->MagicNo
  2622. );
  2623. }
  2624. }
  2625. except (EXCEPTION_EXECUTE_HANDLER) {
  2626. DBGPRINTEXC("WinsPullRange");
  2627. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_PUSH_TRIGGER_EXC);
  2628. RetCode = WINSINTF_FAILURE;
  2629. }
  2630. //
  2631. // Leave the critical section guarded by NmsNmhNamRegCrtSec.
  2632. //
  2633. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  2634. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2635. //
  2636. // if replication was allowed only with configured partners and
  2637. // there was no WINS with the address specified by the client,
  2638. // return failure
  2639. //
  2640. if (!fRplPnr)
  2641. {
  2642. RetCode = WINSINTF_FAILURE;
  2643. }
  2644. return(RetCode);
  2645. }
  2646. DWORD
  2647. WinsSetPriorityClass(
  2648. IN WINSINTF_PRIORITY_CLASS_E PriorityClass_e
  2649. )
  2650. /*++
  2651. Routine Description:
  2652. This function sets the priority class of the Wins process.
  2653. Arguments:
  2654. PriorityClass -- Priority Class of the WINS process
  2655. Externals Used:
  2656. WinsCnf
  2657. Return Value:
  2658. Success status codes --
  2659. Error status codes --
  2660. Error Handling:
  2661. Called by:
  2662. Side Effects:
  2663. Comments:
  2664. None
  2665. --*/
  2666. {
  2667. //DWORD OldPrCls;
  2668. DWORD NewPrCls;
  2669. HANDLE ProcHdl;
  2670. DWORD RetVal = WINSINTF_SUCCESS;
  2671. switch(PriorityClass_e)
  2672. {
  2673. case(WINSINTF_E_NORMAL):
  2674. NewPrCls = NORMAL_PRIORITY_CLASS;
  2675. break;
  2676. case(WINSINTF_E_HIGH):
  2677. NewPrCls = HIGH_PRIORITY_CLASS;
  2678. break;
  2679. default:
  2680. DBGPRINT0(DET, "WinsSetPriorityClass: Invalid Priority Class\n");
  2681. return(WINSINTF_FAILURE);
  2682. break;
  2683. }
  2684. ProcHdl = GetCurrentProcess();
  2685. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2686. #if 0
  2687. try {
  2688. FUTURES("Use a WinsMsc functions here for consistency")
  2689. if ((OldPrCls = GetPriorityClass(ProcHdl)) == 0)
  2690. {
  2691. DBGPRINT1(ERR, "WinsSetPriorityClass: Can not Proc Priority. Error = (%d)\n", GetLastError());
  2692. RetVal = WINSINTF_FAILURE;
  2693. }
  2694. else
  2695. {
  2696. if (OldPrCls == NewPrCls)
  2697. {
  2698. DBGPRINT1(ERR, "WinsSetPriorityClass: Process already has this Priority Class = (%d)\n", NewPrCls);
  2699. }
  2700. else
  2701. {
  2702. #endif
  2703. if (SetPriorityClass(ProcHdl, NewPrCls) == FALSE)
  2704. {
  2705. DBGPRINT1(ERR, "WinsSetPriorityClass: SetPriorityClass() Failed. Error = (%d)\n", GetLastError());
  2706. }
  2707. else
  2708. {
  2709. WinsCnf.WinsPriorityClass = (DWORD)PriorityClass_e;
  2710. }
  2711. #if 0
  2712. }
  2713. }
  2714. }
  2715. except(EXCEPTION_EXECUTE_HANDLER) {
  2716. DBGPRINTEXC("WinsSetPriorityCls");
  2717. }
  2718. #endif
  2719. //
  2720. // ProcHdl is a pseudo-handle and does not need to be closed
  2721. //
  2722. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2723. return(WINSINTF_SUCCESS);
  2724. }
  2725. DWORD
  2726. WinsResetCounters(
  2727. VOID
  2728. )
  2729. /*++
  2730. Routine Description:
  2731. This function resets/clears the counters
  2732. Arguments:
  2733. None
  2734. Externals Used:
  2735. NmsNmhNamRegCrtSec
  2736. Return Value:
  2737. Success status codes --
  2738. Error status codes --
  2739. Error Handling:
  2740. Called by:
  2741. R_WinsResetCounters
  2742. Side Effects:
  2743. Comments:
  2744. None
  2745. --*/
  2746. {
  2747. DWORD i;
  2748. PRPL_CONFIG_REC_T pPnr;
  2749. //
  2750. // Copy the counters
  2751. //
  2752. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  2753. (VOID)RtlFillMemory(&WinsIntfStat.Counters, sizeof(WinsIntfStat.Counters), 0);
  2754. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  2755. // now clear the per partner info.
  2756. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2757. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  2758. for (i = 0; (i<WinsCnf.PullInfo.NoOfPushPnrs) && (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE) ; i++) {
  2759. pPnr->NoOfRpls = 0;
  2760. pPnr->NoOfCommFails = 0;
  2761. pPnr = WinsCnfGetNextRplCnfRec(pPnr,RPL_E_IN_SEQ);
  2762. }
  2763. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2764. //
  2765. // Even if we have multiple threads doing resets (unlikely occurence),
  2766. // the window between the above critical section and the one entered
  2767. // by the following function does not cause any problem.
  2768. //
  2769. WinsIntfSetTime(NULL, WINSINTF_E_COUNTER_RESET);
  2770. return(WINSINTF_SUCCESS);
  2771. }
  2772. DWORD
  2773. WinsWorkerThdUpd(
  2774. DWORD NewNoOfNbtThds
  2775. )
  2776. /*++
  2777. Routine Description:
  2778. This function is called to change the count of the NBT threads in
  2779. the WINS process.
  2780. Arguments:
  2781. NewNoOfNbtThds - The new count of the Nbt threads
  2782. Externals Used:
  2783. None
  2784. Return Value:
  2785. Success status codes -- WINSINTF_SUCCESS
  2786. Error status codes -- WINSINTF_FAILURE
  2787. Error Handling:
  2788. Called by:
  2789. Side Effects:
  2790. Comments:
  2791. None
  2792. --*/
  2793. {
  2794. //
  2795. // If the WINS server is not in steady state or if the new count
  2796. // of Nbt threads requested is outside the allowed range, return
  2797. // failure
  2798. //
  2799. CHECK("Somehow, if the number of threads is equal to the max. number allowed")
  2800. CHECK("pTls comes out as NULL for all NBT threads (seen at termination)")
  2801. if (
  2802. ((WinsCnf.State_e != WINSCNF_E_RUNNING)
  2803. &&
  2804. (WinsCnf.State_e != WINSCNF_E_PAUSED))
  2805. ||
  2806. (NewNoOfNbtThds >= WINSTHD_MAX_NO_NBT_THDS)
  2807. ||
  2808. (NewNoOfNbtThds < WINSTHD_MIN_NO_NBT_THDS)
  2809. )
  2810. {
  2811. return(WINSINTF_FAILURE);
  2812. }
  2813. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2814. WinsIntfNoOfNbtThds = NewNoOfNbtThds;
  2815. try {
  2816. //
  2817. // If the new count is more than the existing count, store the new
  2818. // count in a global and signal an Nbt thread. The signaled
  2819. // Nbt thread will create all the extra threads needed
  2820. //
  2821. if (NewNoOfNbtThds > NmsNoOfNbtThds)
  2822. {
  2823. WinsMscSignalHdl(NmsCrDelNbtThdEvt);
  2824. }
  2825. else
  2826. {
  2827. //
  2828. // if the new count is same as the existing count, return
  2829. // success
  2830. //
  2831. if (NewNoOfNbtThds == NmsNoOfNbtThds)
  2832. {
  2833. DBGPRINT1(FLOW, "WinsWorkerThdUpd: Wins server already has %d threads\n", NewNoOfNbtThds);
  2834. }
  2835. else // NewNoOfNbtThds < NmsNoOfNbtThds
  2836. {
  2837. //
  2838. // Signal a thread to delete self. The signaled thread will
  2839. // signal the event again if more than one thread has to be
  2840. // deleted
  2841. //
  2842. WinsMscSignalHdl(NmsCrDelNbtThdEvt);
  2843. }
  2844. }
  2845. }
  2846. except (EXCEPTION_EXECUTE_HANDLER) {
  2847. DBGPRINTEXC("WinsWorkerThdUpd");
  2848. }
  2849. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2850. return(WINSINTF_SUCCESS);
  2851. }
  2852. DWORD
  2853. WinsGetNameAndAdd(
  2854. PWINSINTF_ADD_T pWinsAdd,
  2855. LPBYTE pUncName
  2856. )
  2857. {
  2858. DWORD RetStat = WINSINTF_SUCCESS;
  2859. // TCHAR UncName[MAX_COMPUTERNAME_LENGTH + 1];
  2860. // DWORD LenOfBuff = WINSINTF_MAX_COMPUTERNAME_LENGTH;
  2861. DWORD LenOfBuff = MAX_COMPUTERNAME_LENGTH + 1;
  2862. pWinsAdd->IPAdd = NmsLocalAdd.Add.IPAdd;
  2863. FUTURES("Change this to GetComputerName when winsadmn is made unicode compliant")
  2864. if (GetComputerNameA(pUncName, &LenOfBuff) == FALSE)
  2865. {
  2866. DBGPRINT1(ERR, "WinsGetNameAndAdd: Name error. Error=(%x)\n", GetLastError());
  2867. RetStat = GetLastError();
  2868. }
  2869. return(RetStat);
  2870. }
  2871. #define INITIAL_RAMPUP_NO 3
  2872. DWORD
  2873. WinsGetBrowserNames(
  2874. PWINSINTF_BIND_DATA_T pWinsHdl,
  2875. PWINSINTF_BROWSER_NAMES_T pNames
  2876. )
  2877. {
  2878. DWORD RetVal = WINSINTF_SUCCESS;
  2879. time_t CurrentTime;
  2880. static DWORD sNoOfTimes = 0;
  2881. static time_t sLastTime = 0;
  2882. BOOL fPopCache = FALSE;
  2883. UNREFERENCED_PARAMETER(pWinsHdl);
  2884. //
  2885. // If this the initial ramp up period, populate the cache
  2886. //
  2887. if (sNoOfTimes++ < INITIAL_RAMPUP_NO)
  2888. {
  2889. //
  2890. // if this is the first call, create the dom. cache event.
  2891. //
  2892. if (sNoOfTimes == 1)
  2893. {
  2894. WinsMscCreateEvt(L"WinsDomCachEvt", FALSE, &sDomCache.EvtHdl);
  2895. }
  2896. DBGPRINT1(SPEC, "WinsGetBrowserNames: sNoOfTimes = (%d)\n", sNoOfTimes);
  2897. fPopCache = TRUE;
  2898. }
  2899. else
  2900. {
  2901. //
  2902. // Initial ramp up period is past. Populate the cache if 3 mts
  2903. // have expired since it was last populated
  2904. //
  2905. if ((time(&CurrentTime) - sLastTime) > THREE_MTS || sDomCache.bRefresh)
  2906. {
  2907. DBGPRINT0(SPEC, "WinsGetBrowserNames: Pop Cache due to timeout\n");
  2908. sDomCache.bRefresh = FALSE;
  2909. sLastTime = CurrentTime;
  2910. fPopCache = TRUE;
  2911. }
  2912. }
  2913. try {
  2914. //
  2915. // Populate the cache if fPopCache is set or if the number of entries
  2916. // in the current cache are 0
  2917. //
  2918. if (fPopCache || (sDomCache.SzOfBlock == 0))
  2919. {
  2920. //
  2921. // if our cache has some data, deallocate it first.
  2922. //
  2923. // Note: There could be an rpc thread in the rpc code accessing
  2924. // this buffer. I can't free this buffer until it is done.
  2925. //
  2926. if (sDomCache.SzOfBlock > 0)
  2927. {
  2928. DWORD i;
  2929. PWINSINTF_BROWSER_INFO_T pBrInfo = sDomCache.pInfo;
  2930. DWORD NoOfUsers;
  2931. //
  2932. // Wait until all users are done. We won't iterate more than
  2933. //
  2934. // We can iterate a max. of INITIAL_RAMPUP_NO of times and
  2935. // that too only at initial ramp up time. If a thread is
  2936. // waiting on the event, another thread will also wait
  2937. // on it (except during initial rampup time)
  2938. //
  2939. do {
  2940. EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
  2941. NoOfUsers = sDomCache.NoOfUsers;
  2942. LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
  2943. if (NoOfUsers > 0)
  2944. {
  2945. WinsMscWaitInfinite(sDomCache.EvtHdl);
  2946. }
  2947. } while (NoOfUsers > 0);
  2948. //
  2949. // Free all memory allocated for names
  2950. //
  2951. for (i=0; i< sDomCache.EntriesRead; i++, pBrInfo++)
  2952. {
  2953. midl_user_free(pBrInfo->pName);
  2954. }
  2955. //
  2956. // Free the main block
  2957. //
  2958. midl_user_free(sDomCache.pInfo);
  2959. sDomCache.SzOfBlock = 0;
  2960. pNames->EntriesRead = 0;
  2961. pNames->pInfo = NULL;
  2962. }
  2963. NmsDbThdInit(WINS_E_WINSRPC);
  2964. NmsDbOpenTables(WINS_E_WINSRPC);
  2965. DBGMYNAME("RPC-WinsGetBrowserNames");
  2966. //
  2967. // Get all records starting with 1B Names
  2968. //
  2969. RetVal = NmsDbGetNamesWPrefixChar(
  2970. 0x1B,
  2971. &pNames->pInfo,
  2972. &pNames->EntriesRead
  2973. );
  2974. NmsDbCloseTables();
  2975. NmsDbEndSession();
  2976. //
  2977. // Store the info. only if there is something to be stored.
  2978. //
  2979. if (
  2980. (RetVal == WINS_SUCCESS)
  2981. &&
  2982. (pNames->EntriesRead > 0)
  2983. )
  2984. {
  2985. sDomCache.SzOfBlock =
  2986. pNames->EntriesRead * sizeof(WINSINTF_BROWSER_INFO_T);
  2987. // sDomCache.pInfo = midl_user_allocate(sDomCache.SzOfBlock);
  2988. // WINSMSC_COPY_MEMORY_M(sDomCache.pInfo, pNames->pInfo,
  2989. // sDomCache.SzOfBlock);
  2990. sDomCache.pInfo = pNames->pInfo;
  2991. sDomCache.EntriesRead = pNames->EntriesRead;
  2992. }
  2993. else
  2994. {
  2995. //
  2996. // We did not get anything from the db
  2997. //
  2998. sDomCache.SzOfBlock = 0;
  2999. pNames->EntriesRead = 0;
  3000. pNames->pInfo = NULL;
  3001. }
  3002. }
  3003. else
  3004. {
  3005. //
  3006. // Use the cached info.
  3007. //
  3008. //pNames->pInfo = midl_user_allocate(sDomCache.SzOfBlock);
  3009. //WINSMSC_COPY_MEMORY_M(pNames->pInfo, sDomCache.pInfo,
  3010. // sDomCache.SzOfBlock);
  3011. pNames->pInfo = sDomCache.pInfo;
  3012. pNames->EntriesRead = sDomCache.EntriesRead;
  3013. }
  3014. }
  3015. except(EXCEPTION_EXECUTE_HANDLER) {
  3016. DBGPRINTEXC("WinsGetBrowserNames");
  3017. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_BROWSER_NAME_EXC);
  3018. pNames->EntriesRead = 0;
  3019. pNames->pInfo = NULL;
  3020. RetVal = WINSINTF_FAILURE;
  3021. }
  3022. return(RetVal);
  3023. }
  3024. VOID
  3025. R_WinsGetBrowserNames_notify_flag(boolean __MIDL_NotifyFlag
  3026. )
  3027. /*++
  3028. Routine Description:
  3029. Called by rpc to indicate that it is done with the buffer returned by
  3030. WinsGetBrowserNames
  3031. Arguments:
  3032. Externals Used:
  3033. None
  3034. Return Value:
  3035. Success status codes --
  3036. Error status codes --
  3037. Error Handling:
  3038. Called by:
  3039. Side Effects:
  3040. Comments:
  3041. None
  3042. --*/
  3043. {
  3044. //
  3045. // Decrement the user count. If equal to 0, signal the event to let
  3046. // another thread go on.
  3047. //
  3048. EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
  3049. //
  3050. // workaround an rpc bug (18627) where it may call notify without calling
  3051. // R_WinsGetBrowserNames (checkout winsif_s.c)
  3052. //
  3053. if (
  3054. (sDomCache.NoOfUsers > 0) &&
  3055. (--sDomCache.NoOfUsers == 0) &&
  3056. sDomCache.EvtHdl != NULL
  3057. )
  3058. {
  3059. WinsMscSignalHdl(sDomCache.EvtHdl);
  3060. }
  3061. LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
  3062. return;
  3063. }
  3064. DWORD
  3065. WinsDeleteWins(
  3066. PWINSINTF_ADD_T pWinsAdd
  3067. )
  3068. {
  3069. PCOMM_ADD_T pAdd;
  3070. DWORD RetVal = WINSINTF_FAILURE;
  3071. if (pWinsAdd->IPAdd == NmsLocalAdd.Add.IPAdd)
  3072. {
  3073. WINSINTF_VERS_NO_T MinVersNo = {0};
  3074. WINSINTF_VERS_NO_T MaxVersNo = {0};
  3075. RetVal = WinsDelDbRecs(pWinsAdd, MinVersNo, MaxVersNo);
  3076. #if 0
  3077. //
  3078. // We always keep the entry for the local WINS. For any
  3079. //
  3080. DBGPRINT0(ERR, "WinsDeleteWins: Sorry, you can not delete the entry for the local WINS\n");
  3081. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_DELETE_LOCAL_WINS_DISALLOWED);
  3082. RetVal = WINSINTF_CAN_NOT_DEL_LOCAL_WINS;
  3083. #endif
  3084. }
  3085. else
  3086. {
  3087. WCHAR String[WINS_MAX_NAME_SZ];
  3088. struct in_addr InAddr;
  3089. InAddr.s_addr = htonl(pWinsAdd->IPAdd);
  3090. (VOID)WinsMscConvertAsciiStringToUnicode(
  3091. inet_ntoa( InAddr),
  3092. (LPBYTE)String,
  3093. WINS_MAX_NAME_SZ);
  3094. WinsLogAdminEvent(WINS_EVT_ADMIN_DEL_OWNER_INITIATED,1,String);
  3095. //
  3096. // Allocate from the general heap (not from the rpc heap)
  3097. // since this memory will be deallocated by DeleteWins in
  3098. // rplpull.c which I don't want to tie to just rpc work.
  3099. //
  3100. WinsMscAlloc(sizeof(COMM_ADD_T), &pAdd);
  3101. pAdd->AddTyp_e = pWinsAdd->Type;
  3102. pAdd->AddLen = pWinsAdd->Len;
  3103. pAdd->Add.IPAdd = pWinsAdd->IPAdd;
  3104. //
  3105. // Call RplInsertQue to insert the push request to
  3106. // the Pull Thread
  3107. //
  3108. ERplInsertQue(
  3109. WINS_E_WINSRPC,
  3110. QUE_E_CMD_DELETE_WINS,
  3111. NULL, //no Dlg Hdl
  3112. NULL, //no msg is there
  3113. 0, //msg length
  3114. pAdd, //client context,
  3115. 0 //no magic no
  3116. );
  3117. RetVal = WINSINTF_SUCCESS;
  3118. }
  3119. return(RetVal);
  3120. }
  3121. #define MAX_RECS_TO_RETURN 5000
  3122. DWORD
  3123. WinsGetDbRecsByName (
  3124. PWINSINTF_ADD_T pWinsAdd,
  3125. DWORD Location,
  3126. LPBYTE pName,
  3127. DWORD NameLen,
  3128. DWORD NoOfRecsDesired,
  3129. DWORD TypeOfRecs,
  3130. PWINSINTF_RECS_T pRecs
  3131. )
  3132. /*++
  3133. Routine Description:
  3134. This function returns with all the records (that can fit into the
  3135. buffer passed) owned by a WINS in the local db of this WINS.
  3136. Arguments:
  3137. Externals Used:
  3138. None
  3139. Return Value:
  3140. Success status codes --
  3141. Error status codes --
  3142. Error Handling:
  3143. Called by:
  3144. Side Effects:
  3145. Comments:
  3146. None
  3147. --*/
  3148. {
  3149. COMM_ADD_T Address;
  3150. LPVOID pBuff = NULL;
  3151. DWORD BuffLen;
  3152. DWORD NoOfRecs = 0;
  3153. DWORD Status;
  3154. PWINSTHD_TLS_T pTls;
  3155. DBGENTER("WinsGetDbRecsByName\n");
  3156. if ((NoOfRecsDesired == 0) || (NoOfRecsDesired > MAX_RECS_TO_RETURN))
  3157. {
  3158. NoOfRecsDesired = MAX_RECS_TO_RETURN;
  3159. }
  3160. if ((pWinsAdd != NULL) && (pWinsAdd->IPAdd != 0))
  3161. {
  3162. Address.AddTyp_e = pWinsAdd->Type;
  3163. Address.AddLen = pWinsAdd->Len;
  3164. Address.Add.IPAdd = pWinsAdd->IPAdd;
  3165. }
  3166. //
  3167. // initialize this thread with the db engine
  3168. //
  3169. NmsDbThdInit(WINS_E_WINSRPC);
  3170. NmsDbOpenTables(WINS_E_WINSRPC);
  3171. DBGMYNAME("RPC-WinsGetDbRecsByName");
  3172. try {
  3173. if ((pName != NULL) && (NameLen != 0))
  3174. {
  3175. //
  3176. // Terminate name with NULL, just in case user didn't do it.
  3177. //
  3178. *(pName + NameLen) = (BYTE)NULL;
  3179. }
  3180. if ((pName == NULL) && (NameLen > 0))
  3181. {
  3182. NameLen = 0;
  3183. }
  3184. PERF("The caller can pass the number of records for which space has been")
  3185. PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
  3186. PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
  3187. PERF("more records than are necessary")
  3188. Status = NmsDbGetDataRecsByName(
  3189. pName,
  3190. NameLen != 0 ? NameLen + 1 : 0,
  3191. Location,
  3192. NoOfRecsDesired,
  3193. pWinsAdd != NULL ? &Address : NULL,
  3194. TypeOfRecs,
  3195. &pBuff,
  3196. &BuffLen,
  3197. &NoOfRecs
  3198. );
  3199. if (Status == WINS_SUCCESS)
  3200. {
  3201. Status = PackageRecs( pBuff, BuffLen, NoOfRecs, pRecs);
  3202. }
  3203. }
  3204. except(EXCEPTION_EXECUTE_HANDLER) {
  3205. DBGPRINTEXC("WinsGetDbRecsByName");
  3206. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  3207. Status = WINS_FAILURE;
  3208. }
  3209. //
  3210. // Free the buffer and destroy the heap.
  3211. //
  3212. GET_TLS_M(pTls);
  3213. if (pTls->HeapHdl != NULL)
  3214. {
  3215. if (pBuff != NULL)
  3216. {
  3217. WinsMscHeapFree(pTls->HeapHdl, pBuff);
  3218. }
  3219. WinsMscHeapDestroy(pTls->HeapHdl);
  3220. // pTls->HeapHdl = NULL;
  3221. }
  3222. //
  3223. // Let us end the session
  3224. //
  3225. NmsDbCloseTables();
  3226. NmsDbEndSession();
  3227. if (Status != WINS_SUCCESS)
  3228. {
  3229. pRecs->pRow = NULL;
  3230. pRecs->NoOfRecs = 0;
  3231. Status = WINSINTF_FAILURE;
  3232. }
  3233. else
  3234. {
  3235. if (pRecs->NoOfRecs == 0)
  3236. {
  3237. pRecs->pRow = NULL;
  3238. pRecs->NoOfRecs = 0;
  3239. Status = WINSINTF_REC_NOT_FOUND;
  3240. }
  3241. }
  3242. DBGLEAVE("WinsGetDbRecsByName\n");
  3243. return (Status);
  3244. }
  3245. STATUS
  3246. PackageRecs(
  3247. PRPL_REC_ENTRY2_T pBuff,
  3248. DWORD BuffLen,
  3249. DWORD NoOfRecs,
  3250. PWINSINTF_RECS_T pRecs
  3251. )
  3252. /*++
  3253. Routine Description:
  3254. Arguments:
  3255. Externals Used:
  3256. None
  3257. Return Value:
  3258. Success status codes --
  3259. Error status codes --
  3260. Error Handling:
  3261. Called by:
  3262. Side Effects:
  3263. Comments:
  3264. None
  3265. --*/
  3266. {
  3267. // ULONG Status;
  3268. BOOL fExcRaised = FALSE;
  3269. PWINSINTF_RECORD_ACTION_T pRow;
  3270. DWORD i;
  3271. DWORD ind;
  3272. DWORD EntType;
  3273. // DWORD MaxAdds;
  3274. PWINSTHD_TLS_T pTls;
  3275. DBGENTER("PackageRecs\n");
  3276. i = 0;
  3277. GET_TLS_M(pTls);
  3278. try {
  3279. //
  3280. // If there are records to send back and the client has specified
  3281. // a buffer for them, insert the records
  3282. //
  3283. if (NoOfRecs > 0)
  3284. {
  3285. //
  3286. // Allocate memory for the no of records
  3287. //
  3288. pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
  3289. //
  3290. // If memory can not be allocate, an exception will be returned
  3291. // by midl_user_alloc
  3292. //
  3293. pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
  3294. #if 0
  3295. pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
  3296. if (Status != RPC_S_OK)
  3297. {
  3298. DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3299. }
  3300. #endif
  3301. pRow = pRecs->pRow;
  3302. for (; i<NoOfRecs; i++)
  3303. {
  3304. //
  3305. // Initialize so that we don't get "enum wrong" error.
  3306. //
  3307. pRow->Cmd_e = WINSINTF_E_QUERY;
  3308. //
  3309. // the name retrieved has NULL as the last character. This
  3310. // We need to pass a name without this NULL.
  3311. //
  3312. pRow->NameLen = pBuff->NameLen;
  3313. if (*pBuff->pName == 0x1B)
  3314. {
  3315. WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
  3316. }
  3317. // +1 added to fix #390830
  3318. pRow->pName = midl_user_allocate(pRow->NameLen + 1);
  3319. #if 0
  3320. pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
  3321. if (Status != RPC_S_OK)
  3322. {
  3323. DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3324. }
  3325. #endif
  3326. WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,pRow->NameLen);
  3327. WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
  3328. EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
  3329. pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
  3330. ? WINSINTF_E_UNIQUE :
  3331. (NMSDB_ENTRY_NORM_GRP_M(EntType) ?
  3332. WINSINTF_E_NORM_GROUP :
  3333. (NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
  3334. WINSINTF_E_SPEC_GROUP :
  3335. WINSINTF_E_MULTIHOMED));
  3336. if (
  3337. (pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
  3338. (pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
  3339. )
  3340. {
  3341. PWINSINTF_ADD_T pAdd;
  3342. DWORD No;
  3343. if (pBuff->NoOfAdds > 0)
  3344. {
  3345. pRow->NoOfAdds = pBuff->NoOfAdds * 2;
  3346. //
  3347. // Each member is comprised of two addresses,
  3348. // first address is that of the owner WINS, second
  3349. // address is that of the node registered
  3350. //
  3351. pRow->pAdd =
  3352. // RpcSmAllocate(
  3353. midl_user_allocate(
  3354. (unsigned int)(pRow->NoOfAdds)
  3355. *
  3356. sizeof(WINSINTF_ADD_T)//,
  3357. // &Status
  3358. );
  3359. #if 0
  3360. if (Status != RPC_S_OK)
  3361. {
  3362. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3363. }
  3364. #endif
  3365. for (
  3366. No= 0, ind= 0, pAdd = pRow->pAdd;
  3367. No < (pRow->NoOfAdds/2);
  3368. No++
  3369. )
  3370. {
  3371. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
  3372. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  3373. pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
  3374. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
  3375. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  3376. pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
  3377. }
  3378. WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
  3379. }
  3380. }
  3381. else
  3382. {
  3383. pRow->NoOfAdds = 0;
  3384. pRow->pAdd = NULL;
  3385. pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
  3386. pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
  3387. pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
  3388. }
  3389. pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
  3390. pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
  3391. pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
  3392. pRow->VersNo = pBuff->VersNo;
  3393. pRow->TimeStamp = pBuff->TimeStamp;
  3394. pRow->OwnerId = pBuff->OwnerId;
  3395. pRow++;
  3396. pBuff = (PRPL_REC_ENTRY2_T)((LPBYTE)pBuff + RPL_REC_ENTRY2_SIZE);
  3397. PERF("Do the addition above the for loop and store in a var. Use var. here")
  3398. } // end of for loop
  3399. } //end of if block
  3400. else
  3401. {
  3402. pRecs->pRow = NULL;
  3403. }
  3404. } // end of try
  3405. except(EXCEPTION_EXECUTE_HANDLER) {
  3406. DBGPRINTEXC("WinsGetDbRecs");
  3407. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  3408. fExcRaised = TRUE;
  3409. }
  3410. pRecs->TotalNoOfRecs = NoOfRecs;
  3411. if (!fExcRaised)
  3412. {
  3413. pRecs->NoOfRecs = i;
  3414. }
  3415. else
  3416. {
  3417. // RpcSmFree(pRecs->pRow);
  3418. midl_user_free(pRecs->pRow);
  3419. pRecs->NoOfRecs = 0;
  3420. }
  3421. DBGENTER("PackageRecs\n");
  3422. return (WINSINTF_SUCCESS);
  3423. }
  3424. //void __RPC_FAR * __RPC_API
  3425. void *
  3426. midl_user_allocate(size_t cBytes)
  3427. {
  3428. #if 0
  3429. //#ifdef WINSDBG
  3430. LPVOID pMem = WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes);
  3431. DBGPRINT1(DET, "midl_user_alloc: Memory allocated is (%d)\n", pMem);
  3432. return(pMem);
  3433. //#else
  3434. #endif
  3435. return(WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes));
  3436. }
  3437. //void __RPC_FAR __RPC_API
  3438. void
  3439. //midl_user_free(void __RPC_FAR *pMem)
  3440. midl_user_free(void *pMem)
  3441. {
  3442. if (pMem != NULL)
  3443. {
  3444. // DBGPRINT1(DET, "midl_user_free: Memory to free is (%d)\n", pMem);
  3445. WinsMscHeapFree(NmsRpcHeapHdl, pMem);
  3446. }
  3447. return;
  3448. }
  3449. VOID
  3450. LogClientInfo(
  3451. RPC_BINDING_HANDLE ClientHdl,
  3452. BOOL fAbruptTerm
  3453. )
  3454. {
  3455. RPC_STATUS RpcRet;
  3456. RPC_BINDING_HANDLE Binding;
  3457. PTUCHAR pStringBinding;
  3458. PTUCHAR pProtSeq;
  3459. PTUCHAR pNetworkAddress;
  3460. WINSEVT_STRS_T EvtStrs;
  3461. NOTE("remove #if 0 when we go to 540 or above")
  3462. #if 0
  3463. RpcRet = RpcBindingServerFromClient(ClientHdl, &Binding);
  3464. if (RpcRet != RPC_S_OK)
  3465. {
  3466. DBGPRINT1(ERR, "LogClientInfo: Can not get binding handle. Rpc Error = (%d)\nThis could be because named pipe protocol is being used\n", RpcRet);
  3467. Binding = ClientHdl;
  3468. }
  3469. #endif
  3470. NOTE("remove when we go to 540 or above")
  3471. Binding = ClientHdl;
  3472. RpcRet = RpcBindingToStringBinding(Binding, &pStringBinding);
  3473. if (RpcRet != RPC_S_OK)
  3474. {
  3475. DBGPRINT1(ERR, "LogClientInfo: RpcBindingToStringBinding returned error = (%d)\n", RpcRet);
  3476. return;
  3477. }
  3478. RpcRet = RpcStringBindingParse(
  3479. pStringBinding,
  3480. NULL, //don't want uuid
  3481. &pProtSeq,
  3482. &pNetworkAddress,
  3483. NULL, //end point
  3484. NULL //network options
  3485. );
  3486. if (RpcRet != RPC_S_OK)
  3487. {
  3488. DBGPRINT1(ERR, "LogClientInfo: RpcStringBindingParse returned error = (%d)\n", RpcRet);
  3489. RpcStringFree(&pStringBinding);
  3490. return;
  3491. }
  3492. #ifndef UNICODE
  3493. DBGPRINT2(FLOW, "LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
  3494. #else
  3495. #ifdef WINSDBG
  3496. IF_DBG(FLOW)
  3497. {
  3498. wprintf(L"LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
  3499. }
  3500. #endif
  3501. #endif
  3502. RpcStringFree(&pProtSeq);
  3503. RpcStringFree(&pNetworkAddress);
  3504. EvtStrs.NoOfStrs = 1;
  3505. EvtStrs.pStr[0] = (LPTSTR)pNetworkAddress;
  3506. if (fAbruptTerm)
  3507. {
  3508. WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ABRUPT_SHUTDOWN, &EvtStrs);
  3509. }
  3510. else
  3511. {
  3512. WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ORDERLY_SHUTDOWN, &EvtStrs);
  3513. }
  3514. return;
  3515. }