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

1589 lines
39 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. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  409. if ( pszSuffixString )
  410. {
  411. ::lstrcat( chMesg, _T(" ") ) ;
  412. ::lstrcat( chMesg, pszSuffixString ) ;
  413. }
  414. return ::AfxMessageBox( chMesg, nType, nHelpContext ) ;
  415. }
  416. /*!--------------------------------------------------------------------------
  417. WinsMessageBoxEx
  418. Puts up a message box with the corresponding error text.
  419. Author: EricDav
  420. ---------------------------------------------------------------------------*/
  421. int
  422. WinsMessageBoxEx
  423. (
  424. UINT nIdPrompt,
  425. LPCTSTR pszPrefixMessage,
  426. UINT nType,
  427. UINT nHelpContext
  428. )
  429. {
  430. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  431. TCHAR chMesg[4000];
  432. CString strMessage;
  433. BOOL bOk;
  434. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(TCHAR));
  435. if ( pszPrefixMessage )
  436. {
  437. strMessage = pszPrefixMessage;
  438. strMessage += _T("\n");
  439. strMessage += _T("\n");
  440. strMessage += chMesg;
  441. }
  442. else
  443. {
  444. strMessage = chMesg;
  445. }
  446. return AfxMessageBox(strMessage, nType, nHelpContext);
  447. }
  448. // class NameTypeMapping handlers
  449. /*!--------------------------------------------------------------------------
  450. MapDWORDToCString
  451. Generic mapping of a DWORD to a CString.
  452. dwNameType is the 16th byte of the name.
  453. dwWinsType is Unique, multihomed, group, etc...
  454. Author: KennT
  455. ---------------------------------------------------------------------------*/
  456. void MapDWORDToCString(DWORD dwNameType, DWORD dwWinsType, const CStringMapArray * pMap, CString & strName)
  457. {
  458. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  459. CStringMapEntry mapEntry;
  460. for (int i = 0; i < pMap->GetSize(); i++)
  461. {
  462. mapEntry = pMap->GetAt(i);
  463. // break out if this is the correct type and the wins type
  464. // matches or is a don't care
  465. if ( (mapEntry.dwNameType == dwNameType) &&
  466. ( (mapEntry.dwWinsType == -1) ||
  467. (mapEntry.dwWinsType == dwWinsType) ) )
  468. {
  469. break;
  470. }
  471. mapEntry.dwNameType = 0xFFFFFFFF;
  472. }
  473. if (mapEntry.dwNameType == 0xFFFFFFFF)
  474. {
  475. MapDWORDToCString(NAME_TYPE_OTHER, dwWinsType, pMap, strName);
  476. }
  477. else
  478. {
  479. if (mapEntry.st.IsEmpty())
  480. Verify(pMap->GetAt(i).st.LoadString(mapEntry.ulStringId));
  481. strName = pMap->GetAt(i).st;
  482. }
  483. }
  484. // this structure allows us to map name types to strings. The secondary
  485. // check is based on the wins defined record type. In order for this to work
  486. // correctly, place any names that need to be defined with the wins type before
  487. // the entry with the wins type set to -1.
  488. static const UINT s_NameTypeMappingDefault[NUM_DEFAULT_NAME_TYPES][3] =
  489. {
  490. { NAME_TYPE_WORKSTATION, WINSINTF_E_NORM_GROUP, IDS_NAMETYPE_MAP_WORKGROUP },
  491. { NAME_TYPE_WORKSTATION, -1, IDS_NAMETYPE_MAP_WORKSTATION },
  492. { NAME_TYPE_DC, -1, IDS_NAMETYPE_MAP_DC },
  493. { NAME_TYPE_FILE_SERVER, WINSINTF_E_SPEC_GROUP, IDS_NAMETYPE_MAP_SPECIAL_INTERNET_GROUP },
  494. { NAME_TYPE_FILE_SERVER, -1, IDS_NAMETYPE_MAP_FILE_SERVER },
  495. { NAME_TYPE_DMB , -1, IDS_NAMETYPE_MAP_DMB },
  496. { NAME_TYPE_OTHER, -1, IDS_NAMETYPE_MAP_OTHER },
  497. { NAME_TYPE_NETDDE, -1, IDS_NAMETYPE_MAP_NETDDE },
  498. { NAME_TYPE_MESSENGER, -1, IDS_NAMETYPE_MAP_MESSENGER },
  499. { NAME_TYPE_RAS_SERVER, -1, IDS_NAMETYPE_MAP_RAS_SERVER },
  500. { NAME_TYPE_NORM_GRP_NAME, -1, IDS_NAMETYPE_MAP_NORMAL_GROUP_NAME },
  501. { NAME_TYPE_WORK_NW_MON_AGENT, -1, IDS_NAMETYPE_MAP_NW_MON_AGENT },
  502. { NAME_TYPE_WORK_NW_MON_NAME, -1, IDS_NAMETYPE_MAP_NMN},
  503. };
  504. const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szNameTypeMapKey = _T("SYSTEM\\CurrentControlSet\\Services\\wins\\NameTypeMap");
  505. const NameTypeMapping::REGKEYNAME NameTypeMapping::c_szDefault= _T("(Default)");
  506. NameTypeMapping ::NameTypeMapping()
  507. {
  508. }
  509. NameTypeMapping ::~NameTypeMapping()
  510. {
  511. Unload();
  512. }
  513. void
  514. NameTypeMapping ::SetMachineName(LPCTSTR pszMachineName)
  515. {
  516. m_strMachineName = pszMachineName;
  517. }
  518. HRESULT NameTypeMapping::Load()
  519. {
  520. HRESULT hr = hrOK;
  521. RegKey regkey;
  522. RegKey regkeyMachine;
  523. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  524. RegKey::CREGKEY_KEY_INFO regkeyInfo;
  525. RegKeyIterator regkeyIter;
  526. UINT i;
  527. WORD langID;
  528. RegKey regkeyProto;
  529. DWORD dwErr;
  530. CStringMapEntry mapEntry;
  531. ::ZeroMemory(&regkeyInfo, sizeof(regkeyInfo));
  532. // Look for the registry key
  533. if (FHrSucceeded(hr))
  534. hr = HRESULT_FROM_WIN32( regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) );
  535. // Get the count of items
  536. if (FHrSucceeded(hr))
  537. hr = HRESULT_FROM_WIN32( regkey.QueryKeyInfo(&regkeyInfo) );
  538. // Alloc the array for the count of items + default items
  539. Unload();
  540. // Read in the registry data and add it to the internal array
  541. //
  542. // enumerate the keys
  543. //
  544. if (FHrSucceeded(hr))
  545. hr = regkeyIter.Init(&regkey);
  546. if (FHrSucceeded(hr))
  547. {
  548. HRESULT hrIter;
  549. DWORD dwProtoId;
  550. CString stKey;
  551. CString stLang;
  552. // Now that we have this key, look for the language id
  553. langID = GetUserDefaultLangID();
  554. stLang.Format(_T("%04x"), (DWORD)langID);
  555. for (hrIter = regkeyIter.Next(&stKey, NULL); hrIter == hrOK; hrIter = regkeyIter.Next(&stKey, NULL))
  556. {
  557. CString st;
  558. // Given the name of the key, that is a hex value (the protocol id)
  559. // Convert that into a DWORD
  560. dwProtoId = _tcstoul((LPCTSTR) stKey, NULL, 16);
  561. // Open this key
  562. regkeyProto.Close();
  563. dwErr = regkeyProto.Open(regkey, stKey);
  564. if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  565. continue;
  566. // Ok, get the name value
  567. dwErr = regkeyProto.QueryValue(stLang, st);
  568. if (!FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  569. {
  570. // Look for the key with the name of default
  571. dwErr = regkeyProto.QueryValue(c_szDefault, st);
  572. }
  573. if (FHrSucceeded(HRESULT_FROM_WIN32(dwErr)))
  574. {
  575. // Ok, add this value to the list
  576. mapEntry.dwNameType = dwProtoId;
  577. mapEntry.st = st;
  578. mapEntry.ulStringId = 0;
  579. Add(mapEntry);
  580. }
  581. }
  582. }
  583. // Read in the default item data and add it to the array
  584. for (i = 0; i < DimensionOf(s_NameTypeMappingDefault); i++)
  585. {
  586. mapEntry.dwNameType = s_NameTypeMappingDefault[i][0];
  587. mapEntry.dwWinsType = s_NameTypeMappingDefault[i][1];
  588. mapEntry.st.LoadString(s_NameTypeMappingDefault[i][2]);
  589. mapEntry.ulStringId = 0;
  590. Add(mapEntry);
  591. }
  592. return hrOK;
  593. }
  594. void NameTypeMapping::Unload()
  595. {
  596. RemoveAll();
  597. }
  598. void NameTypeMapping::TypeToCString(DWORD dwProtocolId, DWORD dwRecordType, CString & strName)
  599. {
  600. MapDWORDToCString(dwProtocolId, dwRecordType, this, strName);
  601. }
  602. // add in the new id/name
  603. HRESULT NameTypeMapping::AddEntry(DWORD dwProtocolId, LPCTSTR pstrName)
  604. {
  605. HRESULT hr = hrOK;
  606. RegKey regkey;
  607. RegKey regkeyID;
  608. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  609. WORD langID;
  610. CStringMapEntry mapEntry;
  611. CString stID, stLang, stNew;
  612. // Look for the registry key
  613. if (FHrSucceeded(hr))
  614. hr = HRESULT_FROM_WIN32( regkey.Create(hkeyMachine, c_szNameTypeMapKey, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) );
  615. // build our new ID string
  616. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  617. // Now that we have this key, look for the language id
  618. langID = GetUserDefaultLangID();
  619. stLang.Format(_T("%04x"), (DWORD)langID);
  620. stNew = c_szNameTypeMapKey + _T("\\") + stID;
  621. // create the ID key
  622. if (FHrSucceeded(hr))
  623. hr = HRESULT_FROM_WIN32( regkeyID.Create(hkeyMachine, stNew, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, m_strMachineName) );
  624. // set the name value
  625. if (FHrSucceeded(hr))
  626. hr = HRESULT_FROM_WIN32( regkeyID.SetValue(stLang, pstrName) );
  627. if (FHrSucceeded(hr))
  628. {
  629. // add to internal list
  630. mapEntry.dwNameType = dwProtocolId;
  631. mapEntry.st = pstrName;
  632. mapEntry.ulStringId = 0;
  633. Add(mapEntry);
  634. }
  635. return hr;
  636. }
  637. // modify the given ID's string name
  638. HRESULT NameTypeMapping::ModifyEntry(DWORD dwProtocolId, LPCTSTR pstrName)
  639. {
  640. HRESULT hr = hrOK;
  641. RegKey regkey;
  642. RegKey regkeyID;
  643. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  644. int i;
  645. WORD langID;
  646. CString stID, stLang, stNew;
  647. // Look for the registry key
  648. if (FHrSucceeded(hr))
  649. hr = HRESULT_FROM_WIN32( regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) );
  650. // build our new ID string
  651. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  652. stNew = c_szNameTypeMapKey + _T("\\") + stID;
  653. // open the correct ID key
  654. if (FHrSucceeded(hr))
  655. hr = HRESULT_FROM_WIN32( regkeyID.Open(hkeyMachine, stNew, KEY_ALL_ACCESS, m_strMachineName) );
  656. // Now that we have this key, look for the language id
  657. langID = GetUserDefaultLangID();
  658. stLang.Format(_T("%04x"), (DWORD)langID);
  659. // set the new value
  660. if (FHrSucceeded(hr))
  661. hr = HRESULT_FROM_WIN32( regkeyID.SetValue(stLang, pstrName) );
  662. if (FHrSucceeded(hr))
  663. {
  664. // modify the internal list
  665. for (i = 0; i < GetSize(); i++)
  666. {
  667. if (GetAt(i).dwNameType == dwProtocolId)
  668. {
  669. m_pData[i].st = pstrName;
  670. break;
  671. }
  672. }
  673. }
  674. return hr;
  675. }
  676. // remove the given ID's string name
  677. HRESULT NameTypeMapping::RemoveEntry(DWORD dwProtocolId)
  678. {
  679. HRESULT hr = hrOK;
  680. RegKey regkey;
  681. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  682. int i;
  683. CString stID;
  684. // Look for the registry key
  685. if (FHrSucceeded(hr))
  686. hr = HRESULT_FROM_WIN32( regkey.Open(hkeyMachine, c_szNameTypeMapKey, KEY_READ, m_strMachineName) );
  687. // build our new ID string
  688. stID.Format(_T("%04x"), (DWORD) dwProtocolId);
  689. // set the new value
  690. if (FHrSucceeded(hr))
  691. hr = HRESULT_FROM_WIN32( regkey.RecurseDeleteKey(stID) );
  692. if (FHrSucceeded(hr))
  693. {
  694. // modify the internal list
  695. for (i = 0; i < GetSize(); i++)
  696. {
  697. if (GetAt(i).dwNameType == dwProtocolId)
  698. {
  699. RemoveAt(i);
  700. break;
  701. }
  702. }
  703. }
  704. return hr;
  705. }
  706. BOOL
  707. NameTypeMapping::EntryExists(DWORD dwProtocolId)
  708. {
  709. BOOL fExists = FALSE;
  710. for (int i = 0; i < GetSize(); i++)
  711. {
  712. if (GetAt(i).dwNameType == dwProtocolId)
  713. {
  714. fExists = TRUE;
  715. break;
  716. }
  717. }
  718. return fExists;
  719. }
  720. /*---------------------------------------------------------------------------
  721. CleanString(CString& str)
  722. Strip leading and trailing spaces from the string.
  723. ---------------------------------------------------------------------------*/
  724. CString&
  725. CleanString(
  726. CString& str
  727. )
  728. {
  729. if (str.IsEmpty())
  730. {
  731. return str ;
  732. }
  733. int n = 0;
  734. while ((n < str.GetLength()) && (str[n] == ' '))
  735. {
  736. ++n;
  737. }
  738. if (n)
  739. {
  740. str = str.Mid(n);
  741. }
  742. n = str.GetLength();
  743. while (n && (str[--n] == ' '))
  744. {
  745. str.ReleaseBuffer(n);
  746. }
  747. return str;
  748. }
  749. /*---------------------------------------------------------------------------
  750. IsValidNetBIOSName
  751. Determine if the given netbios is valid, and pre-pend
  752. a double backslash if not already present (and the address
  753. is otherwise valid).
  754. ---------------------------------------------------------------------------*/
  755. BOOL
  756. IsValidNetBIOSName(
  757. CString & strAddress,
  758. BOOL fLanmanCompatible,
  759. BOOL fWackwack // expand slashes if not present
  760. )
  761. {
  762. TCHAR szWacks[] = _T("\\\\");
  763. if (strAddress.IsEmpty())
  764. {
  765. return FALSE;
  766. }
  767. if (strAddress[0] == _T('\\'))
  768. {
  769. if (strAddress.GetLength() < 3)
  770. {
  771. return FALSE;
  772. }
  773. if (strAddress[1] != _T('\\'))
  774. {
  775. // One slash only? Not valid
  776. return FALSE;
  777. }
  778. }
  779. else
  780. {
  781. if (fWackwack)
  782. {
  783. // Add the backslashes
  784. strAddress = szWacks + strAddress;
  785. }
  786. }
  787. int nMaxAllowedLength = fLanmanCompatible
  788. ? LM_NAME_MAX_LENGTH
  789. : NB_NAME_MAX_LENGTH;
  790. if (fLanmanCompatible)
  791. {
  792. strAddress.MakeUpper();
  793. }
  794. return strAddress.GetLength() <= nMaxAllowedLength + 2;
  795. }
  796. /*---------------------------------------------------------------------------
  797. IsValidDomain
  798. Determine if the given domain name address is valid, and clean
  799. it up, if necessary
  800. ---------------------------------------------------------------------------*/
  801. BOOL
  802. IsValidDomain(CString & strDomain)
  803. {
  804. /* int nLen;
  805. if ((nLen = strDomain.GetLength()) != 0)
  806. {
  807. if (nLen < DOMAINNAME_LENGTH) // 255
  808. {
  809. int i;
  810. int istr = 0;
  811. TCHAR ch;
  812. BOOL fLet_Dig = FALSE;
  813. BOOL fDot = FALSE;
  814. int cHostname = 0;
  815. for (i = 0; i < nLen; i++)
  816. {
  817. // check each character
  818. ch = strDomain[i];
  819. BOOL fAlNum = iswalpha(ch) || iswdigit(ch);
  820. if (((i == 0) && !fAlNum) ||
  821. // first letter must be a digit or a letter
  822. (fDot && !fAlNum) ||
  823. // first letter after dot must be a digit or a letter
  824. ((i == (nLen - 1)) && !fAlNum) ||
  825. // last letter must be a letter or a digit
  826. (!fAlNum && ( ch != _T('-') && ( ch != _T('.') && ( ch != _T('_'))))) ||
  827. // must be letter, digit, - or "."
  828. (( ch == _T('.')) && ( !fLet_Dig )))
  829. // must be letter or digit before '.'
  830. {
  831. return FALSE;
  832. }
  833. fLet_Dig = fAlNum;
  834. fDot = (ch == _T('.'));
  835. cHostname++;
  836. if ( cHostname > HOSTNAME_LENGTH )
  837. {
  838. return FALSE;
  839. }
  840. if ( fDot )
  841. {
  842. cHostname = 0;
  843. }
  844. }
  845. }
  846. }
  847. */
  848. return TRUE;
  849. }
  850. /*---------------------------------------------------------------------------
  851. IsValidIpAddress
  852. Determine if the given IP address is valid, and clean
  853. it up, if necessary
  854. ---------------------------------------------------------------------------*/
  855. BOOL
  856. IsValidIpAddress(CString & strAddress)
  857. {
  858. if (strAddress.IsEmpty())
  859. {
  860. return FALSE;
  861. }
  862. CIpAddress ia(strAddress);
  863. BOOL fValid = ia.IsValid();
  864. if (fValid)
  865. {
  866. // Fill out the IP address string for clarity
  867. strAddress = ia;
  868. return TRUE;
  869. }
  870. return FALSE;
  871. }
  872. /*---------------------------------------------------------------------------
  873. IsValidAddress
  874. Determine if the given address is a valid NetBIOS or
  875. TCP/IP address, judging by the name only. Note that
  876. validation may clean up the given string
  877. NetBIOS names not beginning with "\\" will have those characters
  878. pre-pended, and otherwise valid IP Addresses are filled out to
  879. 4 octets.
  880. Leading and trailing spaces are removed from the string.
  881. --------------------------------------------------------------------------*/
  882. BOOL
  883. IsValidAddress(
  884. CString& strAddress,
  885. BOOL * fIpAddress,
  886. BOOL fLanmanCompatible,
  887. BOOL fWackwack // expand netbios slashes
  888. )
  889. {
  890. int i;
  891. // Remove leading and trailing spaces
  892. CleanString(strAddress);
  893. if (strAddress.IsEmpty()) {
  894. *fIpAddress = FALSE;
  895. return FALSE;
  896. }
  897. if (strAddress[0] == _T('\\')) {
  898. *fIpAddress = FALSE;
  899. return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
  900. }
  901. if (IsValidIpAddress(strAddress))
  902. {
  903. *fIpAddress = TRUE;
  904. return TRUE;
  905. }
  906. else
  907. {
  908. *fIpAddress = FALSE;
  909. }
  910. if (IsValidDomain (strAddress)) {
  911. return TRUE;
  912. }
  913. // last chance, maybe its a NetBIOS name w/o wackwack
  914. return IsValidNetBIOSName(strAddress, fLanmanCompatible, fWackwack);
  915. }
  916. /*---------------------------------------------------------------------------
  917. VerifyWinsServer(CString& strServer,CString& strIP)
  918. Called if the server is not coonected yet, gets the name and
  919. IP address od the server
  920. Author:v-shubk
  921. ---------------------------------------------------------------------------*/
  922. /*
  923. DWORD
  924. VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP)
  925. {
  926. CString strNameIP = strAddress;
  927. BOOL fIp;
  928. DWORD err = ERROR_SUCCESS;
  929. if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE))
  930. {
  931. CWinsServerObj ws(NULL,"", TRUE, TRUE);
  932. if (fIp)
  933. {
  934. // IP address specified
  935. ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE);
  936. }
  937. else
  938. {
  939. // machine name specified
  940. ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE);
  941. }
  942. WINSINTF_BIND_DATA_T wbdBindData;
  943. handle_t hBinding = NULL;
  944. WINSINTF_ADD_T waWinsAddress;
  945. char szNetBIOSName[256] = {0};
  946. do
  947. {
  948. // First attempt to bind to the new address
  949. wbdBindData.fTcpIp = ws.GetNetBIOSName().IsEmpty();
  950. CString strTempAddress;
  951. if (wbdBindData.fTcpIp)
  952. {
  953. strTempAddress = ((CString)ws.GetIpAddress());
  954. }
  955. else
  956. {
  957. //strTempAddress = _T("\\\\") + ws.GetNetBIOSName();
  958. CString tmp;
  959. tmp = ws.GetNetBIOSName();
  960. if ( (tmp[0] == _T('\\')) && (tmp[1] == _T('\\')) )
  961. strTempAddress = ws.GetNetBIOSName();
  962. else
  963. strTempAddress = _T("\\\\") + ws.GetNetBIOSName();
  964. }
  965. wbdBindData.pPipeName = wbdBindData.fTcpIp ? NULL : (LPSTR) g_szPipeName;
  966. wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strTempAddress;
  967. if ((hBinding = ::WinsBind(&wbdBindData)) == NULL)
  968. {
  969. err = ::GetLastError();
  970. break;
  971. }
  972. #ifdef WINS_CLIENT_APIS
  973. err = ::WinsGetNameAndAdd(hBinding,
  974. &waWinsAddress,
  975. (LPBYTE) szNetBIOSName);
  976. #else
  977. err = ::WinsGetNameAndAdd(&waWinsAddress,
  978. (LPBYTE) szNetBIOSName);
  979. #endif WINS_CLIENT_APIS
  980. }
  981. while (FALSE);
  982. if (err == ERROR_SUCCESS)
  983. {
  984. // Always use the IP address used for connection
  985. // if we went over tcpip (not the address returned
  986. // by the WINS service.
  987. if (wbdBindData.fTcpIp)
  988. {
  989. CIpNamePair ip(ws.GetIpAddress(), szNetBIOSName);
  990. ws = ip;
  991. }
  992. else
  993. {
  994. CIpNamePair ip(waWinsAddress.IPAdd, szNetBIOSName);
  995. ws = ip;
  996. }
  997. // convert the dbcs netbios name to wide char
  998. WCHAR szTempIP[20] = {0};
  999. int nNumBytes = MultiByteToWideChar(CP_ACP,
  1000. 0,
  1001. szNetBIOSName,
  1002. -1,
  1003. szTempIP,
  1004. 20);
  1005. // now fill in the name for return
  1006. strServerName = szTempIP;
  1007. // fill in the IP
  1008. dwIP = (LONG) ws.QueryIpAddress();
  1009. }
  1010. if (hBinding)
  1011. {
  1012. // call winsunbind here, No more WINS apis called atfer this
  1013. WinsUnbind(&wbdBindData, hBinding);
  1014. hBinding = NULL;
  1015. }
  1016. }
  1017. return err;
  1018. }
  1019. */
  1020. /*---------------------------------------------------------------------------
  1021. VerifyWinsServer(CString& strServer,CString& strIP)
  1022. Called if the server is not coonected yet, gets the name and
  1023. IP address od the server
  1024. Author: ericdav
  1025. ---------------------------------------------------------------------------*/
  1026. DWORD
  1027. VerifyWinsServer(CString &strAddress, CString &strServerName, DWORD & dwIP)
  1028. {
  1029. CString strNameIP = strAddress;
  1030. BOOL fIp;
  1031. DWORD err = ERROR_SUCCESS;
  1032. if (IsValidAddress(strNameIP, &fIp, TRUE, TRUE))
  1033. {
  1034. CWinsServerObj ws(NULL, "", TRUE, TRUE);
  1035. if (fIp)
  1036. {
  1037. BOOL bIsCluster = ::FIsComputerInRunningCluster(strNameIP);
  1038. // IP address specified
  1039. ws = CWinsServerObj(CIpAddress(strNameIP), "", TRUE, TRUE);
  1040. // if the ip address given to us is a cluster address..
  1041. if (bIsCluster)
  1042. {
  1043. err = GetClusterInfo(
  1044. strNameIP,
  1045. strServerName,
  1046. &dwIP);
  1047. if (err == ERROR_SUCCESS)
  1048. {
  1049. DWORD dwCheckIP;
  1050. err = GetHostAddress(strServerName, &dwCheckIP);
  1051. if (dwCheckIP != dwIP)
  1052. {
  1053. bIsCluster = FALSE;
  1054. }
  1055. }
  1056. }
  1057. // this is not a cluster address
  1058. if (!bIsCluster)
  1059. {
  1060. err = GetHostName((LONG) ws.GetIpAddress(), strServerName);
  1061. if (err == ERROR_SUCCESS)
  1062. {
  1063. if (strServerName.IsEmpty())
  1064. {
  1065. err = DNS_ERROR_NAME_DOES_NOT_EXIST;
  1066. }
  1067. else
  1068. {
  1069. // just want the host name
  1070. int nDot = strServerName.Find('.');
  1071. if (nDot != -1)
  1072. {
  1073. strServerName = strServerName.Left(nDot);
  1074. }
  1075. }
  1076. dwIP = (LONG) ws.GetIpAddress();
  1077. }
  1078. }
  1079. }
  1080. else
  1081. {
  1082. // machine name specified
  1083. ws = CWinsServerObj(CIpAddress(), strNameIP, TRUE, TRUE);
  1084. err = GetHostAddress(strNameIP, &dwIP);
  1085. if (err == ERROR_SUCCESS)
  1086. {
  1087. // just want the host name
  1088. int nDot = strNameIP.Find('.');
  1089. if (nDot != -1)
  1090. {
  1091. strServerName = strNameIP.Left(nDot);
  1092. }
  1093. else
  1094. {
  1095. strServerName = strNameIP;
  1096. }
  1097. }
  1098. }
  1099. }
  1100. return err;
  1101. }
  1102. void MakeIPAddress(DWORD dwIP, CString & strIP)
  1103. {
  1104. CString strTemp;
  1105. DWORD dwFirst = GETIP_FIRST(dwIP);
  1106. DWORD dwSecond = GETIP_SECOND(dwIP);
  1107. DWORD dwThird = GETIP_THIRD(dwIP);
  1108. DWORD dwLast = GETIP_FOURTH(dwIP);
  1109. strIP.Empty();
  1110. // wrap it into CString object
  1111. TCHAR szStr[20] = {0};
  1112. _itot(dwFirst, szStr, 10);
  1113. strTemp = szStr;
  1114. strTemp += _T(".");
  1115. _itot(dwSecond, szStr, 10);
  1116. strTemp += szStr;
  1117. strTemp += _T(".");
  1118. _itot(dwThird, szStr, 10);
  1119. strTemp += szStr;
  1120. strTemp += _T(".");
  1121. _itot(dwLast, szStr, 10);
  1122. strTemp += szStr;
  1123. strIP = strTemp;
  1124. }
  1125. DWORD
  1126. GetHostName
  1127. (
  1128. DWORD dwIpAddr,
  1129. CString & strHostName
  1130. )
  1131. {
  1132. CString strName;
  1133. //
  1134. // Call the Winsock API to get host name information.
  1135. //
  1136. strHostName.Empty();
  1137. u_long ulAddrInNetOrder = ::htonl( (u_long) dwIpAddr ) ;
  1138. HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
  1139. sizeof ulAddrInNetOrder,
  1140. PF_INET ) ;
  1141. if ( pHostInfo == NULL )
  1142. {
  1143. return ::WSAGetLastError();
  1144. }
  1145. // copy the name
  1146. MBCSToWide(pHostInfo->h_name, strName);
  1147. strName.MakeUpper();
  1148. int nDot = strName.Find(_T("."));
  1149. if (nDot != -1)
  1150. strHostName = strName.Left(nDot);
  1151. else
  1152. strHostName = strName;
  1153. return NOERROR;
  1154. }
  1155. /*---------------------------------------------------------------------------
  1156. GetHostAddress
  1157. Description
  1158. Author: EricDav
  1159. ---------------------------------------------------------------------------*/
  1160. DWORD
  1161. GetHostAddress
  1162. (
  1163. LPCTSTR pszHostName,
  1164. DWORD * pdwIp
  1165. )
  1166. {
  1167. DWORD err = ERROR_SUCCESS;
  1168. CHAR szString [ MAX_PATH ] = {0};
  1169. CString strTemp(pszHostName);
  1170. WideToMBCS(strTemp, szString);
  1171. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  1172. if ( pHostent )
  1173. {
  1174. *pdwIp = ::ntohl( *((u_long *) pHostent->h_addr_list[0]) ) ;
  1175. }
  1176. else
  1177. {
  1178. err = ::WSAGetLastError() ;
  1179. }
  1180. return err ;
  1181. }
  1182. //
  1183. // This function makes the appropriate call to either WinsStatus or WinsStatusNew
  1184. //
  1185. CWinsResults::CWinsResults()
  1186. {
  1187. NoOfOwners = 0;
  1188. AddVersMaps.RemoveAll();
  1189. MyMaxVersNo.QuadPart = 0;
  1190. RefreshInterval = 0;
  1191. TombstoneInterval = 0;
  1192. TombstoneTimeout = 0;
  1193. VerifyInterval = 0;
  1194. WinsPriorityClass = 0;
  1195. NoOfWorkerThds = 0;
  1196. memset(&WinsStat, 0, sizeof(WinsStat));
  1197. }
  1198. CWinsResults::CWinsResults(WINSINTF_RESULTS_T * pwrResults)
  1199. {
  1200. Set(pwrResults);
  1201. }
  1202. CWinsResults::CWinsResults(WINSINTF_RESULTS_NEW_T * pwrResults)
  1203. {
  1204. Set(pwrResults);
  1205. }
  1206. DWORD
  1207. CWinsResults::Update(handle_t hBinding)
  1208. {
  1209. DWORD err;
  1210. //
  1211. // First try the new API which does not
  1212. // not have the 25 partner limitation. If
  1213. // this fails with RPC_S_PROCNUM_OUT_OF_RANGE,
  1214. // we know the server is a down-level server,
  1215. // and we need to call the old method.
  1216. //
  1217. err = GetNewConfig(hBinding);
  1218. if (err == RPC_S_PROCNUM_OUT_OF_RANGE)
  1219. {
  1220. //
  1221. // Try old API
  1222. //
  1223. err = GetConfig(hBinding);
  1224. }
  1225. return err;
  1226. }
  1227. DWORD
  1228. CWinsResults::GetNewConfig(handle_t hBinding)
  1229. {
  1230. WINSINTF_RESULTS_NEW_T wrResults;
  1231. wrResults.WinsStat.NoOfPnrs = 0;
  1232. wrResults.WinsStat.pRplPnrs = NULL;
  1233. wrResults.NoOfWorkerThds = 1;
  1234. wrResults.pAddVersMaps = NULL;
  1235. #ifdef WINS_CLIENT_APIS
  1236. DWORD dwStatus = ::WinsStatusNew(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1237. #else
  1238. DWORD dwStatus = ::WinsStatusNew(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1239. #endif WINS_CLIENT_APIS
  1240. if (dwStatus == ERROR_SUCCESS)
  1241. {
  1242. Set(&wrResults);
  1243. }
  1244. else
  1245. {
  1246. Clear();
  1247. }
  1248. return dwStatus;
  1249. }
  1250. DWORD
  1251. CWinsResults::GetConfig(handle_t hBinding)
  1252. {
  1253. WINSINTF_RESULTS_T wrResults;
  1254. wrResults.WinsStat.NoOfPnrs = 0;
  1255. wrResults.WinsStat.pRplPnrs = NULL;
  1256. wrResults.NoOfWorkerThds = 1;
  1257. #ifdef WINS_CLIENT_APIS
  1258. DWORD dwStatus = ::WinsStatus(hBinding, WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1259. #else
  1260. DWORD dwStatus = ::WinsStatus(WINSINTF_E_CONFIG_ALL_MAPS, &wrResults);
  1261. #endif WINS_CLIENT_APIS
  1262. if (dwStatus == ERROR_SUCCESS)
  1263. {
  1264. Set(&wrResults);
  1265. }
  1266. else
  1267. {
  1268. Clear();
  1269. }
  1270. return dwStatus;
  1271. }
  1272. void
  1273. CWinsResults::Clear()
  1274. {
  1275. AddVersMaps.RemoveAll();
  1276. NoOfOwners = 0;
  1277. MyMaxVersNo.QuadPart = 0;
  1278. RefreshInterval = 0;
  1279. TombstoneInterval = 0;
  1280. TombstoneTimeout = 0;
  1281. VerifyInterval = 0;
  1282. WinsPriorityClass = 0;
  1283. NoOfWorkerThds = 0;
  1284. memset(&WinsStat, 0, sizeof(WinsStat));
  1285. }
  1286. void
  1287. CWinsResults::Set(WINSINTF_RESULTS_NEW_T * pwrResults)
  1288. {
  1289. if (pwrResults)
  1290. {
  1291. NoOfOwners = pwrResults->NoOfOwners;
  1292. AddVersMaps.RemoveAll();
  1293. for (UINT i = 0; i < NoOfOwners; i++)
  1294. {
  1295. AddVersMaps.Add(pwrResults->pAddVersMaps[i]);
  1296. }
  1297. MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart;
  1298. RefreshInterval = pwrResults->RefreshInterval;
  1299. TombstoneInterval = pwrResults->TombstoneInterval;
  1300. TombstoneTimeout = pwrResults->TombstoneTimeout;
  1301. VerifyInterval = pwrResults->VerifyInterval;
  1302. WinsPriorityClass = pwrResults->WinsPriorityClass;
  1303. NoOfWorkerThds = pwrResults->NoOfWorkerThds;
  1304. WinsStat = pwrResults->WinsStat;
  1305. }
  1306. }
  1307. void
  1308. CWinsResults::Set(WINSINTF_RESULTS_T * pwrResults)
  1309. {
  1310. if (pwrResults == NULL)
  1311. {
  1312. Clear();
  1313. }
  1314. else
  1315. {
  1316. NoOfOwners = pwrResults->NoOfOwners;
  1317. AddVersMaps.RemoveAll();
  1318. for (UINT i = 0; i < NoOfOwners; i++)
  1319. {
  1320. AddVersMaps.Add(pwrResults->AddVersMaps[i]);
  1321. }
  1322. MyMaxVersNo.QuadPart = pwrResults->MyMaxVersNo.QuadPart;
  1323. RefreshInterval = pwrResults->RefreshInterval;
  1324. TombstoneInterval = pwrResults->TombstoneInterval;
  1325. TombstoneTimeout = pwrResults->TombstoneTimeout;
  1326. VerifyInterval = pwrResults->VerifyInterval;
  1327. WinsPriorityClass = pwrResults->WinsPriorityClass;
  1328. NoOfWorkerThds = pwrResults->NoOfWorkerThds;
  1329. WinsStat = pwrResults->WinsStat;
  1330. }
  1331. }