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.

1621 lines
42 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. winsup.cpp
  7. Global functions
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "winssup.h"
  12. #include "tregkey.h"
  13. #include "resource.h"
  14. #include "wins.h"
  15. #include <clusapi.h>
  16. #include "..\tfscore\cluster.h"
  17. const TCHAR g_szPipeName[] = _T("\\pipe\\WinsPipe");
  18. const TCHAR g_szDefaultHelpTopic[] = _T("\\help\\winsconcepts.chm::/sag_WINStopnode.htm");
  19. /*---------------------------------------------------------------------------
  20. SendTrigger()
  21. Sends a pull or push replication trigger to a given wins server
  22. ---------------------------------------------------------------------------*/
  23. DWORD
  24. SendTrigger
  25. (
  26. handle_t hWins,
  27. LONG ipTarget,
  28. BOOL fPush,
  29. BOOL fPropagate
  30. )
  31. {
  32. DWORD dwStatus;
  33. WINSINTF_ADD_T WinsAdd;
  34. WinsAdd.Len = 4;
  35. WinsAdd.Type = 0;
  36. WinsAdd.IPAdd = ipTarget;
  37. WINSINTF_TRIG_TYPE_E TrigType;
  38. TrigType = fPush ? (fPropagate ? WINSINTF_E_PUSH_PROP : WINSINTF_E_PUSH) : WINSINTF_E_PULL;
  39. #ifdef WINS_CLIENT_APIS
  40. dwStatus = ::WinsTrigger(hWins,
  41. &WinsAdd,
  42. TrigType);
  43. #else
  44. dwStatus = ::WinsTrigger(&WinsAdd,
  45. TrigType);
  46. #endif WINS_CLIENT_APIS
  47. return dwStatus;
  48. }
  49. /*---------------------------------------------------------------------------
  50. ControlWINSService(LPCTSTR pszName, BOOL bStop)
  51. Stops ot starts the WINS service on the local machine
  52. ---------------------------------------------------------------------------*/
  53. DWORD ControlWINSService(LPCTSTR pszName, BOOL bStop)
  54. {
  55. DWORD dwState = bStop ? SERVICE_STOPPED : SERVICE_RUNNING;
  56. DWORD dwPending = bStop ? SERVICE_STOP_PENDING : SERVICE_START_PENDING;
  57. DWORD err = ERROR_SUCCESS;
  58. int i;
  59. SERVICE_STATUS ss;
  60. DWORD dwControl;
  61. BOOL fSuccess;
  62. SC_HANDLE hService = NULL;
  63. SC_HANDLE hScManager = NULL;
  64. // oepmnt he service control manager
  65. hScManager = ::OpenSCManager(pszName, NULL, SC_MANAGER_ALL_ACCESS);
  66. if (hScManager == NULL)
  67. {
  68. err = ::GetLastError();
  69. Trace1("ControlWINSService - OpenScManager failed! %d\n", err);
  70. goto Error;
  71. }
  72. // get the handle to the WINS service
  73. hService = OpenService(hScManager, _T("WINS"), SERVICE_ALL_ACCESS);
  74. if (hService == NULL)
  75. {
  76. err = ::GetLastError();
  77. Trace1("ControlWINSService - OpenService failed! %d\n", err);
  78. goto Error;
  79. }
  80. // if stop requested
  81. if (bStop)
  82. {
  83. dwControl = SERVICE_CONTROL_STOP;
  84. fSuccess = ::ControlService(hService, dwControl, &ss);
  85. if (!fSuccess)
  86. {
  87. err = ::GetLastError();
  88. Trace1("ControlWINSService - ControlService failed! %d\n", err);
  89. goto Error;
  90. }
  91. }
  92. // otherwise start the service
  93. else
  94. {
  95. fSuccess = ::StartService(hService, 0, NULL);
  96. if (!fSuccess)
  97. {
  98. err = ::GetLastError();
  99. Trace1("ControlWINSService - StartService failed! %d\n", err);
  100. goto Error;
  101. }
  102. }
  103. #define LOOP_TIME 5000
  104. #define NUM_LOOPS 600
  105. // wait for the service to start/stop.
  106. for (i = 0; i < NUM_LOOPS; i++)
  107. {
  108. ::QueryServiceStatus(hService, &ss);
  109. // check to see if we are done
  110. if (ss.dwCurrentState == dwState)
  111. {
  112. int time = LOOP_TIME * i;
  113. Trace1("ControlWINSService - service stopped/started in approx %d ms!\n", time);
  114. break;
  115. }
  116. // now see if something bad happened
  117. if (ss.dwCurrentState != dwPending)
  118. {
  119. int time = LOOP_TIME * i;
  120. Trace1("ControlWINSService - service stop/start failed in approx %d ms!\n", time);
  121. break;
  122. }
  123. Sleep(LOOP_TIME);
  124. }
  125. if (i == NUM_LOOPS)
  126. Trace0("ControlWINSService - service did NOT stop/start in wait period!\n");
  127. if (ss.dwCurrentState != dwState)
  128. err = ERROR_SERVICE_REQUEST_TIMEOUT;
  129. Error:
  130. // close the respective handles
  131. if (hService)
  132. ::CloseServiceHandle(hService);
  133. if (hScManager)
  134. ::CloseServiceHandle(hScManager);
  135. return err;
  136. }
  137. /*---------------------------------------------------------------------------
  138. GetNameIP( const CString &strDisplay,
  139. CString &strName,
  140. CString &strIP)
  141. Returns the Server name and the IP Address string with the
  142. group name
  143. ---------------------------------------------------------------------------*/
  144. void
  145. GetNameIP
  146. (
  147. const CString &strDisplay,
  148. CString &strName,
  149. CString &strIP
  150. )
  151. {
  152. CString strTemp = strDisplay;
  153. // find '['
  154. int nPos = strDisplay.Find(_T("["));
  155. // left of the positioncontains the name and right of it has the IP address
  156. // 1 to take care of the space before '['
  157. strName = strDisplay.Left(nPos-1);
  158. strIP = strDisplay.Right(strDisplay.GetLength() - nPos);
  159. // take out '[' and ']' in strIP
  160. int npos1 = strIP.Find(_T("["));
  161. int npos2 = strIP.Find(_T("]"));
  162. strIP = strIP.Mid(npos1+1, npos2-npos1-1);
  163. return;
  164. }
  165. /*---------------------------------------------------------------------------
  166. WideToMBCS()
  167. converts WCS to MBCS string
  168. NOTE: the caller of this function must make sure that szOut is big
  169. enough to hold any possible string in strIn.
  170. ---------------------------------------------------------------------------*/
  171. DWORD
  172. WideToMBCS(CString & strIn, LPSTR szOut, UINT uCodePage, DWORD dwFlags, BOOL * pfDefaultUsed)
  173. {
  174. DWORD dwErr = ERROR_SUCCESS;
  175. BOOL fDefaultCharUsed = FALSE;
  176. int nNumBytes = ::WideCharToMultiByte(uCodePage,
  177. dwFlags,
  178. strIn,
  179. -1,
  180. szOut,
  181. 0,
  182. NULL,
  183. &fDefaultCharUsed);
  184. dwErr = ::WideCharToMultiByte(uCodePage,
  185. dwFlags,
  186. strIn,
  187. -1,
  188. szOut,
  189. nNumBytes,
  190. NULL,
  191. &fDefaultCharUsed);
  192. szOut[nNumBytes] = '\0';
  193. if (pfDefaultUsed)
  194. *pfDefaultUsed = fDefaultCharUsed;
  195. return dwErr;
  196. }
  197. /*---------------------------------------------------------------------------
  198. MBCSToWide ()
  199. converts MBCS to Wide string
  200. ---------------------------------------------------------------------------*/
  201. DWORD
  202. MBCSToWide(LPSTR szIn, CString & strOut, UINT uCodePage, DWORD dwFlags)
  203. {
  204. DWORD dwErr = ERROR_SUCCESS;
  205. LPTSTR pBuf = strOut.GetBuffer(MAX_PATH * 2);
  206. ZeroMemory(pBuf, MAX_PATH * 2);
  207. dwErr = ::MultiByteToWideChar(uCodePage,
  208. dwFlags,
  209. szIn,
  210. -1,
  211. pBuf,
  212. MAX_PATH * 2);
  213. strOut.ReleaseBuffer();
  214. return dwErr;
  215. }
  216. LONG
  217. GetSystemMessageA
  218. (
  219. UINT nId,
  220. CHAR * chBuffer,
  221. int cbBuffSize
  222. )
  223. {
  224. CHAR * pszText = NULL ;
  225. HINSTANCE hdll = NULL ;
  226. DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS
  227. | FORMAT_MESSAGE_MAX_WIDTH_MASK;
  228. //
  229. // Interpret the error. Need to special case
  230. // the lmerr & ntstatus ranges, as well as
  231. // WINS server error messages.
  232. //
  233. if( nId >= NERR_BASE && nId <= MAX_NERR )
  234. {
  235. hdll = LoadLibrary( _T("netmsg.dll") );
  236. }
  237. else
  238. if( nId >= 0x40000000L )
  239. {
  240. hdll = LoadLibrary( _T("ntdll.dll") );
  241. }
  242. if( hdll == NULL )
  243. {
  244. flags |= FORMAT_MESSAGE_FROM_SYSTEM;
  245. }
  246. else
  247. {
  248. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  249. }
  250. //
  251. // Let FormatMessage do the dirty work.
  252. //
  253. DWORD dwResult = ::FormatMessageA( flags,
  254. (LPVOID) hdll,
  255. nId,
  256. 0,
  257. chBuffer,
  258. cbBuffSize,
  259. NULL ) ;
  260. if( hdll != NULL )
  261. {
  262. LONG err = GetLastError();
  263. FreeLibrary( hdll );
  264. if ( dwResult == 0 )
  265. {
  266. ::SetLastError( err );
  267. }
  268. }
  269. return dwResult ? ERROR_SUCCESS : ::GetLastError() ;
  270. }
  271. LONG
  272. GetSystemMessage
  273. (
  274. UINT nId,
  275. TCHAR * chBuffer,
  276. int cbBuffSize
  277. )
  278. {
  279. TCHAR * pszText = NULL ;
  280. HINSTANCE hdll = NULL ;
  281. DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS
  282. | FORMAT_MESSAGE_MAX_WIDTH_MASK;
  283. //
  284. // Interpret the error. Need to special case
  285. // the lmerr & ntstatus ranges, as well as
  286. // WINS server error messages.
  287. //
  288. if( nId >= NERR_BASE && nId <= MAX_NERR )
  289. {
  290. hdll = LoadLibrary( _T("netmsg.dll") );
  291. }
  292. else
  293. if( nId >= 0x40000000L )
  294. {
  295. hdll = LoadLibrary( _T("ntdll.dll") );
  296. }
  297. if( hdll == NULL )
  298. {
  299. flags |= FORMAT_MESSAGE_FROM_SYSTEM;
  300. }
  301. else
  302. {
  303. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  304. }
  305. //
  306. // Let FormatMessage do the dirty work.
  307. //
  308. DWORD dwResult = ::FormatMessage( flags,
  309. (LPVOID) hdll,
  310. nId,
  311. 0,
  312. chBuffer,
  313. cbBuffSize,
  314. NULL ) ;
  315. if( hdll != NULL )
  316. {
  317. LONG err = GetLastError();
  318. FreeLibrary( hdll );
  319. if ( dwResult == 0 )
  320. {
  321. ::SetLastError( err );
  322. }
  323. }
  324. return dwResult ? ERROR_SUCCESS : ::GetLastError() ;
  325. }
  326. /*!--------------------------------------------------------------------------
  327. LoadMessage
  328. Loads the error message from the correct DLL.
  329. Author: EricDav
  330. ---------------------------------------------------------------------------*/
  331. BOOL
  332. LoadMessage
  333. (
  334. UINT nIdPrompt,
  335. TCHAR * chMsg,
  336. int nMsgSize
  337. )
  338. {
  339. BOOL bOk;
  340. //
  341. // Substitute a friendly message for "RPC server not
  342. // available" and "No more endpoints available from
  343. // the endpoint mapper".
  344. //
  345. if (nIdPrompt == EPT_S_NOT_REGISTERED ||
  346. nIdPrompt == RPC_S_SERVER_UNAVAILABLE)
  347. {
  348. nIdPrompt = IDS_ERR_WINS_DOWN;
  349. }
  350. //
  351. // If it's a socket error or our error, the text is in our resource fork.
  352. // Otherwise, use FormatMessage() and the appropriate DLL.
  353. //
  354. if ( (nIdPrompt >= IDS_ERR_BASE && nIdPrompt < IDS_MSG_LAST) )
  355. {
  356. //
  357. // It's in our resource fork
  358. //
  359. bOk = ::LoadString( AfxGetInstanceHandle(), nIdPrompt, chMsg, nMsgSize / sizeof(TCHAR) ) != 0 ;
  360. }
  361. else
  362. {
  363. //
  364. // It's in the system somewhere.
  365. //
  366. bOk = GetSystemMessage( nIdPrompt, chMsg, nMsgSize ) == 0 ;
  367. }
  368. if (bOk && nIdPrompt == ERROR_ACCESS_DENIED)
  369. {
  370. // tack on our extra help to explain different acess levels
  371. CString strAccessDeniedHelp;
  372. strAccessDeniedHelp.LoadString(IDS_ACCESS_DENIED_HELP);
  373. lstrcat(chMsg, _T("\n\n"));
  374. lstrcat(chMsg, strAccessDeniedHelp);
  375. }
  376. //
  377. // If the error message did not compute, replace it.
  378. //
  379. if ( ! bOk )
  380. {
  381. TCHAR chBuff [STRING_LENGTH_MAX] ;
  382. static const TCHAR * pszReplacement = _T("System Error: %ld");
  383. const TCHAR * pszMsg = pszReplacement ;
  384. //
  385. // Try to load the generic (translatable) error message text
  386. //
  387. if ( ::LoadString( AfxGetInstanceHandle(), IDS_ERR_MESSAGE_GENERIC,
  388. chBuff, STRING_LENGTH_MAX ) != 0 )
  389. {
  390. pszMsg = chBuff ;
  391. }
  392. ::wsprintf( chMsg, pszMsg, nIdPrompt ) ;
  393. }
  394. return bOk;
  395. }
  396. /*!--------------------------------------------------------------------------
  397. WinsMessageBox
  398. Puts up a message box with the corresponding error text.
  399. Author: EricDav
  400. ---------------------------------------------------------------------------*/
  401. int WinsMessageBox(UINT nIdPrompt,
  402. UINT nType ,
  403. const TCHAR * pszSuffixString,
  404. UINT nHelpContext)
  405. {
  406. TCHAR chMesg [4000] ;
  407. BOOL bOk ;
  408. CThemeContextActivator themeActivator;
  409. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  410. if ( pszSuffixString )
  411. {
  412. ::lstrcat( chMesg, _T(" ") ) ;
  413. ::lstrcat( chMesg, pszSuffixString ) ;
  414. }
  415. return ::AfxMessageBox( chMesg, nType, nHelpContext ) ;
  416. }
  417. /*!--------------------------------------------------------------------------
  418. WinsMessageBoxEx
  419. Puts up a message box with the corresponding error text.
  420. Author: EricDav
  421. ---------------------------------------------------------------------------*/
  422. int
  423. WinsMessageBoxEx
  424. (
  425. UINT nIdPrompt,
  426. LPCTSTR pszPrefixMessage,
  427. UINT nType,
  428. UINT nHelpContext
  429. )
  430. {
  431. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  432. TCHAR chMesg[4000];
  433. CString strMessage;
  434. BOOL bOk;
  435. CThemeContextActivator themeActivator;
  436. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  437. if ( pszPrefixMessage )
  438. {
  439. strMessage = pszPrefixMessage;
  440. strMessage += _T("\n");
  441. strMessage += _T("\n");
  442. strMessage += chMesg;
  443. }
  444. else
  445. {
  446. strMessage = chMesg;
  447. }
  448. return AfxMessageBox(strMessage, nType, nHelpContext);
  449. }
  450. // class NameTypeMapping handlers
  451. /*!--------------------------------------------------------------------------
  452. MapDWORDToCString
  453. Generic mapping of a DWORD to a CString.
  454. dwNameType is the 16th byte of the name.
  455. dwWinsType is Unique, multihomed, group, etc...
  456. Author: KennT
  457. ---------------------------------------------------------------------------*/
  458. void MapDWORDToCString(DWORD dwNameType, DWORD dwWinsType, const CStringMapArray * pMap, CString & strName)
  459. {
  460. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  461. CStringMapEntry mapEntry;
  462. for (int i = 0; i < pMap->GetSize(); i++)
  463. {
  464. mapEntry = pMap->GetAt(i);
  465. // break out if this is the correct type and the wins type
  466. // matches or is a don't care
  467. if ( (mapEntry.dwNameType == dwNameType) &&
  468. ( (mapEntry.dwWinsType == -1) ||
  469. (mapEntry.dwWinsType == dwWinsType) ) )
  470. {
  471. break;
  472. }
  473. mapEntry.dwNameType = 0xFFFFFFFF;
  474. }
  475. if (mapEntry.dwNameType == 0xFFFFFFFF)
  476. {
  477. MapDWORDToCString(NAME_TYPE_OTHER, dwWinsType, pMap, strName);
  478. }
  479. else
  480. {
  481. if (mapEntry.st.IsEmpty())
  482. Verify(pMap->GetAt(i).st.LoadString(mapEntry.ulStringId));
  483. strName = pMap->GetAt(i).st;
  484. }
  485. }
  486. // this structure allows us to map name types to strings. The secondary
  487. // check is based on the wins defined record type. In order for this to work
  488. // correctly, place any names that need to be defined with the wins type before
  489. // the entry with the wins type set to -1.
  490. static const UINT s_NameTypeMappingDefault[NUM_DEFAULT_NAME_TYPES][3] =
  491. {
  492. { NAME_TYPE_WORKSTATION, WINSINTF_E_NORM_GROUP, IDS_NAMETYPE_MAP_WORKGROUP },
  493. { NAME_TYPE_WORKSTATION, -1, IDS_NAMETYPE_MAP_WORKSTATION },
  494. { NAME_TYPE_DC, -1, IDS_NAMETYPE_MAP_DC },
  495. { NAME_TYPE_FILE_SERVER, WINSINTF_E_SPEC_GROUP, IDS_NAMETYPE_MAP_SPECIAL_INTERNET_GROUP },
  496. { NAME_TYPE_FILE_SERVER, -1, IDS_NAMETYPE_MAP_FILE_SERVER },
  497. { NAME_TYPE_DMB , -1, IDS_NAMETYPE_MAP_DMB },
  498. { NAME_TYPE_OTHER, -1, IDS_NAMETYPE_MAP_OTHER },
  499. { NAME_TYPE_NETDDE, -1, IDS_NAMETYPE_MAP_NETDDE },
  500. { NAME_TYPE_MESSENGER, -1, IDS_NAMETYPE_MAP_MESSENGER },
  501. { NAME_TYPE_RAS_SERVER, -1, IDS_NAMETYPE_MAP_RAS_SERVER },
  502. { NAME_TYPE_NORM_GRP_NAME, -1, IDS_NAMETYPE_MAP_NORMAL_GROUP_NAME },
  503. { NAME_TYPE_WORK_NW_MON_AGENT, -1, IDS_NAMETYPE_MAP_NW_MON_AGENT },
  504. { NAME_TYPE_WORK_NW_MON_NAME, -1, IDS_NAMETYPE_MAP_NMN},
  505. };
  506. const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szNameTypeMapKey = _T("SYSTEM\\CurrentControlSet\\Services\\wins\\NameTypeMap");
  507. const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szDefault= _T("(Default)");
  508. NameTypeMapping ::NameTypeMapping()
  509. {
  510. }
  511. NameTypeMapping ::~NameTypeMapping()
  512. {
  513. Unload();
  514. }
  515. void
  516. NameTypeMapping ::SetMachineName(LPCTSTR pszMachineName)
  517. {
  518. m_strMachineName = pszMachineName;
  519. }
  520. HRESULT NameTypeMapping::Load()
  521. {
  522. HRESULT hr = hrOK;
  523. RegKey regkey;
  524. RegKey regkeyMachine;
  525. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  526. RegKey::CREGKEY_KEY_INFO regkeyInfo;
  527. RegKeyIterator regkeyIter;
  528. UINT i;
  529. WORD langID;
  530. RegKey regkeyProto;
  531. DWORD dwErr;
  532. CStringMapEntry mapEntry;
  533. ::ZeroMemory(&regkeyInfo, sizeof(regkeyInfo));
  534. // Look for the registry key
  535. if (FHrSucceeded(hr))
  536. {
  537. DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ;
  538. hr = HRESULT_FROM_WIN32( dwErr );
  539. }
  540. // Get the count of items
  541. if (FHrSucceeded(hr))
  542. {
  543. DWORD dwErr = regkey.QueryKeyInfo(&regkeyInfo) ;
  544. hr = HRESULT_FROM_WIN32( dwErr );
  545. }
  546. // Alloc the array for the count of items + default items
  547. Unload();
  548. // Read in the registry data and add it to the internal array
  549. //
  550. // enumerate the keys
  551. //
  552. if (FHrSucceeded(hr))
  553. hr = regkeyIter.Init(&regkey);
  554. if (FHrSucceeded(hr))
  555. {
  556. HRESULT hrIter;
  557. DWORD dwProtoId;
  558. CString stKey;
  559. CString stLang;
  560. // Now that we have this key, look for the language id
  561. langID = GetUserDefaultLangID();
  562. stLang.Format(_T("%04x"), (DWORD)langID);
  563. for (hrIter = regkeyIter.Next(&stKey, NULL); hrIter == hrOK; hrIter = regkeyIter.Next(&stKey, NULL))
  564. {
  565. CString st;
  566. // Given the name of the key, that is a hex value (the protocol id)
  567. // Convert that into a DWORD
  568. dwProtoId = _tcstoul((LPCTSTR) stKey, NULL, 16);
  569. // Open this key
  570. regkeyProto.Close();
  571. dwErr = regkeyProto.Open(regkey, stKey);
  572. if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  573. continue;
  574. // Ok, get the name value
  575. dwErr = regkeyProto.QueryValue(stLang, st);
  576. if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  577. {
  578. // Look for the key with the name of default
  579. dwErr = regkeyProto.QueryValue(c_szDefault, st);
  580. }
  581. if (FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  582. {
  583. // Ok, add this value to the list
  584. mapEntry.dwNameType = dwProtoId;
  585. mapEntry.st = st;
  586. mapEntry.ulStringId = 0;
  587. Add(mapEntry);
  588. }
  589. }
  590. }
  591. // Read in the default item data and add it to the array
  592. for (i = 0; i < DimensionOf(s_NameTypeMappingDefault); i++)
  593. {
  594. mapEntry.dwNameType = s_NameTypeMappingDefault[i][0];
  595. mapEntry.dwWinsType = s_NameTypeMappingDefault[i][1];
  596. mapEntry.st.LoadString(s_NameTypeMappingDefault[i][2]);
  597. mapEntry.ulStringId = 0;
  598. Add(mapEntry);
  599. }
  600. return hrOK;
  601. }
  602. void NameTypeMapping::Unload()
  603. {
  604. RemoveAll();
  605. }
  606. void NameTypeMapping::TypeToCString(DWORD dwProtocolId, DWORD dwRecordType, CString & strName)
  607. {
  608. MapDWORDToCString(dwProtocolId, dwRecordType, this, strName);
  609. }
  610. // add in the new id/name
  611. HRESULT NameTypeMapping::AddEntry(DWORD dwProtocolId, LPCTSTR pstrName)
  612. {
  613. HRESULT hr = hrOK;
  614. RegKey regkey;
  615. RegKey regkeyID;
  616. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  617. WORD langID;
  618. CStringMapEntry mapEntry;
  619. CString stID, stLang, stNew;
  620. // Look for the registry key
  621. if (FHrSucceeded(hr))
  622. {
  623. DWORD dwErr = regkey.Create(hkeyMachine, c_szNameTypeMapKey, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) ;
  624. hr = HRESULT_FROM_WIN32( dwErr );
  625. }
  626. // build our new ID string
  627. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  628. // Now that we have this key, look for the language id
  629. langID = GetUserDefaultLangID();
  630. stLang.Format(_T("%04x"), (DWORD)langID);
  631. stNew = c_szNameTypeMapKey + _T("\\") + stID;
  632. // create the ID key
  633. if (FHrSucceeded(hr))
  634. {
  635. DWORD dwErr = regkeyID.Create(hkeyMachine, stNew, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) ;
  636. hr = HRESULT_FROM_WIN32( dwErr );
  637. }
  638. // set the name value
  639. if (FHrSucceeded(hr))
  640. {
  641. DWORD dwErr = regkeyID.SetValue(stLang, pstrName) ;
  642. hr = HRESULT_FROM_WIN32( dwErr );
  643. }
  644. if (FHrSucceeded(hr))
  645. {
  646. // add to internal list
  647. mapEntry.dwNameType = dwProtocolId;
  648. mapEntry.st = pstrName;
  649. mapEntry.ulStringId = 0;
  650. Add(mapEntry);
  651. }
  652. return hr;
  653. }
  654. // modify the given ID's string name
  655. HRESULT NameTypeMapping::ModifyEntry(DWORD dwProtocolId, LPCTSTR pstrName)
  656. {
  657. HRESULT hr = hrOK;
  658. RegKey regkey;
  659. RegKey regkeyID;
  660. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  661. int i;
  662. WORD langID;
  663. CString stID, stLang, stNew;
  664. // Look for the registry key
  665. if (FHrSucceeded(hr))
  666. {
  667. DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ;
  668. hr = HRESULT_FROM_WIN32( dwErr );
  669. }
  670. // build our new ID string
  671. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  672. stNew = c_szNameTypeMapKey + _T("\\") + stID;
  673. // open the correct ID key
  674. if (FHrSucceeded(hr))
  675. {
  676. DWORD dwErr = regkeyID.Open(hkeyMachine, stNew, KEY_ALL_ACCESS, m_strMachineName) ;
  677. hr = HRESULT_FROM_WIN32( dwErr );
  678. }
  679. // Now that we have this key, look for the language id
  680. langID = GetUserDefaultLangID();
  681. stLang.Format(_T("%04x"), (DWORD)langID);
  682. // set the new value
  683. if (FHrSucceeded(hr))
  684. {
  685. DWORD dwErr = regkeyID.SetValue(stLang, pstrName) ;
  686. hr = HRESULT_FROM_WIN32( dwErr );
  687. }
  688. if (FHrSucceeded(hr))
  689. {
  690. // modify the internal list
  691. for (i = 0; i < GetSize(); i++)
  692. {
  693. if (GetAt(i).dwNameType == dwProtocolId)
  694. {
  695. m_pData[i].st = pstrName;
  696. break;
  697. }
  698. }
  699. }
  700. return hr;
  701. }
  702. // remove the given ID's string name
  703. HRESULT NameTypeMapping::RemoveEntry(DWORD dwProtocolId)
  704. {
  705. HRESULT hr = hrOK;
  706. RegKey regkey;
  707. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  708. int i;
  709. CString stID;
  710. // Look for the registry key
  711. if (FHrSucceeded(hr))
  712. {
  713. DWORD dwErr = regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) ;
  714. hr = HRESULT_FROM_WIN32( dwErr );
  715. }
  716. // build our new ID string
  717. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  718. // set the new value
  719. if (FHrSucceeded(hr))
  720. {
  721. DWORD dwErr = regkey.RecurseDeleteKey(stID) ;
  722. hr = HRESULT_FROM_WIN32( dwErr );
  723. }
  724. if (FHrSucceeded(hr))
  725. {
  726. // modify the internal list
  727. for (i = 0; i < GetSize(); i++)
  728. {
  729. if (GetAt(i).dwNameType == dwProtocolId)
  730. {
  731. RemoveAt(i);
  732. break;
  733. }
  734. }
  735. }
  736. return hr;
  737. }
  738. BOOL
  739. NameTypeMapping::EntryExists(DWORD dwProtocolId)
  740. {
  741. BOOL fExists = FALSE;
  742. for (int i = 0; i < GetSize(); i++)
  743. {
  744. if (GetAt(i).dwNameType == dwProtocolId)
  745. {
  746. fExists = TRUE;
  747. break;
  748. }
  749. }
  750. return fExists;
  751. }
  752. /*---------------------------------------------------------------------------
  753. CleanString(CString& str)
  754. Strip leading and trailing spaces from the string.
  755. ---------------------------------------------------------------------------*/
  756. CString&
  757. CleanString(
  758. CString& str
  759. )
  760. {
  761. if (str.IsEmpty())
  762. {
  763. return str ;
  764. }
  765. int n = 0;
  766. while ((n < str.GetLength()) && (str[n] == ' '))
  767. {
  768. ++n;
  769. }
  770. if (n)
  771. {
  772. str = str.Mid(n);
  773. }
  774. n = str.GetLength();
  775. while (n && (str[--n] == ' '))
  776. {
  777. str.ReleaseBuffer(n);
  778. }
  779. return str;
  780. }
  781. /*---------------------------------------------------------------------------
  782. IsValidNetBIOSName
  783. Determine if the given netbios is valid, and pre-pend
  784. a double backslash if not already present (and the address
  785. is otherwise valid).
  786. ---------------------------------------------------------------------------*/
  787. BOOL
  788. IsValidNetBIOSName(
  789. CString & strAddress,
  790. BOOL fLanmanCompatible,
  791. BOOL fWackwack // expand slashes if not present
  792. )
  793. {
  794. TCHAR szWacks[] = _T("\\\\");
  795. if (strAddress.IsEmpty())
  796. {
  797. return FALSE;
  798. }
  799. if (strAddress[0] == _T('\\'))
  800. {
  801. if (strAddress.GetLength() < 3)
  802. {
  803. return FALSE;
  804. }
  805. if (strAddress[1] != _T('\\'))
  806. {
  807. // One slash only? Not valid
  808. return FALSE;
  809. }
  810. }
  811. else
  812. {
  813. if (fWackwack)
  814. {
  815. // Add the backslashes
  816. strAddress = szWacks + strAddress;
  817. }
  818. }
  819. int nMaxAllowedLength = fLanmanCompatible
  820. ? LM_NAME_MAX_LENGTH
  821. : NB_NAME_MAX_LENGTH;
  822. if (fLanmanCompatible)
  823. {
  824. strAddress.MakeUpper();
  825. }
  826. return strAddress.GetLength() <= nMaxAllowedLength + 2;
  827. }
  828. /*---------------------------------------------------------------------------
  829. IsValidDomain
  830. Determine if the given domain name address is valid, and clean
  831. it up, if necessary
  832. ---------------------------------------------------------------------------*/
  833. BOOL
  834. IsValidDomain(CString & strDomain)
  835. {
  836. /* int nLen;
  837. if ((nLen = strDomain.GetLength()) != 0)
  838. {
  839. if (nLen < DOMAINNAME_LENGTH) // 255
  840. {
  841. int i;
  842. int istr = 0;
  843. TCHAR ch;
  844. BOOL fLet_Dig = FALSE;
  845. BOOL fDot = FALSE;
  846. int cHostname = 0;
  847. for (i = 0; i < nLen; i++)
  848. {
  849. // check each character
  850. ch = strDomain[i];
  851. BOOL fAlNum = iswalpha(ch) || iswdigit(ch);
  852. if (((i == 0) && !fAlNum) ||
  853. // first letter must be a digit or a letter
  854. (fDot && !fAlNum) ||
  855. // first letter after dot must be a digit or a letter
  856. ((i == (nLen - 1)) && !fAlNum) ||
  857. // last letter must be a letter or a digit
  858. (!fAlNum && ( ch != _T('-') && ( ch != _T('.') && ( ch != _T('_'))))) ||
  859. // must be letter, digit, - or "."
  860. (( ch == _T('.')) && ( !fLet_Dig )))
  861. // must be letter or digit before '.'
  862. {
  863. return FALSE;
  864. }
  865. fLet_Dig = fAlNum;
  866. fDot = (ch == _T('.'));
  867. cHostname++;
  868. if ( cHostname > HOSTNAME_LENGTH )
  869. {
  870. return FALSE;
  871. }
  872. if ( fDot )
  873. {
  874. cHostname = 0;
  875. }
  876. }
  877. }
  878. }
  879. */
  880. return TRUE;
  881. }
  882. /*---------------------------------------------------------------------------
  883. IsValidIpAddress
  884. Determine if the given IP address is valid, and clean
  885. it up, if necessary
  886. ---------------------------------------------------------------------------*/
  887. BOOL
  888. IsValidIpAddress(CString & strAddress)
  889. {
  890. if (strAddress.IsEmpty())
  891. {
  892. return FALSE;
  893. }
  894. CIpAddress ia(strAddress);
  895. BOOL fValid = ia.IsValid();
  896. if (fValid)
  897. {
  898. // Fill out the IP address string for clarity
  899. strAddress = ia;
  900. return TRUE;
  901. }
  902. return FALSE;
  903. }
  904. /*---------------------------------------------------------------------------
  905. IsValidAddress
  906. Determine if the given address is a valid NetBIOS or
  907. TCP/IP address, judging by the name only. Note that
  908. validation may clean up the given string
  909. NetBIOS names not beginning with "\\" will have those characters
  910. pre-pended, and otherwise valid IP Addresses are filled out to
  911. 4 octets.
  912. Leading and trailing spaces are removed from the string.
  913. --------------------------------------------------------------------------*/
  914. BOOL
  915. IsValidAddress(
  916. CString& strAddress,
  917. BOOL * fIpAddress,
  918. BOOL fLanmanCompatible,
  919. BOOL fWackwack // expand netbios slashes
  920. )
  921. {
  922. int i;
  923. // Remove leading and trailing spaces
  924. CleanString(strAddress);
  925. if (strAddress.IsEmpty()) {
  926. *fIpAddress = FALSE;
  927. return FALSE;
  928. }
  929. if (strAddress[0] == _T('\\')) {
  930. *fIpAddress = FALSE;
  931. return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
  932. }
  933. if (IsValidIpAddress(strAddress))
  934. {
  935. *fIpAddress = TRUE;
  936. return TRUE;
  937. }
  938. else
  939. {
  940. *fIpAddress = FALSE;
  941. }
  942. if (IsValidDomain (strAddress)) {
  943. return TRUE;
  944. }
  945. // last chance, maybe its a NetBIOS name w/o wackwack
  946. return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
  947. }
  948. /*---------------------------------------------------------------------------
  949. VerifyWinsServer(CString& strServer,CString& strIP)
  950. Called if the server is not coonected yet, gets the name and
  951. IP address od the server
  952. Author:v-shubk
  953. ---------------------------------------------------------------------------*/
  954. /*
  955. DWORD
  956. VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP)
  957. {
  958. CString strNameIP = strAddress;
  959. BOOL fIp;
  960. DWORD err = ERROR_SUCCESS;
  961. if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE))
  962. {
  963. CWinsServerObj ws(NULL,"", TRUE, TRUE);
  964. if (fIp)
  965. {
  966. // IP address specified
  967. ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE);
  968. }
  969. else
  970. {
  971. // machine name specified
  972. ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE);
  973. }
  974. WINSINTF_BIND_DATA_T wbdBindData;
  975. handle_t hBinding = NULL;
  976. WINSINTF_ADD_T waWinsAddress;
  977. char szNetBIOSName[256] = {0};
  978. do
  979. {
  980. // First attempt to bind to the new address
  981. wbdBindData.fTcpIp = ws.GetNetBIOSName().IsEmpty();
  982. CString strTempAddress;
  983. if (wbdBindData.fTcpIp)
  984. {
  985. strTempAddress = ((CString)ws.GetIpAddress());
  986. }
  987. else
  988. {
  989. //strTempAddress = _T("\\\\") + ws.GetNetBIOSName();
  990. CString tmp;
  991. tmp = ws.GetNetBIOSName();
  992. if ( (tmp[0] == _T('\\')) && (tmp[1] == _T('\\')) )
  993. strTempAddress = ws.GetNetBIOSName();
  994. else
  995. strTempAddress = _T("\\\\") + ws.GetNetBIOSName();
  996. }
  997. wbdBindData.pPipeName = wbdBindData.fTcpIp ? NULL : (LPSTR) g_szPipeName;
  998. wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strTempAddress;
  999. if ((hBinding = ::WinsBind(&wbdBindData)) == NULL)
  1000. {
  1001. err = ::GetLastError();
  1002. break;
  1003. }
  1004. #ifdef WINS_CLIENT_APIS
  1005. err = ::WinsGetNameAndAdd(hBinding,
  1006. &waWinsAddress,
  1007. (LPBYTE) szNetBIOSName);
  1008. #else
  1009. err = ::WinsGetNameAndAdd(&waWinsAddress,
  1010. (LPBYTE) szNetBIOSName);
  1011. #endif WINS_CLIENT_APIS
  1012. }
  1013. while (FALSE);
  1014. if (err == ERROR_SUCCESS)
  1015. {
  1016. // Always use the IP address used for connection
  1017. // if we went over tcpip (not the address returned
  1018. // by the WINS service.
  1019. if (wbdBindData.fTcpIp)
  1020. {
  1021. CIpNamePair ip(ws.GetIpAddress(), szNetBIOSName);
  1022. ws = ip;
  1023. }
  1024. else
  1025. {
  1026. CIpNamePair ip(waWinsAddress.IPAdd, szNetBIOSName);
  1027. ws = ip;
  1028. }
  1029. // convert the dbcs netbios name to wide char
  1030. WCHAR szTempIP[20] = {0};
  1031. int nNumBytes = MultiByteToWideChar(CP_ACP,
  1032. 0,
  1033. szNetBIOSName,
  1034. -1,
  1035. szTempIP,
  1036. 20);
  1037. // now fill in the name for return
  1038. strServerName = szTempIP;
  1039. // fill in the IP
  1040. dwIP = (LONG) ws.QueryIpAddress();
  1041. }
  1042. if (hBinding)
  1043. {
  1044. // call winsunbind here, No more WINS apis called atfer this
  1045. WinsUnbind(&wbdBindData, hBinding);
  1046. hBinding = NULL;
  1047. }
  1048. }
  1049. return err;
  1050. }
  1051. */
  1052. /*---------------------------------------------------------------------------
  1053. VerifyWinsServer(CString& strServer,CString& strIP)
  1054. Called if the server is not coonected yet, gets the name and
  1055. IP address od the server
  1056. Author: ericdav
  1057. ---------------------------------------------------------------------------*/
  1058. DWORD
  1059. VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP)
  1060. {
  1061. CString strNameIP = strAddress;
  1062. BOOL fIp;
  1063. DWORD err = ERROR_SUCCESS;
  1064. if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE))
  1065. {
  1066. CWinsServerObj ws(NULL, "", TRUE, TRUE);
  1067. if (fIp)
  1068. {
  1069. BOOL bIsCluster = ::FIsComputerInRunningCluster(strNameIP);
  1070. // IP address specified
  1071. ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE);
  1072. // if the ip address given to us is a cluster address..
  1073. if (bIsCluster)
  1074. {
  1075. err = GetClusterInfo(
  1076. strNameIP,
  1077. strServerName,
  1078. &dwIP);
  1079. if (err == ERROR_SUCCESS)
  1080. {
  1081. DWORD dwCheckIP;
  1082. err = GetHostAddress(strServerName, &dwCheckIP);
  1083. if (dwCheckIP != dwIP)
  1084. {
  1085. bIsCluster = FALSE;
  1086. }
  1087. }
  1088. }
  1089. // this is not a cluster address
  1090. if (!bIsCluster)
  1091. {
  1092. err = GetHostName((LONG) ws.GetIpAddress(), strServerName);
  1093. if (err == ERROR_SUCCESS)
  1094. {
  1095. if (strServerName.IsEmpty())
  1096. {
  1097. err = DNS_ERROR_NAME_DOES_NOT_EXIST;
  1098. }
  1099. else
  1100. {
  1101. // just want the host name
  1102. int nDot = strServerName.Find('.');
  1103. if (nDot != -1)
  1104. {
  1105. strServerName = strServerName.Left(nDot);
  1106. }
  1107. }
  1108. dwIP = (LONG) ws.GetIpAddress();
  1109. }
  1110. }
  1111. }
  1112. else
  1113. {
  1114. // machine name specified
  1115. ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE);
  1116. err = GetHostAddress(strNameIP, &dwIP);
  1117. if (err == ERROR_SUCCESS)
  1118. {
  1119. // just want the host name
  1120. int nDot = strNameIP.Find('.');
  1121. if (nDot != -1)
  1122. {
  1123. strServerName = strNameIP.Left(nDot);
  1124. }
  1125. else
  1126. {
  1127. strServerName = strNameIP;
  1128. }
  1129. }
  1130. }
  1131. }
  1132. return err;
  1133. }
  1134. void MakeIPAddress(DWORD dwIP, CString & strIP)
  1135. {
  1136. CString strTemp;
  1137. DWORD dwFirst = GETIP_FIRST(dwIP);
  1138. DWORD dwSecond = GETIP_SECOND(dwIP);
  1139. DWORD dwThird = GETIP_THIRD(dwIP);
  1140. DWORD dwLast = GETIP_FOURTH(dwIP);
  1141. strIP.Empty();
  1142. // wrap it into CString object
  1143. TCHAR szStr[20] = {0};
  1144. _itot(dwFirst, szStr, 10);
  1145. strTemp = szStr;
  1146. strTemp += _T(".");
  1147. _itot(dwSecond, szStr, 10);
  1148. strTemp += szStr;
  1149. strTemp += _T(".");
  1150. _itot(dwThird, szStr, 10);
  1151. strTemp += szStr;
  1152. strTemp += _T(".");
  1153. _itot(dwLast, szStr, 10);
  1154. strTemp += szStr;
  1155. strIP = strTemp;
  1156. }
  1157. DWORD
  1158. GetHostName
  1159. (
  1160. DWORD dwIpAddr,
  1161. CString & strHostName
  1162. )
  1163. {
  1164. CString strName;
  1165. //
  1166. // Call the Winsock API to get host name information.
  1167. //
  1168. strHostName.Empty();
  1169. u_long ulAddrInNetOrder = ::htonl( (u_long) dwIpAddr ) ;
  1170. HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
  1171. sizeof ulAddrInNetOrder,
  1172. PF_INET ) ;
  1173. if ( pHostInfo == NULL )
  1174. {
  1175. return ::WSAGetLastError();
  1176. }
  1177. // copy the name
  1178. MBCSToWide(pHostInfo->h_name, strName);
  1179. strName.MakeUpper();
  1180. int nDot = strName.Find(_T("."));
  1181. if (nDot != -1)
  1182. strHostName = strName.Left(nDot);
  1183. else
  1184. strHostName = strName;
  1185. return NOERROR;
  1186. }
  1187. /*---------------------------------------------------------------------------
  1188. GetHostAddress
  1189. Description
  1190. Author: EricDav
  1191. ---------------------------------------------------------------------------*/
  1192. DWORD
  1193. GetHostAddress
  1194. (
  1195. LPCTSTR pszHostName,
  1196. DWORD * pdwIp
  1197. )
  1198. {
  1199. DWORD err = ERROR_SUCCESS;
  1200. CHAR szString [ 2 * (MAX_PATH + 1)] = {0}; // large enough for a MAX_PATH MBCS encoding
  1201. CString strTemp(pszHostName);
  1202. WideToMBCS(strTemp, szString);
  1203. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  1204. if ( pHostent )
  1205. {
  1206. *pdwIp = ::ntohl( *((u_long *) pHostent->h_addr_list[0]) ) ;
  1207. }
  1208. else
  1209. {
  1210. err = ::WSAGetLastError() ;
  1211. }
  1212. return err ;
  1213. }
  1214. //
  1215. // This function makes the appropriate call to either WinsStatus or WinsStatusNew
  1216. //
  1217. CWinsResults::CWinsResults()
  1218. {
  1219. NoOfOwners = 0;
  1220. AddVersMaps.RemoveAll();
  1221. MyMaxVersNo.QuadPart = 0;
  1222. RefreshInterval = 0;
  1223. TombstoneInterval = 0;
  1224. TombstoneTimeout = 0;
  1225. VerifyInterval = 0;
  1226. WinsPriorityClass = 0;
  1227. NoOfWorkerThds = 0;
  1228. memset(&WinsStat, 0, sizeof(WinsStat));
  1229. }
  1230. CWinsResults::CWinsResults(WINSINTF_RESULTS_T * pwrResults)
  1231. {
  1232. Set(pwrResults);
  1233. }
  1234. CWinsResults::CWinsResults(WINSINTF_RESULTS_NEW_T * pwrResults)
  1235. {
  1236. Set(pwrResults);
  1237. }
  1238. DWORD
  1239. CWinsResults::Update(handle_t hBinding)
  1240. {
  1241. DWORD err;
  1242. //
  1243. // First try the new API which does not
  1244. // not have the 25 partner limitation. If
  1245. // this fails with RPC_S_PROCNUM_OUT_OF_RANGE,
  1246. // we know the server is a down-level server,
  1247. // and we need to call the old method.
  1248. //
  1249. err = GetNewConfig(hBinding);
  1250. if (err == RPC_S_PROCNUM_OUT_OF_RANGE)
  1251. {
  1252. //
  1253. // Try old API
  1254. //
  1255. err = GetConfig(hBinding);
  1256. }
  1257. return err;
  1258. }
  1259. DWORD
  1260. CWinsResults::GetNewConfig(handle_t hBinding)
  1261. {
  1262. WINSINTF_RESULTS_NEW_T wrResults;
  1263. wrResults.WinsStat.NoOfPnrs = 0;
  1264. wrResults.WinsStat.pRplPnrs = NULL;
  1265. wrResults.NoOfWorkerThds = 1;
  1266. wrResults.pAddVersMaps = NULL;
  1267. #ifdef WINS_CLIENT_APIS
  1268. DWORD dwStatus = ::WinsStatusNew(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1269. #else
  1270. DWORD dwStatus = ::WinsStatusNew(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1271. #endif WINS_CLIENT_APIS
  1272. if (dwStatus == ERROR_SUCCESS)
  1273. {
  1274. Set(&wrResults);
  1275. }
  1276. else
  1277. {
  1278. Clear();
  1279. }
  1280. return dwStatus;
  1281. }
  1282. DWORD
  1283. CWinsResults::GetConfig(handle_t hBinding)
  1284. {
  1285. WINSINTF_RESULTS_T wrResults;
  1286. wrResults.WinsStat.NoOfPnrs = 0;
  1287. wrResults.WinsStat.pRplPnrs = NULL;
  1288. wrResults.NoOfWorkerThds = 1;
  1289. #ifdef WINS_CLIENT_APIS
  1290. DWORD dwStatus = ::WinsStatus(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1291. #else
  1292. DWORD dwStatus = ::WinsStatus(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1293. #endif WINS_CLIENT_APIS
  1294. if (dwStatus == ERROR_SUCCESS)
  1295. {
  1296. Set(&wrResults);
  1297. }
  1298. else
  1299. {
  1300. Clear();
  1301. }
  1302. return dwStatus;
  1303. }
  1304. void
  1305. CWinsResults::Clear()
  1306. {
  1307. AddVersMaps.RemoveAll();
  1308. NoOfOwners = 0;
  1309. MyMaxVersNo.QuadPart = 0;
  1310. RefreshInterval = 0;
  1311. TombstoneInterval = 0;
  1312. TombstoneTimeout = 0;
  1313. VerifyInterval = 0;
  1314. WinsPriorityClass = 0;
  1315. NoOfWorkerThds = 0;
  1316. memset(&WinsStat, 0, sizeof(WinsStat));
  1317. }
  1318. void
  1319. CWinsResults::Set(WINSINTF_RESULTS_NEW_T * pwrResults)
  1320. {
  1321. if (pwrResults)
  1322. {
  1323. NoOfOwners = pwrResults->NoOfOwners;
  1324. AddVersMaps.RemoveAll();
  1325. for (UINT i = 0; i < NoOfOwners; i++)
  1326. {
  1327. AddVersMaps.Add(pwrResults->pAddVersMaps[i]);
  1328. }
  1329. MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart;
  1330. RefreshInterval = pwrResults->RefreshInterval;
  1331. TombstoneInterval = pwrResults->TombstoneInterval;
  1332. TombstoneTimeout = pwrResults->TombstoneTimeout;
  1333. VerifyInterval = pwrResults->VerifyInterval;
  1334. WinsPriorityClass = pwrResults->WinsPriorityClass;
  1335. NoOfWorkerThds = pwrResults->NoOfWorkerThds;
  1336. WinsStat = pwrResults->WinsStat;
  1337. }
  1338. }
  1339. void
  1340. CWinsResults::Set(WINSINTF_RESULTS_T * pwrResults)
  1341. {
  1342. if (pwrResults == NULL)
  1343. {
  1344. Clear();
  1345. }
  1346. else
  1347. {
  1348. NoOfOwners = pwrResults->NoOfOwners;
  1349. AddVersMaps.RemoveAll();
  1350. for (UINT i = 0; i < NoOfOwners; i++)
  1351. {
  1352. AddVersMaps.Add(pwrResults->AddVersMaps[i]);
  1353. }
  1354. MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart;
  1355. RefreshInterval = pwrResults->RefreshInterval;
  1356. TombstoneInterval = pwrResults->TombstoneInterval;
  1357. TombstoneTimeout = pwrResults->TombstoneTimeout;
  1358. VerifyInterval = pwrResults->VerifyInterval;
  1359. WinsPriorityClass = pwrResults->WinsPriorityClass;
  1360. NoOfWorkerThds = pwrResults->NoOfWorkerThds;
  1361. WinsStat = pwrResults->WinsStat;
  1362. }
  1363. }