Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4189 lines
124 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(WINS_QUERY_ACCESS);
  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. if (pResultsN->pAddVersMaps == NULL)
  1565. return WINSINTF_FAILURE;
  1566. pAddVersMaps = pResultsN->pAddVersMaps;
  1567. }
  1568. else
  1569. {
  1570. pAddVersMaps = pResults->AddVersMaps;
  1571. }
  1572. pAddVersMapsStore = pAddVersMaps;
  1573. //
  1574. // First extract the timeouts and Non-remote WINS information
  1575. // from the WinsCnf global var. We enter the WinsCnfCnfCrtSec
  1576. // since we need to synchronize with the thread doing the
  1577. // reinitialization (Main thread)
  1578. //
  1579. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1580. if (!fNew)
  1581. {
  1582. pResults->RefreshInterval = WinsCnf.RefreshInterval;
  1583. pResults->TombstoneInterval = WinsCnf.TombstoneInterval;
  1584. pResults->TombstoneTimeout = WinsCnf.TombstoneTimeout;
  1585. pResults->VerifyInterval = WinsCnf.VerifyInterval;
  1586. pResults->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
  1587. pResults->NoOfWorkerThds = NmsNoOfNbtThds;
  1588. }
  1589. else
  1590. {
  1591. pResultsN->RefreshInterval = WinsCnf.RefreshInterval;
  1592. pResultsN->TombstoneInterval = WinsCnf.TombstoneInterval;
  1593. pResultsN->TombstoneTimeout = WinsCnf.TombstoneTimeout;
  1594. pResultsN->VerifyInterval = WinsCnf.VerifyInterval;
  1595. pResultsN->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
  1596. pResultsN->NoOfWorkerThds = NmsNoOfNbtThds;
  1597. }
  1598. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1599. //
  1600. // Enter two critical sections in sequence. No danger of deadlock
  1601. // here. The only other thread that takes both these critical section
  1602. // is the RplPush thread. It takes these in the same order (See
  1603. // HandleVersMapReq())
  1604. //
  1605. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  1606. EnterCriticalSection(&RplVersNoStoreCrtSec);
  1607. try {
  1608. NONPORT("Change when using different address family")
  1609. for (
  1610. i=0, n = 0;
  1611. i < NmsDbNoOfOwners;
  1612. i++
  1613. )
  1614. {
  1615. if (!fNew && (i == WINSINTF_MAX_NO_RPL_PNRS))
  1616. {
  1617. break;
  1618. }
  1619. //
  1620. // if the record is deleted in the in-memory table, it
  1621. // means that there are no records for it in the
  1622. // database
  1623. //
  1624. if ((pNmsDbOwnAddTbl+i)->WinsState_e == NMSDB_E_WINS_DELETED)
  1625. {
  1626. //
  1627. // if only active mappings are sought, skip this
  1628. // entry
  1629. //
  1630. if (!fAllMaps)
  1631. {
  1632. continue;
  1633. }
  1634. else
  1635. {
  1636. fDel = TRUE;
  1637. }
  1638. }
  1639. //
  1640. // Find address corresponding to the owner id.
  1641. //
  1642. RPL_FIND_ADD_BY_OWNER_ID_M(i, pWinsAdd, pWinsState_e,
  1643. pStartVersNo);
  1644. //
  1645. // It is possible for NmsDbNoOfOwners to be more than the
  1646. // number of initialized RplPullVersNoTbl entries. When
  1647. // we reach a NULL entry, we break out of the loop.
  1648. //
  1649. if (pWinsAdd != NULL)
  1650. {
  1651. pAddVersMaps->Add.Type = WINSINTF_TCP_IP;
  1652. pAddVersMaps->Add.Len = pWinsAdd->AddLen;
  1653. pAddVersMaps->Add.IPAdd = pWinsAdd->Add.IPAdd;
  1654. pAddVersMaps++->VersNo = (fDel == FALSE) ? (pRplPullOwnerVersNo+i)->VersNo : VersNoForDelRec;
  1655. }
  1656. else
  1657. {
  1658. break;
  1659. }
  1660. if (fDel)
  1661. {
  1662. fDel = FALSE;
  1663. }
  1664. n++;
  1665. } // end of for ..
  1666. //
  1667. // Since RplPullOwnerVersNo[0] may be out of date, let us get
  1668. // get the uptodate value
  1669. //
  1670. NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
  1671. pAddVersMapsStore->VersNo
  1672. );
  1673. if (fNew)
  1674. {
  1675. pResultsN->NoOfOwners = n;
  1676. }
  1677. else
  1678. {
  1679. pResults->NoOfOwners = n;
  1680. }
  1681. NOTE("Wins Mib agent relies on the first entry being that of the local WINS")
  1682. NOTE("See WinsMib.c -- EnumAddKeys")
  1683. #if 0
  1684. //
  1685. // Since RplPullOwnerVersNo[0] may be out of date, let us get
  1686. // get the uptodate value
  1687. //
  1688. NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
  1689. pResults->AddVersMaps[0].VersNo
  1690. );
  1691. #endif
  1692. }
  1693. except(EXCEPTION_EXECUTE_HANDLER) {
  1694. DBGPRINTEXC("GetConfig");
  1695. //
  1696. // log a message
  1697. //
  1698. }
  1699. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  1700. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  1701. return(WINSINTF_SUCCESS);
  1702. }
  1703. DWORD
  1704. GetStatistics(
  1705. LPVOID pResultsA,
  1706. BOOL fNew
  1707. )
  1708. /*++
  1709. Routine Description:
  1710. This function returns with the highest version number of records
  1711. owned by a particular WINS
  1712. Arguments:
  1713. Externals Used:
  1714. None
  1715. Return Value:
  1716. Success status codes -- WINSINTF_SUCCESS
  1717. Error status codes -- WINSINTF_FAILURE
  1718. Error Handling:
  1719. Called by:
  1720. Side Effects:
  1721. Comments:
  1722. None
  1723. --*/
  1724. {
  1725. PRPL_CONFIG_REC_T pPnr;
  1726. PWINSINTF_RPL_COUNTERS_T pPnrData;
  1727. DWORD i;
  1728. PWINSINTF_RESULTS_T pResults = pResultsA;
  1729. PWINSINTF_RESULTS_NEW_T pResultsN = pResultsA;
  1730. ASSERT(pResults != NULL);
  1731. //
  1732. // If client passed us a non-null pRplPnr, then we return failure
  1733. // so as to avoid a memory leak.
  1734. //
  1735. if (!fNew)
  1736. {
  1737. if (pResults->WinsStat.pRplPnrs != NULL)
  1738. {
  1739. return(WINSINTF_FAILURE);
  1740. }
  1741. }
  1742. else
  1743. {
  1744. if (pResultsN->WinsStat.pRplPnrs != NULL)
  1745. {
  1746. return(WINSINTF_FAILURE);
  1747. }
  1748. }
  1749. //
  1750. // Copy the counters
  1751. //
  1752. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1753. if (!fNew)
  1754. {
  1755. pResults->WinsStat.Counters = WinsIntfStat.Counters;
  1756. FUTURES("Get rid of of the following two fields")
  1757. pResults->WinsStat.Counters.NoOfQueries =
  1758. WinsIntfStat.Counters.NoOfSuccQueries +
  1759. WinsIntfStat.Counters.NoOfFailQueries;
  1760. pResults->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
  1761. + WinsIntfStat.Counters.NoOfFailRel;
  1762. }
  1763. else
  1764. {
  1765. pResultsN->WinsStat.Counters = WinsIntfStat.Counters;
  1766. FUTURES("Get rid of of the following two fields")
  1767. pResultsN->WinsStat.Counters.NoOfQueries =
  1768. WinsIntfStat.Counters.NoOfSuccQueries +
  1769. WinsIntfStat.Counters.NoOfFailQueries;
  1770. pResultsN->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
  1771. + WinsIntfStat.Counters.NoOfFailRel;
  1772. }
  1773. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1774. //
  1775. // Copy the TimeStamps and replication specific counters
  1776. //
  1777. EnterCriticalSection(&WinsIntfCrtSec);
  1778. {
  1779. PWINSINTF_STAT_T pWinsStat = (fNew) ? &(pResultsN->WinsStat) : &(pResults->WinsStat);
  1780. TIME_ZONE_INFORMATION tzInfo;
  1781. GetTimeZoneInformation(&tzInfo);
  1782. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.WinsStartTime), &(pWinsStat->TimeStamps.WinsStartTime));
  1783. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPScvTime), &(pWinsStat->TimeStamps.LastPScvTime));
  1784. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATScvTime), &(pWinsStat->TimeStamps.LastATScvTime));
  1785. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastTombScvTime), &(pWinsStat->TimeStamps.LastTombScvTime));
  1786. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastVerifyScvTime), &(pWinsStat->TimeStamps.LastVerifyScvTime));
  1787. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastInitDbTime), &(pWinsStat->TimeStamps.LastInitDbTime));
  1788. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPRplTime), &(pWinsStat->TimeStamps.LastPRplTime));
  1789. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATRplTime), &(pWinsStat->TimeStamps.LastATRplTime));
  1790. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastNTRplTime), &(pWinsStat->TimeStamps.LastNTRplTime));
  1791. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastACTRplTime), &(pWinsStat->TimeStamps.LastACTRplTime));
  1792. SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.CounterResetTime), &(pWinsStat->TimeStamps.CounterResetTime));
  1793. }
  1794. LeaveCriticalSection(&WinsIntfCrtSec);
  1795. EnterCriticalSection(&WinsCnfCnfCrtSec);
  1796. try {
  1797. DWORD NoOfPnrs;
  1798. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  1799. if (!fNew)
  1800. {
  1801. NoOfPnrs = pResults->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
  1802. }
  1803. else
  1804. {
  1805. NoOfPnrs = pResultsN->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
  1806. }
  1807. //
  1808. // If no. of push pnrs (pnrs under the pull key) is > 0
  1809. //
  1810. if (NoOfPnrs > 0)
  1811. {
  1812. if (!fNew)
  1813. {
  1814. pPnrData = pResults->WinsStat.pRplPnrs =
  1815. midl_user_allocate(pResults->WinsStat.NoOfPnrs *
  1816. sizeof(WINSINTF_RPL_COUNTERS_T));
  1817. }
  1818. else
  1819. {
  1820. pPnrData = pResultsN->WinsStat.pRplPnrs =
  1821. midl_user_allocate(pResultsN->WinsStat.NoOfPnrs *
  1822. sizeof(WINSINTF_RPL_COUNTERS_T));
  1823. }
  1824. PERF("remove one of the expressions in the test condition of the if statement")
  1825. for (
  1826. i = 0;
  1827. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  1828. &&
  1829. i < NoOfPnrs;
  1830. pPnrData++, i++
  1831. )
  1832. {
  1833. pPnrData->Add.IPAdd = pPnr->WinsAdd.Add.IPAdd;
  1834. (VOID)InterlockedExchange(
  1835. &pPnrData->NoOfRpls, pPnr->NoOfRpls);
  1836. (VOID)InterlockedExchange(
  1837. &pPnrData->NoOfCommFails,
  1838. pPnr->NoOfCommFails
  1839. );
  1840. //
  1841. // Get the next record that follows this one sequentially
  1842. //
  1843. pPnr = WinsCnfGetNextRplCnfRec(
  1844. pPnr,
  1845. RPL_E_IN_SEQ //seq. traversal
  1846. );
  1847. }
  1848. }
  1849. else
  1850. {
  1851. if (!fNew)
  1852. {
  1853. pResults->WinsStat.pRplPnrs = NULL;
  1854. }
  1855. else
  1856. {
  1857. pResultsN->WinsStat.pRplPnrs = NULL;
  1858. }
  1859. }
  1860. }
  1861. except(EXCEPTION_EXECUTE_HANDLER) {
  1862. DBGPRINTEXC("GetStatistics");
  1863. //
  1864. // log a message
  1865. //
  1866. }
  1867. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  1868. GetConfig(pResultsA, fNew, FALSE);
  1869. return(WINSINTF_SUCCESS);
  1870. } // GetStatistics
  1871. DWORD
  1872. WinsDoStaticInit(
  1873. LPWSTR pDataFilePath,
  1874. DWORD fDel
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. This function does the STATIC initialization of WINS
  1879. Arguments:
  1880. pDataFilePath - Path to the data file or NULL
  1881. Externals Used:
  1882. None
  1883. Return Value:
  1884. Success status codes -- WINSINTF_SUCCESS
  1885. Error status codes -- WINSINTF_FAILURE
  1886. Error Handling:
  1887. Called by:
  1888. R_WinsDoStaticInit
  1889. Side Effects:
  1890. Comments:
  1891. None
  1892. --*/
  1893. {
  1894. WINSCNF_CNF_T WinsCnf;
  1895. STATUS RetStat = WINS_SUCCESS;
  1896. //
  1897. // If no path has been specified, take the values from the registry
  1898. //
  1899. if (pDataFilePath == NULL)
  1900. {
  1901. //
  1902. // Read the DataFiles info information
  1903. //
  1904. // This function will return with either the name of the default
  1905. // file to read or one or more files specified under the
  1906. // Parameters\Datafiles key of WINS
  1907. //
  1908. (VOID)WinsCnfGetNamesOfDataFiles(&WinsCnf);
  1909. }
  1910. else
  1911. {
  1912. FUTURES("expensive. Change idl prototype to pass length")
  1913. if (lstrlen(pDataFilePath) >= WINS_MAX_FILENAME_SZ)
  1914. {
  1915. return(WINSINTF_STATIC_INIT_FAILED);
  1916. }
  1917. //
  1918. // Set time of data initialization
  1919. //
  1920. WinsIntfSetTime(NULL, WINSINTF_E_INIT_DB);
  1921. WinsMscAlloc(WINSCNF_FILE_INFO_SZ, &WinsCnf.pStaticDataFile);
  1922. lstrcpy(WinsCnf.pStaticDataFile->FileNm, pDataFilePath);
  1923. WinsCnf.pStaticDataFile->StrType = REG_EXPAND_SZ;
  1924. WinsCnf.NoOfDataFiles = 1;
  1925. }
  1926. //
  1927. // If Static initialization fails, it will be logged.
  1928. // This function does not return an error code
  1929. //
  1930. if ((RetStat = WinsPrsDoStaticInit(
  1931. WinsCnf.pStaticDataFile,
  1932. WinsCnf.NoOfDataFiles,
  1933. FALSE //do it synchronously
  1934. )) == WINS_SUCCESS)
  1935. {
  1936. if ((pDataFilePath != NULL) && fDel)
  1937. {
  1938. if (!DeleteFile(pDataFilePath))
  1939. {
  1940. DWORD Error;
  1941. Error = GetLastError();
  1942. if (Error != ERROR_FILE_NOT_FOUND)
  1943. {
  1944. DBGPRINT1(ERR, "DbgOpenFile: Could not delete the data file. Error = (%d). Dbg file will not be truncated\n", Error);
  1945. WinsEvtLogDetEvt(FALSE, WINS_EVT_COULD_NOT_DELETE_FILE,
  1946. TEXT("winsintf.c"), __LINE__, "ud", pDataFilePath, Error);
  1947. RetStat = Error;
  1948. }
  1949. }
  1950. }
  1951. }
  1952. return (RetStat == WINS_SUCCESS ? WINSINTF_SUCCESS : WINSINTF_STATIC_INIT_FAILED);
  1953. }
  1954. DWORD
  1955. WinsDoScavenging(
  1956. VOID
  1957. )
  1958. /*++
  1959. Routine Description:
  1960. This function starts the scavenging cycle
  1961. Arguments:
  1962. None
  1963. Externals Used:
  1964. None
  1965. Return Value:
  1966. Success status codes -- WINSINTF_SUCCESS
  1967. Error status codes -- exception from WinsMscSignalHdl
  1968. Error Handling:
  1969. Called by:
  1970. R_WinsDoScavenging
  1971. Side Effects:
  1972. Comments:
  1973. None
  1974. --*/
  1975. {
  1976. PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
  1977. pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
  1978. pWrkItm->Opcode_e = WINSINTF_E_SCV_GENERAL;
  1979. pWrkItm->CmdTyp_e = QUE_E_CMD_SCV_ADMIN;
  1980. pWrkItm->fForce = 0;
  1981. pWrkItm->Age = 1; //should not be zero since zero implies
  1982. //consistency check on all replicas.
  1983. WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
  1984. QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
  1985. return (WINSINTF_SUCCESS);
  1986. }
  1987. DWORD
  1988. WinsDoScavengingNew(
  1989. PWINSINTF_SCV_REQ_T pScvReq
  1990. )
  1991. /*++
  1992. Routine Description:
  1993. This function starts the scavenging cycle
  1994. Arguments:
  1995. None
  1996. Externals Used:
  1997. None
  1998. Return Value:
  1999. Success status codes -- WINSINTF_SUCCESS
  2000. Error status codes -- exception from WinsMscSignalHdl
  2001. Error Handling:
  2002. Called by:
  2003. R_WinsDoScavenging
  2004. Side Effects:
  2005. Comments:
  2006. None
  2007. --*/
  2008. {
  2009. PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
  2010. pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
  2011. pWrkItm->Opcode_e = pScvReq->Opcode_e;
  2012. pWrkItm->Age = pScvReq->Age;
  2013. pWrkItm->fForce = pScvReq->fForce;
  2014. if (WINSINTF_E_SCV_GENERAL == pWrkItm->Opcode_e ) {
  2015. WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
  2016. } else {
  2017. WinsLogAdminEvent( WINS_EVT_ADMIN_CCCHECK_INITIATED, 0);
  2018. }
  2019. QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
  2020. return (WINSINTF_SUCCESS);
  2021. }
  2022. DWORD
  2023. WinsGetDbRecs (
  2024. PWINSINTF_ADD_T pWinsAdd,
  2025. WINSINTF_VERS_NO_T MinVersNo,
  2026. WINSINTF_VERS_NO_T MaxVersNo,
  2027. PWINSINTF_RECS_T pRecs
  2028. )
  2029. /*++
  2030. Routine Description:
  2031. This function returns with all the records (that can fit into the
  2032. buffer passed) owned by a WINS in the local db of this WINS.
  2033. Arguments:
  2034. Externals Used:
  2035. None
  2036. Return Value:
  2037. Success status codes --
  2038. Error status codes --
  2039. Error Handling:
  2040. Called by:
  2041. Side Effects:
  2042. Comments:
  2043. None
  2044. --*/
  2045. {
  2046. COMM_ADD_T Address;
  2047. PRPL_REC_ENTRY_T pBuff = NULL;
  2048. LPVOID pStartBuff;
  2049. DWORD BuffLen;
  2050. DWORD NoOfRecs;
  2051. PWINSINTF_RECORD_ACTION_T pRow;
  2052. DWORD i;
  2053. DWORD ind;
  2054. //VERS_NO_T MinVersNo = {0,0};
  2055. DWORD EntType;
  2056. PWINSTHD_TLS_T pTls;
  2057. //ULONG Status;
  2058. BOOL fExcRaised = FALSE;
  2059. // PVOID pCallersAdd, pCallersCaller;
  2060. // RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
  2061. DBGENTER("WinsGetDbRecs\n");
  2062. if (LiLtr(MaxVersNo, MinVersNo))
  2063. {
  2064. return(WINSINTF_FAILURE);
  2065. }
  2066. Address.AddTyp_e = pWinsAdd->Type;
  2067. Address.AddLen = pWinsAdd->Len;
  2068. //
  2069. // snmp agent can pass a 0 for the address to ask for all records
  2070. // owned by the local wins.
  2071. //
  2072. if (pWinsAdd->IPAdd == 0)
  2073. {
  2074. Address.AddTyp_e = NmsLocalAdd.AddTyp_e;
  2075. Address.AddLen = NmsLocalAdd.AddLen;
  2076. Address.Add.IPAdd = NmsLocalAdd.Add.IPAdd;
  2077. }
  2078. else
  2079. {
  2080. Address.AddTyp_e = pWinsAdd->Type;
  2081. Address.AddLen = pWinsAdd->Len;
  2082. Address.Add.IPAdd = pWinsAdd->IPAdd;
  2083. }
  2084. //
  2085. // initialize this thread with the db engine
  2086. //
  2087. NmsDbThdInit(WINS_E_WINSRPC);
  2088. NmsDbOpenTables(WINS_E_WINSRPC);
  2089. DBGMYNAME("RPC-WinsGetDbRecs");
  2090. PERF("The caller can pass the number of records for which space has been")
  2091. PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
  2092. PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
  2093. PERF("more records than are necessary")
  2094. GET_TLS_M(pTls);
  2095. try {
  2096. NmsDbGetDataRecs(
  2097. WINS_E_WINSRPC,
  2098. 0, //not used
  2099. MinVersNo,
  2100. MaxVersNo,
  2101. 0, //not used
  2102. LiEqlZero(MinVersNo) && LiEqlZero(MaxVersNo) ? TRUE : FALSE,
  2103. FALSE, //not used
  2104. NULL, //must be NULL since we are not doing
  2105. //scavenging of clutter
  2106. &Address,
  2107. FALSE, //dynamic + static records are wanted
  2108. //#if RPL_TYPE
  2109. WINSCNF_RPL_DEFAULT_TYPE,
  2110. //#endif
  2111. &pBuff,
  2112. &BuffLen,
  2113. &NoOfRecs
  2114. );
  2115. i = 0;
  2116. pStartBuff = pBuff;
  2117. //
  2118. // If there are records to send back and the client has specified
  2119. // a buffer for them, insert the records
  2120. //
  2121. if (NoOfRecs > 0)
  2122. {
  2123. //
  2124. // Allocate memory for the no of records
  2125. //
  2126. pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
  2127. //
  2128. // If memory can not be allocate, an exception will be returned
  2129. // by midl_user_alloc
  2130. //
  2131. pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
  2132. // DBGPRINT1(DET, "WinsGetDbRecs: Address of memory for records is (%d)\n", pRecs->pRow);
  2133. #if 0
  2134. pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
  2135. if (Status != RPC_S_OK)
  2136. {
  2137. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2138. }
  2139. #endif
  2140. pRow = pRecs->pRow;
  2141. for (; i<NoOfRecs; i++)
  2142. {
  2143. //
  2144. // Initialize so that we don't get "enum wrong" error.
  2145. //
  2146. pRow->Cmd_e = WINSINTF_E_QUERY;
  2147. //
  2148. // the name retrieved has NULL as the last character. This
  2149. // We need to pass a name without this NULL.
  2150. //
  2151. pRow->NameLen = pBuff->NameLen;
  2152. if (*pBuff->pName == 0x1B)
  2153. {
  2154. WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
  2155. }
  2156. pRow->pName = midl_user_allocate(pRow->NameLen + 1);
  2157. //DBGPRINT2(DET, "WinsGetDbRecs: Address of name = (%s) is (%d) \n", pBuff->pName, pRow->pName);
  2158. #if 0
  2159. pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
  2160. if (Status != RPC_S_OK)
  2161. {
  2162. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2163. }
  2164. #endif
  2165. WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,
  2166. pRow->NameLen);
  2167. WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
  2168. EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
  2169. pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
  2170. ? WINSINTF_E_UNIQUE :
  2171. (NMSDB_ENTRY_NORM_GRP_M(EntType) ?
  2172. WINSINTF_E_NORM_GROUP :
  2173. (NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
  2174. WINSINTF_E_SPEC_GROUP :
  2175. WINSINTF_E_MULTIHOMED));
  2176. if (
  2177. (pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
  2178. (pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
  2179. )
  2180. {
  2181. PWINSINTF_ADD_T pAdd;
  2182. DWORD No;
  2183. if (pBuff->NoOfAdds > 0)
  2184. {
  2185. pRow->NoOfAdds = pBuff->NoOfAdds * 2;
  2186. //
  2187. // Each member is comprised of two addresses,
  2188. // first address is that of the owner WINS, second
  2189. // address is that of the node registered
  2190. //
  2191. pRow->pAdd =
  2192. // RpcSmAllocate(
  2193. midl_user_allocate(
  2194. (unsigned int)(pRow->NoOfAdds)
  2195. *
  2196. sizeof(WINSINTF_ADD_T)//,
  2197. // &Status
  2198. );
  2199. //DBGPRINT2(DET, "WinsGetDbRecs: Address of ip address for name = (%s) is (%d) \n", pRow->pName, pRow->pAdd);
  2200. #if 0
  2201. if (Status != RPC_S_OK)
  2202. {
  2203. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  2204. }
  2205. #endif
  2206. for (
  2207. No= 0, ind= 0, pAdd = pRow->pAdd;
  2208. No < (pRow->NoOfAdds/2);
  2209. No++
  2210. )
  2211. {
  2212. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
  2213. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  2214. pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
  2215. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
  2216. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  2217. pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
  2218. }
  2219. WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
  2220. }
  2221. }
  2222. else
  2223. {
  2224. pRow->NoOfAdds = 0;
  2225. pRow->pAdd = NULL;
  2226. pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
  2227. pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
  2228. pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
  2229. }
  2230. pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
  2231. pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
  2232. pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
  2233. pRow->VersNo = pBuff->VersNo;
  2234. pRow->TimeStamp = pBuff->TimeStamp;
  2235. pRow++;
  2236. pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
  2237. PERF("Do the addition above the for loop and store in a var. Use var. here")
  2238. } // end of for loop
  2239. } //end of if block
  2240. else
  2241. {
  2242. pRecs->pRow = NULL;
  2243. }
  2244. } // end of try
  2245. except(EXCEPTION_EXECUTE_HANDLER) {
  2246. DBGPRINTEXC("WinsGetDbRecs");
  2247. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  2248. fExcRaised = TRUE;
  2249. }
  2250. pRecs->TotalNoOfRecs = NoOfRecs;
  2251. //
  2252. // Deallocate the buffer allocated by NmsDbGetDataRecs
  2253. //
  2254. WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
  2255. WinsMscHeapDestroy(pTls->HeapHdl);
  2256. if (!fExcRaised)
  2257. {
  2258. pRecs->NoOfRecs = i;
  2259. }
  2260. else
  2261. {
  2262. // RpcSmFree(pRecs->pRow);
  2263. midl_user_free(pRecs->pRow);
  2264. pRecs->NoOfRecs = 0;
  2265. }
  2266. //
  2267. // Let us end the session
  2268. //
  2269. NmsDbCloseTables();
  2270. NmsDbEndSession();
  2271. DBGLEAVE("WinsGetDbRecs\n");
  2272. return (WINSINTF_SUCCESS);
  2273. }
  2274. VOID
  2275. WinsIntfSetTime(
  2276. OUT PSYSTEMTIME pTime,
  2277. IN WINSINTF_TIME_TYPE_E TimeType_e
  2278. )
  2279. /*++
  2280. Routine Description:
  2281. This function is called to set the the time in the WINSINTF_STAT_T
  2282. structure
  2283. Arguments:
  2284. pTime - Local Time (returned)
  2285. TimeType_e - The activity for which the time has to be stored
  2286. Externals Used:
  2287. None
  2288. Return Value:
  2289. NONE
  2290. Error Handling:
  2291. Called by:
  2292. Side Effects:
  2293. Comments:
  2294. None
  2295. --*/
  2296. {
  2297. SYSTEMTIME SysTime;
  2298. PSYSTEMTIME pSysTime = &SysTime;
  2299. GetSystemTime(pSysTime);
  2300. EnterCriticalSection(&WinsIntfCrtSec);
  2301. switch(TimeType_e)
  2302. {
  2303. case(WINSINTF_E_WINS_START):
  2304. WinsIntfStat.TimeStamps.WinsStartTime = *pSysTime;
  2305. break;
  2306. case(WINSINTF_E_PLANNED_SCV):
  2307. WinsIntfStat.TimeStamps.LastPScvTime = *pSysTime;
  2308. break;
  2309. case(WINSINTF_E_ADMIN_TRIG_SCV):
  2310. WinsIntfStat.TimeStamps.LastATScvTime = *pSysTime;
  2311. break;
  2312. case(WINSINTF_E_TOMBSTONES_SCV):
  2313. WinsIntfStat.TimeStamps.LastTombScvTime = *pSysTime;
  2314. break;
  2315. case(WINSINTF_E_VERIFY_SCV):
  2316. WinsIntfStat.TimeStamps.LastVerifyScvTime = *pSysTime;
  2317. break;
  2318. case(WINSINTF_E_INIT_DB):
  2319. WinsIntfStat.TimeStamps.LastInitDbTime = *pSysTime;
  2320. break;
  2321. case(WINSINTF_E_PLANNED_PULL):
  2322. WinsIntfStat.TimeStamps.LastPRplTime = *pSysTime;
  2323. break;
  2324. case(WINSINTF_E_ADMIN_TRIG_PULL):
  2325. WinsIntfStat.TimeStamps.LastATRplTime = *pSysTime;
  2326. break;
  2327. case(WINSINTF_E_NTWRK_TRIG_PULL):
  2328. WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
  2329. break;
  2330. case(WINSINTF_E_UPDCNT_TRIG_PULL):
  2331. WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
  2332. break;
  2333. case(WINSINTF_E_ADDCHG_TRIG_PULL):
  2334. WinsIntfStat.TimeStamps.LastACTRplTime = *pSysTime;
  2335. break;
  2336. case(WINSINTF_E_COUNTER_RESET):
  2337. WinsIntfStat.TimeStamps.CounterResetTime = *pSysTime;
  2338. break;
  2339. default:
  2340. DBGPRINT1(EXC, "WinsIntfSetTime: Weird Timestamp type = (%d)\n", TimeType_e);
  2341. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  2342. break;
  2343. }
  2344. LeaveCriticalSection(&WinsIntfCrtSec);
  2345. if (pTime)
  2346. {
  2347. TIME_ZONE_INFORMATION tzInfo;
  2348. GetTimeZoneInformation(&tzInfo);
  2349. SystemTimeToTzSpecificLocalTime(&tzInfo, pSysTime, pTime);
  2350. }
  2351. return;
  2352. }
  2353. DWORD
  2354. WinsDelDbRecs(
  2355. IN PWINSINTF_ADD_T pAdd,
  2356. IN WINSINTF_VERS_NO_T MinVersNo,
  2357. IN WINSINTF_VERS_NO_T MaxVersNo
  2358. )
  2359. /*++
  2360. Routine Description:
  2361. This func. deletes a specified range of records belonging to a
  2362. particular owner
  2363. Arguments:
  2364. Externals Used:
  2365. None
  2366. Return Value:
  2367. Success status codes -- WINSINTF_SUCCESS
  2368. Error status codes -- WINSINTF_FAILURE
  2369. Error Handling:
  2370. Called by:
  2371. R_WinsDelDbRecs
  2372. Side Effects:
  2373. Comments:
  2374. None
  2375. --*/
  2376. {
  2377. COMM_ADD_T Address;
  2378. DWORD RetVal = WINSINTF_SUCCESS;
  2379. DWORD dwOwnerId;
  2380. BOOL fAllocNew = FALSE;
  2381. Address.AddTyp_e = pAdd->Type;
  2382. Address.AddLen = pAdd->Len;
  2383. Address.Add.IPAdd = pAdd->IPAdd;
  2384. //
  2385. // initialize this thread with the db engine
  2386. //
  2387. NmsDbThdInit(WINS_E_WINSRPC);
  2388. NmsDbOpenTables(WINS_E_WINSRPC);
  2389. DBGMYNAME("RPC-WinsDelDbRecs");
  2390. if (RplFindOwnerId(
  2391. &Address,
  2392. &fAllocNew, //do not allocate an entry if not
  2393. //present
  2394. &dwOwnerId,
  2395. WINSCNF_E_IGNORE_PREC,
  2396. WINSCNF_LOW_PREC
  2397. ) != WINS_SUCCESS)
  2398. {
  2399. DBGPRINT0(DET, "WinsDelDataRecs: WINS is not in the owner-add mapping table\n");
  2400. RetVal = WINSINTF_FAILURE;
  2401. }
  2402. else
  2403. {
  2404. if (NmsDbDelDataRecs(
  2405. dwOwnerId,
  2406. MinVersNo,
  2407. MaxVersNo,
  2408. TRUE, //enter critical section
  2409. FALSE //no fragmented deletion
  2410. ) != WINS_SUCCESS)
  2411. {
  2412. RetVal = WINSINTF_FAILURE;
  2413. }
  2414. }
  2415. //
  2416. // Let us end the session
  2417. //
  2418. NmsDbCloseTables();
  2419. NmsDbEndSession();
  2420. return(RetVal);
  2421. }
  2422. DWORD
  2423. WinsTombstoneDbRecs(
  2424. IN PWINSINTF_ADD_T pAdd,
  2425. IN WINSINTF_VERS_NO_T MinVersNo,
  2426. IN WINSINTF_VERS_NO_T MaxVersNo
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. This func. tombstones a specified range of records belonging to a
  2431. particular owner
  2432. Arguments:
  2433. Externals Used:
  2434. None
  2435. Return Value:
  2436. Success status codes -- WINSINTF_SUCCESS
  2437. Error status codes -- WINSINTF_FAILURE
  2438. Error Handling:
  2439. Called by:
  2440. R_WinsTombstoneDbRecs
  2441. Side Effects:
  2442. Comments:
  2443. None
  2444. --*/
  2445. {
  2446. DWORD RetVal = WINSINTF_SUCCESS;
  2447. COMM_ADD_T Address;
  2448. DWORD dwOwnerId;
  2449. BOOL fAllocNew = FALSE;
  2450. Address.AddTyp_e = pAdd->Type;
  2451. Address.AddLen = pAdd->Len;
  2452. Address.Add.IPAdd = pAdd->IPAdd;
  2453. //
  2454. // initialize this thread with the db engine
  2455. //
  2456. NmsDbThdInit(WINS_E_WINSRPC);
  2457. NmsDbOpenTables(WINS_E_WINSRPC);
  2458. DBGMYNAME("RPC-WinsTombstoneDbRecs");
  2459. if (RplFindOwnerId(
  2460. &Address,
  2461. &fAllocNew, //do not allocate an entry if not
  2462. //present
  2463. &dwOwnerId,
  2464. WINSCNF_E_IGNORE_PREC,
  2465. WINSCNF_LOW_PREC
  2466. ) != WINS_SUCCESS)
  2467. {
  2468. DBGPRINT0(DET, "WinsTombstoneDataRecs: WINS is not in the owner-add mapping table\n");
  2469. RetVal = WINSINTF_FAILURE;
  2470. }else if(NmsDbTombstoneDataRecs(
  2471. dwOwnerId,
  2472. MinVersNo,
  2473. MaxVersNo
  2474. ) != WINS_SUCCESS)
  2475. {
  2476. RetVal = WINSINTF_FAILURE;
  2477. }
  2478. // Let us end the session
  2479. NmsDbCloseTables();
  2480. NmsDbEndSession();
  2481. return(RetVal);
  2482. }
  2483. DWORD
  2484. WinsPullRange(
  2485. IN PWINSINTF_ADD_T pWinsAdd,
  2486. IN PWINSINTF_ADD_T pOwnerAdd,
  2487. IN WINSINTF_VERS_NO_T MinVersNo,
  2488. IN WINSINTF_VERS_NO_T MaxVersNo
  2489. )
  2490. /*++
  2491. Routine Description:
  2492. This function is called to pull a range of records owned by a particular
  2493. WINS server from another WINS server.
  2494. Arguments:
  2495. Externals Used:
  2496. None
  2497. Return Value:
  2498. Success status codes --
  2499. Error status codes --
  2500. Error Handling:
  2501. Called by:
  2502. Side Effects:
  2503. Comments:
  2504. None
  2505. --*/
  2506. {
  2507. PWINSINTF_PULL_RANGE_INFO_T pPullRangeInfo;
  2508. PRPL_CONFIG_REC_T pPnr;
  2509. BOOL fRplPnr = FALSE;
  2510. DWORD RetCode = WINSINTF_SUCCESS;
  2511. //
  2512. // if the minimum version number is > than the max version number
  2513. // return a failure code
  2514. //
  2515. if (LiGtr(MinVersNo, MaxVersNo))
  2516. {
  2517. return(WINSINTF_FAILURE);
  2518. }
  2519. //
  2520. // Enter the critical sections guarded by WinsCnfCnfCrtSec and
  2521. // NmsNmhNamRegCrtSec. There is no danger of deadlock because we
  2522. // always enter the two critical sections in the following sequence
  2523. //
  2524. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2525. PERF("Do we need to enter the following critical section")
  2526. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  2527. try {
  2528. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  2529. //
  2530. // If we are allowed to pull only from configured partners,
  2531. // let us try to find the config record of the partner
  2532. //
  2533. if (WinsCnf.fRplOnlyWCnfPnrs)
  2534. {
  2535. if (pPnr != NULL)
  2536. {
  2537. //
  2538. // Search for the Cnf record for the WINS we want to
  2539. // send the PULL RANGE request to.
  2540. //
  2541. for (
  2542. ;
  2543. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  2544. &&
  2545. !fRplPnr;
  2546. // no third expression
  2547. )
  2548. {
  2549. //
  2550. // Check if this is the one we want
  2551. //
  2552. if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->IPAdd)
  2553. {
  2554. //
  2555. // We are done. Set the fRplPnr flag to TRUE so that
  2556. // we break out of the loop.
  2557. //
  2558. fRplPnr = TRUE;
  2559. //
  2560. // Make it 0, so that we always try to establish
  2561. // a connection. Otherwise, pull thread may not
  2562. // try if it has already exhausted the number of
  2563. // retries
  2564. //
  2565. pPnr->RetryCount = 0;
  2566. continue; //so that we can break out
  2567. }
  2568. //
  2569. // Get the next record that follows this one sequentially
  2570. //
  2571. pPnr = WinsCnfGetNextRplCnfRec(
  2572. pPnr,
  2573. RPL_E_IN_SEQ //seq. traversal
  2574. );
  2575. } // end of for
  2576. } // end of if (pPnr != 0)
  2577. } // end of if (fRplOnlyWCnfPnrs)
  2578. else
  2579. {
  2580. pPnr = WinsMscHeapAlloc( NmsRpcHeapHdl, RPL_CONFIG_REC_SIZE);
  2581. COMM_INIT_ADD_M(&pPnr->WinsAdd, pWinsAdd->IPAdd);
  2582. pPnr->MagicNo = 0;
  2583. pPnr->RetryCount = 0;
  2584. pPnr->LastCommFailTime = 0;
  2585. pPnr->PushNtfTries = 0;
  2586. fRplPnr = TRUE;
  2587. //
  2588. // We want the buffer to be deallocated by the PULL thread
  2589. //
  2590. pPnr->fTemp = TRUE;
  2591. //#if RPL_TYPE
  2592. //
  2593. // We need to pull according to the RplType for the pull pnrs
  2594. //
  2595. pPnr->RplType = WinsCnf.PullInfo.RplType;
  2596. //#endif
  2597. }
  2598. if (fRplPnr)
  2599. {
  2600. pPullRangeInfo = WinsMscHeapAlloc(
  2601. NmsRpcHeapHdl,
  2602. sizeof(WINSINTF_PULL_RANGE_INFO_T)
  2603. );
  2604. #if 0
  2605. WinsMscAlloc(sizeof(WINSINTF_PULL_RANGE_INFO_T),
  2606. &pPullRangeInfo);
  2607. #endif
  2608. pPullRangeInfo->pPnr = pPnr;
  2609. pPullRangeInfo->OwnAdd = *pOwnerAdd;
  2610. pPullRangeInfo->MinVersNo = MinVersNo;
  2611. pPullRangeInfo->MaxVersNo = MaxVersNo;
  2612. //
  2613. // Call RplInsertQue to insert the push request to
  2614. // the Pull Thread
  2615. //
  2616. ERplInsertQue(
  2617. WINS_E_WINSRPC,
  2618. QUE_E_CMD_PULL_RANGE,
  2619. NULL, //no Dlg Hdl
  2620. NULL, //no msg is there
  2621. 0, //msg length
  2622. pPullRangeInfo, //client context
  2623. pPnr->MagicNo
  2624. );
  2625. }
  2626. }
  2627. except (EXCEPTION_EXECUTE_HANDLER) {
  2628. DBGPRINTEXC("WinsPullRange");
  2629. WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_PUSH_TRIGGER_EXC);
  2630. RetCode = WINSINTF_FAILURE;
  2631. }
  2632. //
  2633. // Leave the critical section guarded by NmsNmhNamRegCrtSec.
  2634. //
  2635. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  2636. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2637. //
  2638. // if replication was allowed only with configured partners and
  2639. // there was no WINS with the address specified by the client,
  2640. // return failure
  2641. //
  2642. if (!fRplPnr)
  2643. {
  2644. RetCode = WINSINTF_FAILURE;
  2645. }
  2646. return(RetCode);
  2647. }
  2648. DWORD
  2649. WinsSetPriorityClass(
  2650. IN WINSINTF_PRIORITY_CLASS_E PriorityClass_e
  2651. )
  2652. /*++
  2653. Routine Description:
  2654. This function sets the priority class of the Wins process.
  2655. Arguments:
  2656. PriorityClass -- Priority Class of the WINS process
  2657. Externals Used:
  2658. WinsCnf
  2659. Return Value:
  2660. Success status codes --
  2661. Error status codes --
  2662. Error Handling:
  2663. Called by:
  2664. Side Effects:
  2665. Comments:
  2666. None
  2667. --*/
  2668. {
  2669. //DWORD OldPrCls;
  2670. DWORD NewPrCls;
  2671. HANDLE ProcHdl;
  2672. DWORD RetVal = WINSINTF_SUCCESS;
  2673. switch(PriorityClass_e)
  2674. {
  2675. case(WINSINTF_E_NORMAL):
  2676. NewPrCls = NORMAL_PRIORITY_CLASS;
  2677. break;
  2678. case(WINSINTF_E_HIGH):
  2679. NewPrCls = HIGH_PRIORITY_CLASS;
  2680. break;
  2681. default:
  2682. DBGPRINT0(DET, "WinsSetPriorityClass: Invalid Priority Class\n");
  2683. return(WINSINTF_FAILURE);
  2684. break;
  2685. }
  2686. ProcHdl = GetCurrentProcess();
  2687. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2688. #if 0
  2689. try {
  2690. FUTURES("Use a WinsMsc functions here for consistency")
  2691. if ((OldPrCls = GetPriorityClass(ProcHdl)) == 0)
  2692. {
  2693. DBGPRINT1(ERR, "WinsSetPriorityClass: Can not Proc Priority. Error = (%d)\n", GetLastError());
  2694. RetVal = WINSINTF_FAILURE;
  2695. }
  2696. else
  2697. {
  2698. if (OldPrCls == NewPrCls)
  2699. {
  2700. DBGPRINT1(ERR, "WinsSetPriorityClass: Process already has this Priority Class = (%d)\n", NewPrCls);
  2701. }
  2702. else
  2703. {
  2704. #endif
  2705. if (SetPriorityClass(ProcHdl, NewPrCls) == FALSE)
  2706. {
  2707. DBGPRINT1(ERR, "WinsSetPriorityClass: SetPriorityClass() Failed. Error = (%d)\n", GetLastError());
  2708. }
  2709. else
  2710. {
  2711. WinsCnf.WinsPriorityClass = (DWORD)PriorityClass_e;
  2712. }
  2713. #if 0
  2714. }
  2715. }
  2716. }
  2717. except(EXCEPTION_EXECUTE_HANDLER) {
  2718. DBGPRINTEXC("WinsSetPriorityCls");
  2719. }
  2720. #endif
  2721. //
  2722. // ProcHdl is a pseudo-handle and does not need to be closed
  2723. //
  2724. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2725. return(WINSINTF_SUCCESS);
  2726. }
  2727. DWORD
  2728. WinsResetCounters(
  2729. VOID
  2730. )
  2731. /*++
  2732. Routine Description:
  2733. This function resets/clears the counters
  2734. Arguments:
  2735. None
  2736. Externals Used:
  2737. NmsNmhNamRegCrtSec
  2738. Return Value:
  2739. Success status codes --
  2740. Error status codes --
  2741. Error Handling:
  2742. Called by:
  2743. R_WinsResetCounters
  2744. Side Effects:
  2745. Comments:
  2746. None
  2747. --*/
  2748. {
  2749. DWORD i;
  2750. PRPL_CONFIG_REC_T pPnr;
  2751. //
  2752. // Copy the counters
  2753. //
  2754. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  2755. (VOID)RtlFillMemory(&WinsIntfStat.Counters, sizeof(WinsIntfStat.Counters), 0);
  2756. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  2757. // now clear the per partner info.
  2758. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2759. pPnr = WinsCnf.PullInfo.pPullCnfRecs;
  2760. for (i = 0; (i<WinsCnf.PullInfo.NoOfPushPnrs) && (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE) ; i++) {
  2761. pPnr->NoOfRpls = 0;
  2762. pPnr->NoOfCommFails = 0;
  2763. pPnr = WinsCnfGetNextRplCnfRec(pPnr,RPL_E_IN_SEQ);
  2764. }
  2765. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2766. //
  2767. // Even if we have multiple threads doing resets (unlikely occurence),
  2768. // the window between the above critical section and the one entered
  2769. // by the following function does not cause any problem.
  2770. //
  2771. WinsIntfSetTime(NULL, WINSINTF_E_COUNTER_RESET);
  2772. return(WINSINTF_SUCCESS);
  2773. }
  2774. DWORD
  2775. WinsWorkerThdUpd(
  2776. DWORD NewNoOfNbtThds
  2777. )
  2778. /*++
  2779. Routine Description:
  2780. This function is called to change the count of the NBT threads in
  2781. the WINS process.
  2782. Arguments:
  2783. NewNoOfNbtThds - The new count of the Nbt threads
  2784. Externals Used:
  2785. None
  2786. Return Value:
  2787. Success status codes -- WINSINTF_SUCCESS
  2788. Error status codes -- WINSINTF_FAILURE
  2789. Error Handling:
  2790. Called by:
  2791. Side Effects:
  2792. Comments:
  2793. None
  2794. --*/
  2795. {
  2796. //
  2797. // If the WINS server is not in steady state or if the new count
  2798. // of Nbt threads requested is outside the allowed range, return
  2799. // failure
  2800. //
  2801. CHECK("Somehow, if the number of threads is equal to the max. number allowed")
  2802. CHECK("pTls comes out as NULL for all NBT threads (seen at termination)")
  2803. if (
  2804. ((WinsCnf.State_e != WINSCNF_E_RUNNING)
  2805. &&
  2806. (WinsCnf.State_e != WINSCNF_E_PAUSED))
  2807. ||
  2808. (NewNoOfNbtThds >= WINSTHD_MAX_NO_NBT_THDS)
  2809. ||
  2810. (NewNoOfNbtThds < WINSTHD_MIN_NO_NBT_THDS)
  2811. )
  2812. {
  2813. return(WINSINTF_FAILURE);
  2814. }
  2815. EnterCriticalSection(&WinsCnfCnfCrtSec);
  2816. WinsIntfNoOfNbtThds = NewNoOfNbtThds;
  2817. try {
  2818. //
  2819. // If the new count is more than the existing count, store the new
  2820. // count in a global and signal an Nbt thread. The signaled
  2821. // Nbt thread will create all the extra threads needed
  2822. //
  2823. if (NewNoOfNbtThds > NmsNoOfNbtThds)
  2824. {
  2825. WinsMscSignalHdl(NmsCrDelNbtThdEvt);
  2826. }
  2827. else
  2828. {
  2829. //
  2830. // if the new count is same as the existing count, return
  2831. // success
  2832. //
  2833. if (NewNoOfNbtThds == NmsNoOfNbtThds)
  2834. {
  2835. DBGPRINT1(FLOW, "WinsWorkerThdUpd: Wins server already has %d threads\n", NewNoOfNbtThds);
  2836. }
  2837. else // NewNoOfNbtThds < NmsNoOfNbtThds
  2838. {
  2839. //
  2840. // Signal a thread to delete self. The signaled thread will
  2841. // signal the event again if more than one thread has to be
  2842. // deleted
  2843. //
  2844. WinsMscSignalHdl(NmsCrDelNbtThdEvt);
  2845. }
  2846. }
  2847. }
  2848. except (EXCEPTION_EXECUTE_HANDLER) {
  2849. DBGPRINTEXC("WinsWorkerThdUpd");
  2850. }
  2851. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  2852. return(WINSINTF_SUCCESS);
  2853. }
  2854. DWORD
  2855. WinsGetNameAndAdd(
  2856. PWINSINTF_ADD_T pWinsAdd,
  2857. LPBYTE pUncName
  2858. )
  2859. {
  2860. DWORD RetStat = WINSINTF_SUCCESS;
  2861. // TCHAR UncName[MAX_COMPUTERNAME_LENGTH + 1];
  2862. // DWORD LenOfBuff = WINSINTF_MAX_COMPUTERNAME_LENGTH;
  2863. DWORD LenOfBuff = MAX_COMPUTERNAME_LENGTH + 1;
  2864. pWinsAdd->IPAdd = NmsLocalAdd.Add.IPAdd;
  2865. FUTURES("Change this to GetComputerName when winsadmn is made unicode compliant")
  2866. if (GetComputerNameA(pUncName, &LenOfBuff) == FALSE)
  2867. {
  2868. DBGPRINT1(ERR, "WinsGetNameAndAdd: Name error. Error=(%x)\n", GetLastError());
  2869. RetStat = GetLastError();
  2870. }
  2871. return(RetStat);
  2872. }
  2873. #define INITIAL_RAMPUP_NO 3
  2874. DWORD
  2875. WinsGetBrowserNames(
  2876. PWINSINTF_BIND_DATA_T pWinsHdl,
  2877. PWINSINTF_BROWSER_NAMES_T pNames
  2878. )
  2879. {
  2880. DWORD RetVal = WINSINTF_SUCCESS;
  2881. time_t CurrentTime;
  2882. static DWORD sNoOfTimes = 0;
  2883. static time_t sLastTime = 0;
  2884. BOOL fPopCache = FALSE;
  2885. UNREFERENCED_PARAMETER(pWinsHdl);
  2886. //
  2887. // If this the initial ramp up period, populate the cache
  2888. //
  2889. if (sNoOfTimes++ < INITIAL_RAMPUP_NO)
  2890. {
  2891. //
  2892. // if this is the first call, create the dom. cache event.
  2893. //
  2894. if (sNoOfTimes == 1)
  2895. {
  2896. WinsMscCreateEvt(L"WinsDomCachEvt", FALSE, &sDomCache.EvtHdl);
  2897. }
  2898. DBGPRINT1(SPEC, "WinsGetBrowserNames: sNoOfTimes = (%d)\n", sNoOfTimes);
  2899. fPopCache = TRUE;
  2900. }
  2901. else
  2902. {
  2903. //
  2904. // Initial ramp up period is past. Populate the cache if 3 mts
  2905. // have expired since it was last populated
  2906. //
  2907. if ((time(&CurrentTime) - sLastTime) > THREE_MTS || sDomCache.bRefresh)
  2908. {
  2909. DBGPRINT0(SPEC, "WinsGetBrowserNames: Pop Cache due to timeout\n");
  2910. sDomCache.bRefresh = FALSE;
  2911. sLastTime = CurrentTime;
  2912. fPopCache = TRUE;
  2913. }
  2914. }
  2915. try {
  2916. //
  2917. // Populate the cache if fPopCache is set or if the number of entries
  2918. // in the current cache are 0
  2919. //
  2920. if (fPopCache || (sDomCache.SzOfBlock == 0))
  2921. {
  2922. //
  2923. // if our cache has some data, deallocate it first.
  2924. //
  2925. // Note: There could be an rpc thread in the rpc code accessing
  2926. // this buffer. I can't free this buffer until it is done.
  2927. //
  2928. if (sDomCache.SzOfBlock > 0)
  2929. {
  2930. DWORD i;
  2931. PWINSINTF_BROWSER_INFO_T pBrInfo = sDomCache.pInfo;
  2932. DWORD NoOfUsers;
  2933. //
  2934. // Wait until all users are done. We won't iterate more than
  2935. //
  2936. // We can iterate a max. of INITIAL_RAMPUP_NO of times and
  2937. // that too only at initial ramp up time. If a thread is
  2938. // waiting on the event, another thread will also wait
  2939. // on it (except during initial rampup time)
  2940. //
  2941. do {
  2942. EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
  2943. NoOfUsers = sDomCache.NoOfUsers;
  2944. LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
  2945. if (NoOfUsers > 0)
  2946. {
  2947. WinsMscWaitInfinite(sDomCache.EvtHdl);
  2948. }
  2949. } while (NoOfUsers > 0);
  2950. //
  2951. // Free all memory allocated for names
  2952. //
  2953. for (i=0; i< sDomCache.EntriesRead; i++, pBrInfo++)
  2954. {
  2955. midl_user_free(pBrInfo->pName);
  2956. }
  2957. //
  2958. // Free the main block
  2959. //
  2960. midl_user_free(sDomCache.pInfo);
  2961. sDomCache.SzOfBlock = 0;
  2962. pNames->EntriesRead = 0;
  2963. pNames->pInfo = NULL;
  2964. }
  2965. NmsDbThdInit(WINS_E_WINSRPC);
  2966. NmsDbOpenTables(WINS_E_WINSRPC);
  2967. DBGMYNAME("RPC-WinsGetBrowserNames");
  2968. //
  2969. // Get all records starting with 1B Names
  2970. //
  2971. RetVal = NmsDbGetNamesWPrefixChar(
  2972. 0x1B,
  2973. &pNames->pInfo,
  2974. &pNames->EntriesRead
  2975. );
  2976. NmsDbCloseTables();
  2977. NmsDbEndSession();
  2978. //
  2979. // Store the info. only if there is something to be stored.
  2980. //
  2981. if (
  2982. (RetVal == WINS_SUCCESS)
  2983. &&
  2984. (pNames->EntriesRead > 0)
  2985. )
  2986. {
  2987. sDomCache.SzOfBlock =
  2988. pNames->EntriesRead * sizeof(WINSINTF_BROWSER_INFO_T);
  2989. // sDomCache.pInfo = midl_user_allocate(sDomCache.SzOfBlock);
  2990. // WINSMSC_COPY_MEMORY_M(sDomCache.pInfo, pNames->pInfo,
  2991. // sDomCache.SzOfBlock);
  2992. sDomCache.pInfo = pNames->pInfo;
  2993. sDomCache.EntriesRead = pNames->EntriesRead;
  2994. }
  2995. else
  2996. {
  2997. //
  2998. // We did not get anything from the db
  2999. //
  3000. sDomCache.SzOfBlock = 0;
  3001. pNames->EntriesRead = 0;
  3002. pNames->pInfo = NULL;
  3003. }
  3004. }
  3005. else
  3006. {
  3007. //
  3008. // Use the cached info.
  3009. //
  3010. //pNames->pInfo = midl_user_allocate(sDomCache.SzOfBlock);
  3011. //WINSMSC_COPY_MEMORY_M(pNames->pInfo, sDomCache.pInfo,
  3012. // sDomCache.SzOfBlock);
  3013. pNames->pInfo = sDomCache.pInfo;
  3014. pNames->EntriesRead = sDomCache.EntriesRead;
  3015. }
  3016. }
  3017. except(EXCEPTION_EXECUTE_HANDLER) {
  3018. DBGPRINTEXC("WinsGetBrowserNames");
  3019. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_BROWSER_NAME_EXC);
  3020. pNames->EntriesRead = 0;
  3021. pNames->pInfo = NULL;
  3022. RetVal = WINSINTF_FAILURE;
  3023. }
  3024. return(RetVal);
  3025. }
  3026. VOID
  3027. R_WinsGetBrowserNames_notify_flag(boolean __MIDL_NotifyFlag
  3028. )
  3029. /*++
  3030. Routine Description:
  3031. Called by rpc to indicate that it is done with the buffer returned by
  3032. WinsGetBrowserNames
  3033. Arguments:
  3034. Externals Used:
  3035. None
  3036. Return Value:
  3037. Success status codes --
  3038. Error status codes --
  3039. Error Handling:
  3040. Called by:
  3041. Side Effects:
  3042. Comments:
  3043. None
  3044. --*/
  3045. {
  3046. //
  3047. // Decrement the user count. If equal to 0, signal the event to let
  3048. // another thread go on.
  3049. //
  3050. EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
  3051. //
  3052. // workaround an rpc bug (18627) where it may call notify without calling
  3053. // R_WinsGetBrowserNames (checkout winsif_s.c)
  3054. //
  3055. if (
  3056. (sDomCache.NoOfUsers > 0) &&
  3057. (--sDomCache.NoOfUsers == 0) &&
  3058. sDomCache.EvtHdl != NULL
  3059. )
  3060. {
  3061. WinsMscSignalHdl(sDomCache.EvtHdl);
  3062. }
  3063. LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
  3064. return;
  3065. }
  3066. DWORD
  3067. WinsDeleteWins(
  3068. PWINSINTF_ADD_T pWinsAdd
  3069. )
  3070. {
  3071. PCOMM_ADD_T pAdd;
  3072. DWORD RetVal = WINSINTF_FAILURE;
  3073. if (pWinsAdd->IPAdd == NmsLocalAdd.Add.IPAdd)
  3074. {
  3075. WINSINTF_VERS_NO_T MinVersNo = {0};
  3076. WINSINTF_VERS_NO_T MaxVersNo = {0};
  3077. RetVal = WinsDelDbRecs(pWinsAdd, MinVersNo, MaxVersNo);
  3078. #if 0
  3079. //
  3080. // We always keep the entry for the local WINS. For any
  3081. //
  3082. DBGPRINT0(ERR, "WinsDeleteWins: Sorry, you can not delete the entry for the local WINS\n");
  3083. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_DELETE_LOCAL_WINS_DISALLOWED);
  3084. RetVal = WINSINTF_CAN_NOT_DEL_LOCAL_WINS;
  3085. #endif
  3086. }
  3087. else
  3088. {
  3089. WCHAR String[WINS_MAX_NAME_SZ];
  3090. struct in_addr InAddr;
  3091. InAddr.s_addr = htonl(pWinsAdd->IPAdd);
  3092. (VOID)WinsMscConvertAsciiStringToUnicode(
  3093. inet_ntoa( InAddr),
  3094. (LPBYTE)String,
  3095. WINS_MAX_NAME_SZ);
  3096. WinsLogAdminEvent(WINS_EVT_ADMIN_DEL_OWNER_INITIATED,1,String);
  3097. //
  3098. // Allocate from the general heap (not from the rpc heap)
  3099. // since this memory will be deallocated by DeleteWins in
  3100. // rplpull.c which I don't want to tie to just rpc work.
  3101. //
  3102. WinsMscAlloc(sizeof(COMM_ADD_T), &pAdd);
  3103. pAdd->AddTyp_e = pWinsAdd->Type;
  3104. pAdd->AddLen = pWinsAdd->Len;
  3105. pAdd->Add.IPAdd = pWinsAdd->IPAdd;
  3106. //
  3107. // Call RplInsertQue to insert the push request to
  3108. // the Pull Thread
  3109. //
  3110. ERplInsertQue(
  3111. WINS_E_WINSRPC,
  3112. QUE_E_CMD_DELETE_WINS,
  3113. NULL, //no Dlg Hdl
  3114. NULL, //no msg is there
  3115. 0, //msg length
  3116. pAdd, //client context,
  3117. 0 //no magic no
  3118. );
  3119. RetVal = WINSINTF_SUCCESS;
  3120. }
  3121. return(RetVal);
  3122. }
  3123. #define MAX_RECS_TO_RETURN 5000
  3124. DWORD
  3125. WinsGetDbRecsByName (
  3126. PWINSINTF_ADD_T pWinsAdd,
  3127. DWORD Location,
  3128. LPBYTE pName,
  3129. DWORD NameLen,
  3130. DWORD NoOfRecsDesired,
  3131. DWORD TypeOfRecs,
  3132. PWINSINTF_RECS_T pRecs
  3133. )
  3134. /*++
  3135. Routine Description:
  3136. This function returns with all the records (that can fit into the
  3137. buffer passed) owned by a WINS in the local db of this WINS.
  3138. Arguments:
  3139. Externals Used:
  3140. None
  3141. Return Value:
  3142. Success status codes --
  3143. Error status codes --
  3144. Error Handling:
  3145. Called by:
  3146. Side Effects:
  3147. Comments:
  3148. None
  3149. --*/
  3150. {
  3151. COMM_ADD_T Address;
  3152. LPVOID pBuff = NULL;
  3153. DWORD BuffLen;
  3154. DWORD NoOfRecs = 0;
  3155. DWORD Status;
  3156. PWINSTHD_TLS_T pTls;
  3157. DBGENTER("WinsGetDbRecsByName\n");
  3158. if ((NoOfRecsDesired == 0) || (NoOfRecsDesired > MAX_RECS_TO_RETURN))
  3159. {
  3160. NoOfRecsDesired = MAX_RECS_TO_RETURN;
  3161. }
  3162. if ((pWinsAdd != NULL) && (pWinsAdd->IPAdd != 0))
  3163. {
  3164. Address.AddTyp_e = pWinsAdd->Type;
  3165. Address.AddLen = pWinsAdd->Len;
  3166. Address.Add.IPAdd = pWinsAdd->IPAdd;
  3167. }
  3168. //
  3169. // initialize this thread with the db engine
  3170. //
  3171. NmsDbThdInit(WINS_E_WINSRPC);
  3172. NmsDbOpenTables(WINS_E_WINSRPC);
  3173. DBGMYNAME("RPC-WinsGetDbRecsByName");
  3174. try {
  3175. if ((pName != NULL) && (NameLen != 0))
  3176. {
  3177. //
  3178. // Terminate name with NULL, just in case user didn't do it.
  3179. //
  3180. *(pName + NameLen) = (BYTE)NULL;
  3181. }
  3182. if ((pName == NULL) && (NameLen > 0))
  3183. {
  3184. NameLen = 0;
  3185. }
  3186. PERF("The caller can pass the number of records for which space has been")
  3187. PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
  3188. PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
  3189. PERF("more records than are necessary")
  3190. Status = NmsDbGetDataRecsByName(
  3191. pName,
  3192. NameLen != 0 ? NameLen + 1 : 0,
  3193. Location,
  3194. NoOfRecsDesired,
  3195. pWinsAdd != NULL ? &Address : NULL,
  3196. TypeOfRecs,
  3197. &pBuff,
  3198. &BuffLen,
  3199. &NoOfRecs
  3200. );
  3201. if (Status == WINS_SUCCESS)
  3202. {
  3203. Status = PackageRecs( pBuff, BuffLen, NoOfRecs, pRecs);
  3204. }
  3205. }
  3206. except(EXCEPTION_EXECUTE_HANDLER) {
  3207. DBGPRINTEXC("WinsGetDbRecsByName");
  3208. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  3209. Status = WINS_FAILURE;
  3210. }
  3211. //
  3212. // Free the buffer and destroy the heap.
  3213. //
  3214. GET_TLS_M(pTls);
  3215. if (pTls->HeapHdl != NULL)
  3216. {
  3217. if (pBuff != NULL)
  3218. {
  3219. WinsMscHeapFree(pTls->HeapHdl, pBuff);
  3220. }
  3221. WinsMscHeapDestroy(pTls->HeapHdl);
  3222. // pTls->HeapHdl = NULL;
  3223. }
  3224. //
  3225. // Let us end the session
  3226. //
  3227. NmsDbCloseTables();
  3228. NmsDbEndSession();
  3229. if (Status != WINS_SUCCESS)
  3230. {
  3231. pRecs->pRow = NULL;
  3232. pRecs->NoOfRecs = 0;
  3233. Status = WINSINTF_FAILURE;
  3234. }
  3235. else
  3236. {
  3237. if (pRecs->NoOfRecs == 0)
  3238. {
  3239. pRecs->pRow = NULL;
  3240. pRecs->NoOfRecs = 0;
  3241. Status = WINSINTF_REC_NOT_FOUND;
  3242. }
  3243. }
  3244. DBGLEAVE("WinsGetDbRecsByName\n");
  3245. return (Status);
  3246. }
  3247. STATUS
  3248. PackageRecs(
  3249. PRPL_REC_ENTRY2_T pBuff,
  3250. DWORD BuffLen,
  3251. DWORD NoOfRecs,
  3252. PWINSINTF_RECS_T pRecs
  3253. )
  3254. /*++
  3255. Routine Description:
  3256. Arguments:
  3257. Externals Used:
  3258. None
  3259. Return Value:
  3260. Success status codes --
  3261. Error status codes --
  3262. Error Handling:
  3263. Called by:
  3264. Side Effects:
  3265. Comments:
  3266. None
  3267. --*/
  3268. {
  3269. // ULONG Status;
  3270. BOOL fExcRaised = FALSE;
  3271. PWINSINTF_RECORD_ACTION_T pRow;
  3272. DWORD i;
  3273. DWORD ind;
  3274. DWORD EntType;
  3275. // DWORD MaxAdds;
  3276. PWINSTHD_TLS_T pTls;
  3277. DBGENTER("PackageRecs\n");
  3278. i = 0;
  3279. GET_TLS_M(pTls);
  3280. try {
  3281. //
  3282. // If there are records to send back and the client has specified
  3283. // a buffer for them, insert the records
  3284. //
  3285. if (NoOfRecs > 0)
  3286. {
  3287. //
  3288. // Allocate memory for the no of records
  3289. //
  3290. pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
  3291. //
  3292. // If memory can not be allocate, an exception will be returned
  3293. // by midl_user_alloc
  3294. //
  3295. pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
  3296. #if 0
  3297. pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
  3298. if (Status != RPC_S_OK)
  3299. {
  3300. DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3301. }
  3302. #endif
  3303. pRow = pRecs->pRow;
  3304. for (; i<NoOfRecs; i++)
  3305. {
  3306. //
  3307. // Initialize so that we don't get "enum wrong" error.
  3308. //
  3309. pRow->Cmd_e = WINSINTF_E_QUERY;
  3310. //
  3311. // the name retrieved has NULL as the last character. This
  3312. // We need to pass a name without this NULL.
  3313. //
  3314. pRow->NameLen = pBuff->NameLen;
  3315. if (*pBuff->pName == 0x1B)
  3316. {
  3317. WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
  3318. }
  3319. // +1 added to fix #390830
  3320. pRow->pName = midl_user_allocate(pRow->NameLen + 1);
  3321. #if 0
  3322. pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
  3323. if (Status != RPC_S_OK)
  3324. {
  3325. DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3326. }
  3327. #endif
  3328. WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,pRow->NameLen);
  3329. WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
  3330. EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
  3331. pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
  3332. ? WINSINTF_E_UNIQUE :
  3333. (NMSDB_ENTRY_NORM_GRP_M(EntType) ?
  3334. WINSINTF_E_NORM_GROUP :
  3335. (NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
  3336. WINSINTF_E_SPEC_GROUP :
  3337. WINSINTF_E_MULTIHOMED));
  3338. if (
  3339. (pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
  3340. (pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
  3341. )
  3342. {
  3343. PWINSINTF_ADD_T pAdd;
  3344. DWORD No;
  3345. if (pBuff->NoOfAdds > 0)
  3346. {
  3347. pRow->NoOfAdds = pBuff->NoOfAdds * 2;
  3348. //
  3349. // Each member is comprised of two addresses,
  3350. // first address is that of the owner WINS, second
  3351. // address is that of the node registered
  3352. //
  3353. pRow->pAdd =
  3354. // RpcSmAllocate(
  3355. midl_user_allocate(
  3356. (unsigned int)(pRow->NoOfAdds)
  3357. *
  3358. sizeof(WINSINTF_ADD_T)//,
  3359. // &Status
  3360. );
  3361. #if 0
  3362. if (Status != RPC_S_OK)
  3363. {
  3364. DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
  3365. }
  3366. #endif
  3367. for (
  3368. No= 0, ind= 0, pAdd = pRow->pAdd;
  3369. No < (pRow->NoOfAdds/2);
  3370. No++
  3371. )
  3372. {
  3373. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
  3374. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  3375. pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
  3376. pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
  3377. pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
  3378. pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
  3379. }
  3380. WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
  3381. }
  3382. }
  3383. else
  3384. {
  3385. pRow->NoOfAdds = 0;
  3386. pRow->pAdd = NULL;
  3387. pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
  3388. pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
  3389. pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
  3390. }
  3391. pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
  3392. pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
  3393. pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
  3394. pRow->VersNo = pBuff->VersNo;
  3395. pRow->TimeStamp = pBuff->TimeStamp;
  3396. pRow->OwnerId = pBuff->OwnerId;
  3397. pRow++;
  3398. pBuff = (PRPL_REC_ENTRY2_T)((LPBYTE)pBuff + RPL_REC_ENTRY2_SIZE);
  3399. PERF("Do the addition above the for loop and store in a var. Use var. here")
  3400. } // end of for loop
  3401. } //end of if block
  3402. else
  3403. {
  3404. pRecs->pRow = NULL;
  3405. }
  3406. } // end of try
  3407. except(EXCEPTION_EXECUTE_HANDLER) {
  3408. DBGPRINTEXC("WinsGetDbRecs");
  3409. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
  3410. fExcRaised = TRUE;
  3411. }
  3412. pRecs->TotalNoOfRecs = NoOfRecs;
  3413. if (!fExcRaised)
  3414. {
  3415. pRecs->NoOfRecs = i;
  3416. }
  3417. else
  3418. {
  3419. // RpcSmFree(pRecs->pRow);
  3420. midl_user_free(pRecs->pRow);
  3421. pRecs->NoOfRecs = 0;
  3422. }
  3423. DBGENTER("PackageRecs\n");
  3424. return (WINSINTF_SUCCESS);
  3425. }
  3426. //void __RPC_FAR * __RPC_API
  3427. void *
  3428. midl_user_allocate(size_t cBytes)
  3429. {
  3430. #if 0
  3431. //#ifdef WINSDBG
  3432. LPVOID pMem = WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes);
  3433. DBGPRINT1(DET, "midl_user_alloc: Memory allocated is (%d)\n", pMem);
  3434. return(pMem);
  3435. //#else
  3436. #endif
  3437. return(WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes));
  3438. }
  3439. //void __RPC_FAR __RPC_API
  3440. void
  3441. //midl_user_free(void __RPC_FAR *pMem)
  3442. midl_user_free(void *pMem)
  3443. {
  3444. if (pMem != NULL)
  3445. {
  3446. // DBGPRINT1(DET, "midl_user_free: Memory to free is (%d)\n", pMem);
  3447. WinsMscHeapFree(NmsRpcHeapHdl, pMem);
  3448. }
  3449. return;
  3450. }
  3451. VOID
  3452. LogClientInfo(
  3453. RPC_BINDING_HANDLE ClientHdl,
  3454. BOOL fAbruptTerm
  3455. )
  3456. {
  3457. RPC_STATUS RpcRet;
  3458. RPC_BINDING_HANDLE Binding;
  3459. PTUCHAR pStringBinding;
  3460. PTUCHAR pProtSeq;
  3461. PTUCHAR pNetworkAddress;
  3462. WINSEVT_STRS_T EvtStrs;
  3463. NOTE("remove #if 0 when we go to 540 or above")
  3464. #if 0
  3465. RpcRet = RpcBindingServerFromClient(ClientHdl, &Binding);
  3466. if (RpcRet != RPC_S_OK)
  3467. {
  3468. DBGPRINT1(ERR, "LogClientInfo: Can not get binding handle. Rpc Error = (%d)\nThis could be because named pipe protocol is being used\n", RpcRet);
  3469. Binding = ClientHdl;
  3470. }
  3471. #endif
  3472. NOTE("remove when we go to 540 or above")
  3473. Binding = ClientHdl;
  3474. RpcRet = RpcBindingToStringBinding(Binding, &pStringBinding);
  3475. if (RpcRet != RPC_S_OK)
  3476. {
  3477. DBGPRINT1(ERR, "LogClientInfo: RpcBindingToStringBinding returned error = (%d)\n", RpcRet);
  3478. return;
  3479. }
  3480. RpcRet = RpcStringBindingParse(
  3481. pStringBinding,
  3482. NULL, //don't want uuid
  3483. &pProtSeq,
  3484. &pNetworkAddress,
  3485. NULL, //end point
  3486. NULL //network options
  3487. );
  3488. if (RpcRet != RPC_S_OK)
  3489. {
  3490. DBGPRINT1(ERR, "LogClientInfo: RpcStringBindingParse returned error = (%d)\n", RpcRet);
  3491. RpcStringFree(&pStringBinding);
  3492. return;
  3493. }
  3494. #ifndef UNICODE
  3495. DBGPRINT2(FLOW, "LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
  3496. #else
  3497. #ifdef WINSDBG
  3498. IF_DBG(FLOW)
  3499. {
  3500. wprintf(L"LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
  3501. }
  3502. #endif
  3503. #endif
  3504. RpcStringFree(&pProtSeq);
  3505. RpcStringFree(&pNetworkAddress);
  3506. EvtStrs.NoOfStrs = 1;
  3507. EvtStrs.pStr[0] = (LPTSTR)pNetworkAddress;
  3508. if (fAbruptTerm)
  3509. {
  3510. WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ABRUPT_SHUTDOWN, &EvtStrs);
  3511. }
  3512. else
  3513. {
  3514. WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ORDERLY_SHUTDOWN, &EvtStrs);
  3515. }
  3516. return;
  3517. }