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.

1557 lines
38 KiB

  1. //***************************************************************************
  2. //
  3. // UTILS.CPP
  4. //
  5. // Module: NLB Manager (client-side exe)
  6. //
  7. // Purpose: Misc utilities
  8. //
  9. // Copyright (c)2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. // History:
  12. //
  13. // 07/25/01 JosephJ Created
  14. //
  15. //***************************************************************************
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include "wlbsutil.h"
  19. #include "private.h"
  20. #include "utils.tmh"
  21. #define szNLBMGRREG_BASE_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NLB"
  22. LPCWSTR
  23. clustermode_description(
  24. const WLBS_REG_PARAMS *pParams
  25. );
  26. LPCWSTR
  27. rct_description(
  28. const WLBS_REG_PARAMS *pParams
  29. );
  30. // default constructor
  31. //
  32. ClusterProperties::ClusterProperties()
  33. {
  34. cIP = L"0.0.0.0";
  35. cSubnetMask = L"0.0.0.0";
  36. #define szDEFAULT_CLUSTER_NAME L"www.nlb-cluster.com"
  37. cFullInternetName = szDEFAULT_CLUSTER_NAME;
  38. cNetworkAddress = L"00-00-00-00-00-00";
  39. multicastSupportEnabled = false;
  40. remoteControlEnabled = false;
  41. password = L"";
  42. igmpSupportEnabled = false;
  43. clusterIPToMulticastIP = true;
  44. }
  45. // equality operator
  46. //
  47. bool
  48. ClusterProperties::operator==( const ClusterProperties& objToCompare )
  49. {
  50. bool btemp1, btemp2; // Variables to pass to below function. Returned values not used
  51. return !HaveClusterPropertiesChanged(objToCompare, &btemp1, &btemp2);
  52. }
  53. // equality operator
  54. //
  55. bool
  56. ClusterProperties::HaveClusterPropertiesChanged( const ClusterProperties& objToCompare,
  57. bool *pbOnlyClusterNameChanged,
  58. bool *pbClusterIpChanged)
  59. {
  60. *pbClusterIpChanged = false;
  61. *pbOnlyClusterNameChanged = false;
  62. if( cIP != objToCompare.cIP )
  63. {
  64. *pbClusterIpChanged = true;
  65. return true;
  66. }
  67. else if (
  68. ( cSubnetMask != objToCompare.cSubnetMask )
  69. ||
  70. ( cNetworkAddress != objToCompare.cNetworkAddress )
  71. ||
  72. ( multicastSupportEnabled != objToCompare.multicastSupportEnabled )
  73. ||
  74. ( igmpSupportEnabled != objToCompare.igmpSupportEnabled )
  75. ||
  76. ( clusterIPToMulticastIP != objToCompare.clusterIPToMulticastIP )
  77. )
  78. {
  79. return true;
  80. }
  81. else if (
  82. ( cFullInternetName != objToCompare.cFullInternetName )
  83. ||
  84. ( remoteControlEnabled != objToCompare.remoteControlEnabled )
  85. )
  86. {
  87. *pbOnlyClusterNameChanged = true;
  88. return true;
  89. }
  90. else if (
  91. ( remoteControlEnabled == true )
  92. &&
  93. ( password != objToCompare.password )
  94. )
  95. {
  96. *pbOnlyClusterNameChanged = true;
  97. return true;
  98. }
  99. return false;
  100. }
  101. // inequality operator
  102. //
  103. bool
  104. ClusterProperties::operator!=( const ClusterProperties& objToCompare )
  105. {
  106. bool btemp1, btemp2; // Variables to pass to below function. Returned values not used
  107. return HaveClusterPropertiesChanged(objToCompare, &btemp1, &btemp2);
  108. }
  109. // default constructor
  110. //
  111. HostProperties::HostProperties()
  112. {
  113. // TODO set all properties with default values.
  114. }
  115. // equality operator
  116. //
  117. bool
  118. HostProperties::operator==( const HostProperties& objToCompare )
  119. {
  120. if( ( hIP == objToCompare.hIP )
  121. &&
  122. ( hSubnetMask == objToCompare.hSubnetMask )
  123. &&
  124. ( hID == objToCompare.hID )
  125. &&
  126. ( initialClusterStateActive == objToCompare.initialClusterStateActive )
  127. &&
  128. ( machineName == objToCompare.machineName )
  129. )
  130. {
  131. return true;
  132. }
  133. else
  134. {
  135. return false;
  136. }
  137. }
  138. // inequality operator
  139. //
  140. bool
  141. HostProperties::operator!=( const HostProperties& objToCompare )
  142. {
  143. return !operator==(objToCompare );
  144. }
  145. _bstr_t
  146. CommonUtils::getCIPAddressCtrlString( CIPAddressCtrl& ip )
  147. {
  148. unsigned long addr;
  149. ip.GetAddress( addr );
  150. PUCHAR bp = (PUCHAR) &addr;
  151. wchar_t buf[BUF_SIZE];
  152. StringCbPrintf(buf, sizeof(buf), L"%d.%d.%d.%d", bp[3], bp[2], bp[1], bp[0] );
  153. return _bstr_t( buf );
  154. }
  155. void
  156. CommonUtils::fillCIPAddressCtrlString( CIPAddressCtrl& ip,
  157. const _bstr_t& ipAddress )
  158. {
  159. // set the IPAddress control to blank if ipAddress is zero.
  160. unsigned long addr = inet_addr( ipAddress );
  161. if( addr != 0 )
  162. {
  163. PUCHAR bp = (PUCHAR) &addr;
  164. ip.SetAddress( bp[0], bp[1], bp[2], bp[3] );
  165. }
  166. else
  167. {
  168. ip.ClearAddress();
  169. }
  170. }
  171. void
  172. CommonUtils::getVectorFromSafeArray( SAFEARRAY*& stringArray,
  173. vector<_bstr_t>& strings )
  174. {
  175. LONG count = stringArray->rgsabound[0].cElements;
  176. BSTR* pbstr;
  177. HRESULT hr;
  178. if( SUCCEEDED( SafeArrayAccessData( stringArray, ( void **) &pbstr)))
  179. {
  180. for( LONG x = 0; x < count; x++ )
  181. {
  182. strings.push_back( pbstr[x] );
  183. }
  184. hr = SafeArrayUnaccessData( stringArray );
  185. }
  186. }
  187. // checkIfValid
  188. //
  189. bool
  190. MIPAddress::checkIfValid( const _bstr_t& ipAddrToCheck )
  191. {
  192. // The validity rules are as follows
  193. //
  194. // The first byte (FB) has to be : 0 < FB < 224 && FB != 127
  195. // Note that 127 is loopback address.
  196. // hostid portion of an address cannot be zero.
  197. //
  198. // class A range is 1 - 126. hostid portion is last 3 bytes.
  199. // class B range is 128 - 191 hostid portion is last 2 bytes
  200. // class C range is 192 - 223 hostid portion is last byte.
  201. // split up the ipAddrToCheck into its 4 bytes.
  202. //
  203. WTokens tokens;
  204. tokens.init( wstring( ipAddrToCheck ) , L".");
  205. vector<wstring> byteTokens = tokens.tokenize();
  206. if( byteTokens.size() != 4 )
  207. {
  208. return false;
  209. }
  210. int firstByte = _wtoi( byteTokens[0].c_str() );
  211. int secondByte = _wtoi( byteTokens[1].c_str() );
  212. int thirdByte = _wtoi( byteTokens[2].c_str() );
  213. int fourthByte = _wtoi( byteTokens[3].c_str() );
  214. // check firstByte
  215. if ( ( firstByte > 0 )
  216. &&
  217. ( firstByte < 224 )
  218. &&
  219. ( firstByte != 127 )
  220. )
  221. {
  222. // check that host id portion is not zero.
  223. IPClass ipClass;
  224. getIPClass( ipAddrToCheck, ipClass );
  225. switch( ipClass )
  226. {
  227. case classA :
  228. // last three bytes should not be zero.
  229. if( ( _wtoi( byteTokens[1].c_str() ) == 0 )
  230. &&
  231. ( _wtoi( byteTokens[2].c_str() )== 0 )
  232. &&
  233. ( _wtoi( byteTokens[3].c_str() )== 0 )
  234. )
  235. {
  236. return false;
  237. }
  238. break;
  239. case classB :
  240. // last two bytes should not be zero.
  241. if( ( _wtoi( byteTokens[2].c_str() )== 0 )
  242. &&
  243. ( _wtoi( byteTokens[3].c_str() )== 0 )
  244. )
  245. {
  246. return false;
  247. }
  248. break;
  249. case classC :
  250. // last byte should not be zero.
  251. if( _wtoi( byteTokens[3].c_str() )
  252. == 0 )
  253. {
  254. return false;
  255. }
  256. break;
  257. default :
  258. // this should not have happened.
  259. return false;
  260. break;
  261. }
  262. return true;
  263. }
  264. else
  265. {
  266. return false;
  267. }
  268. }
  269. // getDefaultSubnetMask
  270. //
  271. bool
  272. MIPAddress::getDefaultSubnetMask( const _bstr_t& ipAddr,
  273. _bstr_t& subnetMask )
  274. {
  275. // first ensure that the ip is valid.
  276. //
  277. bool isValid = checkIfValid( ipAddr );
  278. if( isValid == false )
  279. {
  280. return false;
  281. }
  282. // get the class to which this ip belongs.
  283. // as this determines the subnet.
  284. IPClass ipClass;
  285. getIPClass( ipAddr,
  286. ipClass );
  287. switch( ipClass )
  288. {
  289. case classA :
  290. subnetMask = L"255.0.0.0";
  291. break;
  292. case classB :
  293. subnetMask = L"255.255.0.0";
  294. break;
  295. case classC :
  296. subnetMask = L"255.255.255.0";
  297. break;
  298. default :
  299. // this should not have happened.
  300. return false;
  301. break;
  302. }
  303. return true;
  304. }
  305. // getIPClass
  306. //
  307. bool
  308. MIPAddress::getIPClass( const _bstr_t& ipAddr,
  309. IPClass& ipClass )
  310. {
  311. // get the first byte of the ipAddr
  312. WTokens tokens;
  313. tokens.init( wstring( ipAddr ) , L".");
  314. vector<wstring> byteTokens = tokens.tokenize();
  315. if( byteTokens.size() == 0 )
  316. {
  317. return false;
  318. }
  319. int firstByte = _wtoi( byteTokens[0].c_str() );
  320. if( ( firstByte >= 1 )
  321. &&
  322. ( firstByte <= 126 )
  323. )
  324. {
  325. // classA
  326. ipClass = classA;
  327. return true;
  328. }
  329. else if( (firstByte >= 128 )
  330. &&
  331. (firstByte <= 191 )
  332. )
  333. {
  334. // classB
  335. ipClass = classB;
  336. return true;
  337. }
  338. else if( (firstByte >= 192 )
  339. &&
  340. (firstByte <= 223 )
  341. )
  342. {
  343. // classC
  344. ipClass = classC;
  345. return true;
  346. }
  347. else if( (firstByte >= 224 )
  348. &&
  349. (firstByte <= 239 )
  350. )
  351. {
  352. // classD
  353. ipClass = classD;
  354. return true;
  355. }
  356. else if( (firstByte >= 240 )
  357. &&
  358. (firstByte <= 247 )
  359. )
  360. {
  361. // classE
  362. ipClass = classE;
  363. return true;
  364. }
  365. else
  366. {
  367. // invalid net portiion.
  368. return false;
  369. }
  370. }
  371. bool
  372. MIPAddress::isValidIPAddressSubnetMaskPair( const _bstr_t& ipAddress,
  373. const _bstr_t& subnetMask )
  374. {
  375. if( IsValidIPAddressSubnetMaskPair( ipAddress, subnetMask ) == TRUE )
  376. {
  377. return true;
  378. }
  379. else
  380. {
  381. return false;
  382. }
  383. }
  384. bool
  385. MIPAddress::isContiguousSubnetMask( const _bstr_t& subnetMask )
  386. {
  387. if( IsContiguousSubnetMask( subnetMask ) == TRUE )
  388. {
  389. return true;
  390. }
  391. else
  392. {
  393. return false;
  394. }
  395. }
  396. MUsingCom::MUsingCom( DWORD type )
  397. : status( MUsingCom_SUCCESS )
  398. {
  399. HRESULT hr;
  400. // Initialize com.
  401. hr = CoInitializeEx(0, type );
  402. if ( FAILED(hr) )
  403. {
  404. // cout << "Failed to initialize COM library" << hr << endl;
  405. status = COM_FAILURE;
  406. }
  407. }
  408. // destructor
  409. MUsingCom::~MUsingCom()
  410. {
  411. CoUninitialize();
  412. }
  413. // getStatus
  414. MUsingCom::MUsingCom_Error
  415. MUsingCom::getStatus()
  416. {
  417. return status;
  418. }
  419. // static member definition.
  420. map< UINT, _bstr_t>
  421. ResourceString::resourceStrings;
  422. ResourceString* ResourceString::_instance = 0;
  423. // Instance
  424. //
  425. ResourceString*
  426. ResourceString::Instance()
  427. {
  428. if( _instance == 0 )
  429. {
  430. _instance = new ResourceString;
  431. }
  432. return _instance;
  433. }
  434. // GetIDString
  435. //
  436. const _bstr_t&
  437. ResourceString::GetIDString( UINT id )
  438. {
  439. // check if string has been loaded previously.
  440. if( resourceStrings.find( id ) == resourceStrings.end() )
  441. {
  442. // first time load.
  443. CString str;
  444. if( str.LoadString( id ) == 0 )
  445. {
  446. // no string mapping to this id.
  447. throw _com_error( WBEM_E_NOT_FOUND );
  448. }
  449. resourceStrings[id] = str;
  450. }
  451. return resourceStrings[ id ];
  452. }
  453. // GETRESOURCEIDSTRING
  454. // helper function.
  455. //
  456. const _bstr_t&
  457. GETRESOURCEIDSTRING( UINT id )
  458. {
  459. return ResourceString::GetIDString( id );
  460. }
  461. //
  462. // constructor
  463. WTokens::WTokens( wstring strToken, wstring strDelimit )
  464. : _strToken( strToken ), _strDelimit( strDelimit )
  465. {}
  466. //
  467. // default constructor
  468. WTokens::WTokens()
  469. {}
  470. //
  471. // destructor
  472. WTokens::~WTokens()
  473. {}
  474. //
  475. // tokenize
  476. vector<wstring>
  477. WTokens::tokenize()
  478. {
  479. vector<wstring> vecTokens;
  480. wchar_t* token;
  481. token = wcstok( (wchar_t *) _strToken.c_str() , _strDelimit.c_str() );
  482. while( token != NULL )
  483. {
  484. vecTokens.push_back( token );
  485. token = wcstok( NULL, _strDelimit.c_str() );
  486. }
  487. return vecTokens;
  488. }
  489. //
  490. void
  491. WTokens::init(
  492. wstring strToken,
  493. wstring strDelimit )
  494. {
  495. _strToken = strToken;
  496. _strDelimit = strDelimit;
  497. }
  498. void
  499. GetErrorCodeText(WBEMSTATUS wStat , _bstr_t& errText )
  500. {
  501. WCHAR rgch[128];
  502. UINT uErr = (UINT) wStat;
  503. LPCWSTR szErr = NULL;
  504. CLocalLogger log;
  505. switch(uErr)
  506. {
  507. case WBEM_E_ACCESS_DENIED:
  508. szErr = GETRESOURCEIDSTRING(IDS_ERROR_ACCESS_DENIED);
  509. break;
  510. case E_ACCESSDENIED:
  511. szErr = GETRESOURCEIDSTRING(IDS_ERROR_ACCESS_DENIED);
  512. break;
  513. case 0x800706ba: // RPC service unavailable
  514. // TODO: find the constant definition for this.
  515. szErr = GETRESOURCEIDSTRING(IDS_ERROR_NLB_NOT_FOUND);
  516. break;
  517. case WBEM_E_LOCAL_CREDENTIALS:
  518. szErr = GETRESOURCEIDSTRING(IDS_ERROR_INVALID_LOCAL_CREDENTIALS);
  519. break;
  520. default:
  521. log.Log(IDS_ERROR_CODE, (UINT) uErr);
  522. szErr = log.GetStringSafe();
  523. break;
  524. }
  525. errText = szErr;
  526. }
  527. UINT
  528. NlbMgrRegReadUINT(
  529. HKEY hKey,
  530. LPCWSTR szName,
  531. UINT Default
  532. )
  533. {
  534. LONG lRet;
  535. DWORD dwType;
  536. DWORD dwData;
  537. DWORD dwRet;
  538. dwData = sizeof(dwRet);
  539. lRet = RegQueryValueEx(
  540. hKey, // handle to key to query
  541. szName,
  542. NULL, // reserved
  543. &dwType, // address of buffer for value type
  544. (LPBYTE) &dwRet, // address of data buffer
  545. &dwData // address of data buffer size
  546. );
  547. if ( lRet != ERROR_SUCCESS
  548. || dwType != REG_DWORD
  549. || dwData != sizeof(dwData))
  550. {
  551. dwRet = (DWORD) Default;
  552. }
  553. return (UINT) dwRet;
  554. }
  555. VOID
  556. NlbMgrRegWriteUINT(
  557. HKEY hKey,
  558. LPCWSTR szName,
  559. UINT Value
  560. )
  561. {
  562. LONG lRet;
  563. lRet = RegSetValueEx(
  564. hKey, // handle to key to set value for
  565. szName,
  566. 0, // reserved
  567. REG_DWORD, // flag for value type
  568. (BYTE*) &Value,// address of value data
  569. sizeof(Value) // size of value data
  570. );
  571. if (lRet !=ERROR_SUCCESS)
  572. {
  573. // trace error
  574. }
  575. }
  576. HKEY
  577. NlbMgrRegCreateKey(
  578. LPCWSTR szSubKey
  579. )
  580. {
  581. WCHAR szKey[256];
  582. DWORD dwOptions = 0;
  583. HKEY hKey = NULL;
  584. ARRAYSTRCPY(szKey, szNLBMGRREG_BASE_KEY);
  585. if (szSubKey != NULL)
  586. {
  587. if (wcslen(szSubKey)>128)
  588. {
  589. // too long.
  590. goto end;
  591. }
  592. ARRAYSTRCAT(szKey, L"\\");
  593. ARRAYSTRCAT(szKey, szSubKey);
  594. }
  595. DWORD dwDisposition;
  596. LONG lRet;
  597. lRet = RegCreateKeyEx(
  598. HKEY_CURRENT_USER, // handle to an open key
  599. szKey, // address of subkey name
  600. 0, // reserved
  601. L"class", // address of class string
  602. 0, // special options flag
  603. KEY_ALL_ACCESS, // desired security access
  604. NULL, // address of key security structure
  605. &hKey, // address of buffer for opened handle
  606. &dwDisposition // address of disposition value buffer
  607. );
  608. if (lRet != ERROR_SUCCESS)
  609. {
  610. hKey = NULL;
  611. }
  612. end:
  613. return hKey;
  614. }
  615. void
  616. GetTimeAndDate(_bstr_t &bstrTime, _bstr_t &bstrDate)
  617. {
  618. WCHAR wszTime[128];
  619. WCHAR wszDate[128];
  620. ConvertTimeToTimeAndDateStrings(time(NULL), wszTime, ASIZECCH(wszTime), wszDate, ASIZECCH(wszDate));
  621. bstrTime = _bstr_t(wszTime);
  622. bstrDate = _bstr_t(wszDate);
  623. }
  624. VOID
  625. CLocalLogger::Log(
  626. IN UINT ResourceID,
  627. // IN LPCWSTR FormatString,
  628. ...
  629. )
  630. {
  631. DWORD dwRet;
  632. WCHAR wszFormat[2048];
  633. WCHAR wszBuffer[2048];
  634. HINSTANCE hInst = AfxGetInstanceHandle();
  635. if (!LoadString(hInst, ResourceID, wszFormat, ASIZE(wszFormat)-1))
  636. {
  637. TRACE_CRIT("LoadString returned 0, GetLastError() : 0x%x, Could not log message !!!", GetLastError());
  638. goto end;
  639. }
  640. va_list arglist;
  641. va_start (arglist, ResourceID);
  642. dwRet = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
  643. wszFormat,
  644. 0, // Message Identifier - Ignored for FORMAT_MESSAGE_FROM_STRING
  645. 0, // Language Identifier
  646. wszBuffer,
  647. ASIZE(wszBuffer)-1,
  648. &arglist);
  649. va_end (arglist);
  650. if (dwRet==0)
  651. {
  652. TRACE_CRIT("FormatMessage returned error : %u, Could not log message !!!", dwRet);
  653. goto end;
  654. }
  655. UINT uLen = wcslen(wszBuffer)+1; // 1 for extra NULL
  656. if ((m_LogSize < (m_CurrentOffset+uLen)))
  657. {
  658. //
  659. // Not enough space -- we double the buffer + some extra
  660. // and copy over the old log.
  661. //
  662. UINT uNewSize = 2*m_LogSize+uLen+1024;
  663. WCHAR *pTmp = new WCHAR[uNewSize];
  664. if (pTmp == NULL)
  665. {
  666. goto end;
  667. }
  668. if (m_CurrentOffset!=0)
  669. {
  670. CopyMemory(pTmp, m_pszLog, m_CurrentOffset*sizeof(WCHAR));
  671. pTmp[m_CurrentOffset] = 0;
  672. }
  673. delete[] m_pszLog;
  674. m_pszLog = pTmp;
  675. m_LogSize = uNewSize;
  676. }
  677. //
  678. // Having made sure there is enough space, copy over the new stuff
  679. //
  680. CopyMemory(m_pszLog+m_CurrentOffset, wszBuffer, uLen*sizeof(WCHAR));
  681. m_CurrentOffset += (uLen-1); // -1 for ending NULL.
  682. end:
  683. return;
  684. }
  685. VOID
  686. CLocalLogger::LogString(
  687. LPCWSTR wszBuffer
  688. )
  689. {
  690. UINT uLen = wcslen(wszBuffer)+1; // 1 for extra NULL
  691. if ((m_LogSize < (m_CurrentOffset+uLen)))
  692. {
  693. //
  694. // Not enough space -- we double the buffer + some extra
  695. // and copy over the old log.
  696. //
  697. UINT uNewSize = 2*m_LogSize+uLen+1024;
  698. WCHAR *pTmp = new WCHAR[uNewSize];
  699. if (pTmp == NULL)
  700. {
  701. goto end;
  702. }
  703. if (m_CurrentOffset!=0)
  704. {
  705. CopyMemory(pTmp, m_pszLog, m_CurrentOffset*sizeof(WCHAR));
  706. pTmp[m_CurrentOffset] = 0;
  707. }
  708. delete[] m_pszLog;
  709. m_pszLog = pTmp;
  710. m_LogSize = uNewSize;
  711. }
  712. //
  713. // Having made sure there is enough space, copy over the new stuff
  714. //
  715. CopyMemory(m_pszLog+m_CurrentOffset, wszBuffer, uLen*sizeof(WCHAR));
  716. m_CurrentOffset += (uLen-1); // -1 for ending NULL.
  717. end:
  718. return;
  719. }
  720. NLBERROR
  721. AnalyzeNlbConfiguration(
  722. IN const NLB_EXTENDED_CLUSTER_CONFIGURATION &Cfg,
  723. IN OUT CLocalLogger &logErrors
  724. )
  725. //
  726. // logErrors - a log of config errors
  727. //
  728. {
  729. NLBERROR nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  730. WBEMSTATUS wStatus;
  731. const WLBS_REG_PARAMS *pParams = &Cfg.NlbParams;
  732. BOOL fRet = FALSE;
  733. NlbIpAddressList addrList;
  734. BOOL fError = FALSE;
  735. //
  736. // We expect NLB to be bound and have a valid configuration (i.e.,
  737. // one wholse NlbParams contains initialized data).
  738. //
  739. if (!Cfg.IsValidNlbConfig())
  740. {
  741. logErrors.Log(IDS_LOG_INVALID_CLUSTER_SPECIFICATION);
  742. nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  743. goto end;
  744. }
  745. //
  746. // Make a copy of the the tcpip address list in addrList
  747. //
  748. fRet = addrList.Set(Cfg.NumIpAddresses, Cfg.pIpAddressInfo, 0);
  749. if (!fRet)
  750. {
  751. TRACE_CRIT(L"Unable to copy old IP address list");
  752. nerr = NLBERR_RESOURCE_ALLOCATION_FAILURE;
  753. logErrors.Log(IDS_LOG_RESOURCE_ALLOCATION_FAILURE);
  754. fError = TRUE;
  755. goto end;
  756. }
  757. //
  758. // Check stuff related to the cluster ip and subnet.
  759. //
  760. do
  761. {
  762. UINT uClusterIp = 0;
  763. const NLB_IP_ADDRESS_INFO *pClusterIpInfo = NULL;
  764. //
  765. // Check that IP is valid
  766. //
  767. {
  768. wStatus = CfgUtilsValidateNetworkAddress(
  769. pParams->cl_ip_addr,
  770. &uClusterIp,
  771. NULL,
  772. NULL
  773. );
  774. if (FAILED(wStatus))
  775. {
  776. logErrors.Log(IDS_LOG_INVALID_CIP, pParams->cl_ip_addr);
  777. nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  778. fError = TRUE;
  779. goto end;
  780. }
  781. }
  782. //
  783. // Check that cluster IP is present in tcpip address list
  784. //
  785. {
  786. pClusterIpInfo = addrList.Find(pParams->cl_ip_addr);
  787. if (pClusterIpInfo == NULL)
  788. {
  789. logErrors.Log(IDS_LOG_CIP_MISSING_FROM_TCPIP, pParams->cl_ip_addr);
  790. fError = TRUE; // we keep going...
  791. }
  792. }
  793. //
  794. // Check that the cluster subnet matches what is in the tcpip address
  795. // list.
  796. //
  797. if (pClusterIpInfo != NULL)
  798. {
  799. if (_wcsicmp(pParams->cl_net_mask, pClusterIpInfo->SubnetMask))
  800. {
  801. logErrors.Log(
  802. IDS_LOG_CIP_SUBNET_MASK_MISMATCH,
  803. pParams->cl_net_mask,
  804. pClusterIpInfo->SubnetMask
  805. );
  806. fError = TRUE; // we keep going...
  807. }
  808. }
  809. } while (FALSE);
  810. //
  811. // Check stuff related to the dedicated IP (if present)
  812. //
  813. do
  814. {
  815. const NLB_IP_ADDRESS_INFO *pDedicatedIpInfo = NULL;
  816. //
  817. // If empty dip, bail...
  818. //
  819. if (Cfg.IsBlankDedicatedIp())
  820. {
  821. break;
  822. }
  823. //
  824. // Check that DIP doesn't match CIP
  825. //
  826. if (!_wcsicmp(pParams->cl_ip_addr, pParams->ded_ip_addr))
  827. {
  828. logErrors.Log(IDS_LOG_CIP_EQUAL_DIP, pParams->cl_ip_addr);
  829. fError = TRUE;
  830. }
  831. //
  832. // Check that the DIP is the 1st address in tcpip's address list.
  833. //
  834. {
  835. const NLB_IP_ADDRESS_INFO *pTmpIpInfo = NULL;
  836. pDedicatedIpInfo = addrList.Find(pParams->ded_ip_addr);
  837. if (pDedicatedIpInfo == NULL)
  838. {
  839. logErrors.Log(IDS_LOG_DIP_MISSING_FROM_TCPIP, pParams->ded_ip_addr);
  840. fError = TRUE; // we keep going...
  841. }
  842. else
  843. {
  844. pTmpIpInfo = addrList.Find(NULL); // returns the 1st
  845. if (pTmpIpInfo != pDedicatedIpInfo)
  846. {
  847. logErrors.Log(IDS_LOG_DIP_NOT_FIRST_IN_TCPIP, pParams->ded_ip_addr);
  848. }
  849. }
  850. }
  851. //
  852. // Check that the DIP subnet matches that in tcpip's address list.
  853. //
  854. if (pDedicatedIpInfo != NULL)
  855. {
  856. if (_wcsicmp(pParams->ded_net_mask, pDedicatedIpInfo->SubnetMask))
  857. {
  858. logErrors.Log(
  859. IDS_LOG_DIP_SUBNET_MASK_MISMATCH,
  860. pParams->ded_net_mask,
  861. pDedicatedIpInfo->SubnetMask
  862. );
  863. fError = TRUE; // we keep going...
  864. }
  865. }
  866. } while (FALSE);
  867. //
  868. // Check host priority
  869. //
  870. // NOTHING to do.
  871. //
  872. //
  873. // Check port rules
  874. //
  875. {
  876. WLBS_PORT_RULE *pRules = NULL;
  877. UINT NumRules=0;
  878. LPCWSTR szAllVip = GETRESOURCEIDSTRING(IDS_REPORT_VIP_ALL);
  879. LPCWSTR szPrevVip = NULL;
  880. wStatus = CfgUtilGetPortRules(pParams, &pRules, &NumRules);
  881. if (FAILED(wStatus))
  882. {
  883. logErrors.Log(IDS_LOG_CANT_EXTRACT_PORTRULES);
  884. fError = TRUE;
  885. nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  886. goto end;
  887. }
  888. for (UINT u = 0; u< NumRules; u++)
  889. {
  890. LPCWSTR szVip = pRules[u].virtual_ip_addr;
  891. const NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  892. //
  893. // Skip the "all-vips" (255.255.255.255) case...
  894. //
  895. if (!lstrcmpi(szVip, szAllVip))
  896. {
  897. continue;
  898. }
  899. if (!lstrcmpi(szVip, L"255.255.255.255"))
  900. {
  901. continue;
  902. }
  903. //
  904. // SKip if we've already checked this VIP (assumes the vips
  905. // are in sorted order)
  906. //
  907. if (szPrevVip != NULL && !lstrcmpi(szVip, szPrevVip))
  908. {
  909. continue;
  910. }
  911. szPrevVip = szVip;
  912. //
  913. // Check that the VIP is present in tcpip's address list.
  914. //
  915. pIpInfo = addrList.Find(szVip); // returns the 1st
  916. if (pIpInfo == NULL)
  917. {
  918. logErrors.Log(IDS_LOG_VIP_NOT_IN_TCPIP, szVip);
  919. fError = TRUE; // We continue...
  920. }
  921. //
  922. // Check that VIPs don't match DIPS.
  923. //
  924. {
  925. if (!lstrcmpi(szVip, pParams->ded_ip_addr))
  926. {
  927. logErrors.Log(IDS_LOG_PORTVIP_MATCHES_DIP, szVip);
  928. }
  929. }
  930. }
  931. }
  932. if (fError)
  933. {
  934. nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  935. }
  936. else
  937. {
  938. nerr = NLBERR_OK;
  939. }
  940. end:
  941. return nerr;
  942. }
  943. NLBERROR
  944. AnalyzeNlbConfigurationPair(
  945. IN const NLB_EXTENDED_CLUSTER_CONFIGURATION &Cfg,
  946. IN const NLB_EXTENDED_CLUSTER_CONFIGURATION &OtherCfg,
  947. IN BOOL fOtherIsCluster,
  948. IN BOOL fCheckOtherForConsistancy,
  949. OUT BOOL &fConnectivityChange,
  950. IN OUT CLocalLogger &logErrors,
  951. IN OUT CLocalLogger &logDifferences
  952. )
  953. {
  954. NLBERROR nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  955. WBEMSTATUS wStatus;
  956. const WLBS_REG_PARAMS *pParams = &Cfg.NlbParams;
  957. const WLBS_REG_PARAMS *pOtherParams = &OtherCfg.NlbParams;
  958. BOOL fRet = FALSE;
  959. NlbIpAddressList addrList;
  960. NlbIpAddressList otherAddrList;
  961. BOOL fError = FALSE;
  962. BOOL fOtherChange = FALSE;
  963. fConnectivityChange = FALSE;
  964. //
  965. // We expect NLB to be bound and have a valid configuration (i.e.,
  966. // one wholse NlbParams contains initialized data).
  967. //
  968. if (!Cfg.IsValidNlbConfig())
  969. {
  970. logErrors.Log(IDS_LOG_INVALID_CLUSTER_SPECIFICATION);
  971. nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
  972. fError = TRUE;
  973. goto end;
  974. }
  975. if (!OtherCfg.IsValidNlbConfig())
  976. {
  977. if (OtherCfg.IsNlbBound())
  978. {
  979. // TODO:
  980. }
  981. else
  982. {
  983. // TODO:
  984. }
  985. nerr = NLBERR_OK;
  986. fConnectivityChange = TRUE;
  987. goto end;
  988. }
  989. //
  990. // Make a copy of the the tcpip address list in addrList
  991. //
  992. fRet = addrList.Set(Cfg.NumIpAddresses, Cfg.pIpAddressInfo, 0);
  993. if (!fRet)
  994. {
  995. TRACE_CRIT(L"Unable to copy IP address list");
  996. nerr = NLBERR_RESOURCE_ALLOCATION_FAILURE;
  997. logErrors.Log(IDS_LOG_RESOURCE_ALLOCATION_FAILURE);
  998. fError = TRUE;
  999. goto end;
  1000. }
  1001. //
  1002. // Make a copy of the other tcpip address list in otherAddrList
  1003. //
  1004. fRet = otherAddrList.Set(OtherCfg.NumIpAddresses, OtherCfg.pIpAddressInfo, 0);
  1005. if (!fRet)
  1006. {
  1007. TRACE_CRIT(L"Unable to copy other IP address list");
  1008. nerr = NLBERR_RESOURCE_ALLOCATION_FAILURE;
  1009. logErrors.Log(IDS_LOG_RESOURCE_ALLOCATION_FAILURE);
  1010. fError = TRUE;
  1011. goto end;
  1012. }
  1013. //
  1014. // Check for changes in IP address lists
  1015. //
  1016. {
  1017. UINT u;
  1018. BOOL fWriteHeader=TRUE;
  1019. //
  1020. // Look for added
  1021. //
  1022. fWriteHeader=TRUE;
  1023. for (u=0;u<Cfg.NumIpAddresses; u++)
  1024. {
  1025. NLB_IP_ADDRESS_INFO *pIpInfo = Cfg.pIpAddressInfo+u;
  1026. const NLB_IP_ADDRESS_INFO *pOtherIpInfo = NULL;
  1027. pOtherIpInfo = otherAddrList.Find(pIpInfo->IpAddress);
  1028. if (pOtherIpInfo == NULL)
  1029. {
  1030. // found a new one!
  1031. fConnectivityChange = TRUE;
  1032. if (fWriteHeader)
  1033. {
  1034. logDifferences.Log(IDS_LOG_ADDED_IPADDR_HEADER);
  1035. fWriteHeader=FALSE;
  1036. }
  1037. logDifferences.Log(
  1038. IDS_LOG_ADDED_IPADDR,
  1039. pIpInfo->IpAddress,
  1040. pIpInfo->SubnetMask
  1041. );
  1042. }
  1043. }
  1044. //
  1045. // Look for removed
  1046. //
  1047. fWriteHeader=TRUE;
  1048. for (u=0;u<OtherCfg.NumIpAddresses; u++)
  1049. {
  1050. NLB_IP_ADDRESS_INFO *pOtherIpInfo = OtherCfg.pIpAddressInfo+u;
  1051. const NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  1052. pIpInfo = addrList.Find(pOtherIpInfo->IpAddress);
  1053. if (pIpInfo == NULL)
  1054. {
  1055. // found a removed one!
  1056. fConnectivityChange = TRUE;
  1057. if (fWriteHeader)
  1058. {
  1059. logDifferences.Log(IDS_LOG_REMOVED_IPADDR_HEADER);
  1060. fWriteHeader = FALSE;
  1061. }
  1062. logDifferences.Log(
  1063. IDS_LOG_REMOVE_IPADDR,
  1064. pOtherIpInfo->IpAddress,
  1065. pOtherIpInfo->SubnetMask
  1066. );
  1067. }
  1068. }
  1069. //
  1070. // Look for modified
  1071. //
  1072. fWriteHeader=TRUE;
  1073. for (u=0;u<Cfg.NumIpAddresses; u++)
  1074. {
  1075. NLB_IP_ADDRESS_INFO *pIpInfo = Cfg.pIpAddressInfo+u;
  1076. const NLB_IP_ADDRESS_INFO *pOtherIpInfo = NULL;
  1077. pOtherIpInfo = otherAddrList.Find(pIpInfo->IpAddress);
  1078. if ( pOtherIpInfo != NULL
  1079. && lstrcmpi(pIpInfo->SubnetMask, pOtherIpInfo->SubnetMask))
  1080. {
  1081. // found a modified one!
  1082. fConnectivityChange = TRUE;
  1083. if (fWriteHeader)
  1084. {
  1085. logDifferences.Log(IDS_LOG_MODIFIED_IPADDR_HEADER);
  1086. fWriteHeader = FALSE;
  1087. }
  1088. logDifferences.Log(
  1089. IDS_LOG_MODIFIED_IPADDR,
  1090. pOtherIpInfo->IpAddress,
  1091. pOtherIpInfo->SubnetMask,
  1092. pIpInfo->SubnetMask
  1093. );
  1094. }
  1095. }
  1096. }
  1097. //
  1098. // Cluster name
  1099. //
  1100. {
  1101. if (lstrcmpi(pOtherParams->domain_name, pParams->domain_name))
  1102. {
  1103. logDifferences.Log(
  1104. IDS_LOG_MODIFIED_CLUSTER_NAME,
  1105. pOtherParams->domain_name,
  1106. pParams->domain_name
  1107. );
  1108. fConnectivityChange = TRUE;
  1109. }
  1110. }
  1111. //
  1112. // Check for cluster traffic mode change
  1113. //
  1114. {
  1115. BOOL fModeChange = FALSE;
  1116. if (pParams->mcast_support != pOtherParams->mcast_support)
  1117. {
  1118. fModeChange = TRUE;
  1119. }
  1120. else if (pParams->mcast_support &&
  1121. pParams->fIGMPSupport != pOtherParams->fIGMPSupport)
  1122. {
  1123. fModeChange = TRUE;
  1124. }
  1125. if (fModeChange)
  1126. {
  1127. LPCWSTR szClusterMode = clustermode_description(pParams);
  1128. LPCWSTR szOtherClusterMode = clustermode_description(pOtherParams);
  1129. logDifferences.Log(
  1130. IDS_LOG_MODIFIED_TRAFFIC_MODE,
  1131. szOtherClusterMode,
  1132. szClusterMode
  1133. );
  1134. fConnectivityChange = TRUE;
  1135. }
  1136. }
  1137. //
  1138. // Check if there is change in rct or a new rct password specified...
  1139. //
  1140. {
  1141. if (Cfg.GetRemoteControlEnabled() !=
  1142. OtherCfg.GetRemoteControlEnabled())
  1143. {
  1144. LPCWSTR szRctDescription = rct_description(pParams);
  1145. LPCWSTR szOtherRctDescription = rct_description(pOtherParams);
  1146. logDifferences.Log(
  1147. IDS_LOG_MODIFIED_RCT,
  1148. szOtherRctDescription,
  1149. szRctDescription
  1150. );
  1151. fOtherChange = TRUE;
  1152. }
  1153. else
  1154. {
  1155. LPCWSTR szNewPwd = Cfg.GetNewRemoteControlPasswordRaw();
  1156. if (szNewPwd != NULL)
  1157. {
  1158. logDifferences.Log(IDS_LOG_NEW_RCT_PWD);
  1159. fOtherChange = TRUE;
  1160. }
  1161. }
  1162. }
  1163. //
  1164. // Port rules
  1165. //
  1166. {
  1167. }
  1168. nerr = NLBERR_OK;
  1169. end:
  1170. return nerr;
  1171. }
  1172. LPCWSTR
  1173. clustermode_description(
  1174. const WLBS_REG_PARAMS *pParams
  1175. )
  1176. {
  1177. LPCWSTR szClusterMode = GETRESOURCEIDSTRING(IDS_DETAILS_HOST_CM_UNICAST);
  1178. if (pParams->mcast_support)
  1179. {
  1180. if (pParams->fIGMPSupport)
  1181. {
  1182. szClusterMode = GETRESOURCEIDSTRING(IDS_DETAILS_HOST_CM_IGMP);
  1183. }
  1184. else
  1185. {
  1186. szClusterMode = GETRESOURCEIDSTRING(IDS_DETAILS_HOST_CM_MULTI);
  1187. }
  1188. }
  1189. return szClusterMode;
  1190. }
  1191. LPCWSTR
  1192. rct_description(
  1193. const WLBS_REG_PARAMS *pParams
  1194. )
  1195. {
  1196. LPCWSTR szClusterRctEnabled;
  1197. if (pParams->rct_enabled)
  1198. {
  1199. szClusterRctEnabled = GETRESOURCEIDSTRING(IDS_DETAILS_HOST_RCT_ENABLED);
  1200. }
  1201. else
  1202. {
  1203. szClusterRctEnabled = GETRESOURCEIDSTRING(IDS_DETAILS_HOST_RCT_DISABLED);
  1204. }
  1205. return szClusterRctEnabled;
  1206. }
  1207. void
  1208. ProcessMsgQueue()
  1209. {
  1210. theApplication.ProcessMsgQueue();
  1211. }
  1212. BOOL
  1213. PromptForEncryptedCreds(
  1214. IN HWND hWnd,
  1215. IN LPCWSTR szCaptionText,
  1216. IN LPCWSTR szMessageText,
  1217. IN OUT LPWSTR szUserName,
  1218. IN UINT cchUserName,
  1219. IN OUT LPWSTR szPassword, // encrypted password
  1220. IN UINT cchPassword // size of szPassword
  1221. )
  1222. /*
  1223. Decrypts szPassword, then brings UI prompting the user to change
  1224. the password, then encrypts the resultant password.
  1225. */
  1226. {
  1227. TRACE_INFO("-> %!FUNC!");
  1228. BOOL fRet = FALSE;
  1229. DWORD dwRet = 0;
  1230. CREDUI_INFO UiInfo;
  1231. PCTSTR pszTargetName= L"%computername%";
  1232. WCHAR rgUserName[CREDUI_MAX_USERNAME_LENGTH+1];
  1233. WCHAR rgClearPassword[CREDUI_MAX_PASSWORD_LENGTH+1];
  1234. WCHAR rgEncPassword[MAX_ENCRYPTED_PASSWORD_LENGTH];
  1235. BOOL fSave = FALSE;
  1236. DWORD dwFlags = 0;
  1237. HRESULT hr;
  1238. rgUserName[0] = 0;
  1239. rgClearPassword[0] = 0;
  1240. rgEncPassword[0] = 0;
  1241. hr = ARRAYSTRCPY(rgUserName, szUserName);
  1242. if (hr != S_OK)
  1243. {
  1244. TRACE_CRIT(L"rgUserName buffer too small for szUserName");
  1245. goto end;
  1246. }
  1247. //
  1248. // Decrypt the password...
  1249. // WARNING: after decryption we need to be sure to zero-out
  1250. // the clear-text pwd before returning from this function.
  1251. //
  1252. // Special case: If enc pwd is "", we "decrypt" it to "".
  1253. //
  1254. if (*szPassword == 0)
  1255. {
  1256. *rgClearPassword = 0;
  1257. fRet = TRUE;
  1258. }
  1259. else
  1260. {
  1261. fRet = CfgUtilDecryptPassword(
  1262. szPassword,
  1263. ASIZE(rgClearPassword),
  1264. rgClearPassword
  1265. );
  1266. }
  1267. if (!fRet)
  1268. {
  1269. TRACE_CRIT(L"CfgUtilDecryptPassword fails! -- bailing!");
  1270. goto end;
  1271. }
  1272. ZeroMemory(&UiInfo, sizeof(UiInfo));
  1273. UiInfo.cbSize = sizeof(CREDUI_INFO);
  1274. UiInfo.hwndParent = hWnd;
  1275. UiInfo.pszMessageText = szMessageText;
  1276. UiInfo.pszCaptionText = szCaptionText;
  1277. UiInfo.hbmBanner = NULL; // use default.
  1278. //
  1279. // Specifying DO_NOT_PERSIST and GENERIC_CREDENTIALS disables all syntax
  1280. // checking, so a null username can be specified.
  1281. //
  1282. dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST
  1283. | CREDUI_FLAGS_GENERIC_CREDENTIALS
  1284. // | CREDUI_FLAGS_VALIDATE_USERNAME
  1285. // | CREDUI_FLAGS_COMPLETE_USERNAME
  1286. // | CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS
  1287. ;
  1288. dwRet = CredUIPromptForCredentials (
  1289. &UiInfo,
  1290. pszTargetName,
  1291. NULL, // Reserved
  1292. 0, // dwAuthError
  1293. rgUserName,
  1294. ASIZE(rgUserName),
  1295. rgClearPassword,
  1296. ASIZE(rgClearPassword),
  1297. &fSave,
  1298. dwFlags
  1299. );
  1300. if (dwRet != 0)
  1301. {
  1302. TRACE_CRIT(L"CredUIPromptForCredentials fails. dwRet = 0x%x", dwRet);
  1303. fRet = FALSE;
  1304. }
  1305. else
  1306. {
  1307. if (*rgUserName == 0)
  1308. {
  1309. *rgEncPassword=0; // we ignore the password field in this case.
  1310. fRet = TRUE;
  1311. }
  1312. else
  1313. {
  1314. //
  1315. // TODO: prepend %computername% if required.
  1316. //
  1317. fRet = CfgUtilEncryptPassword(
  1318. rgClearPassword,
  1319. ASIZE(rgEncPassword),
  1320. rgEncPassword
  1321. );
  1322. }
  1323. if (!fRet)
  1324. {
  1325. TRACE_CRIT("CfgUtilEncryptPassword fails");
  1326. }
  1327. else
  1328. {
  1329. //
  1330. // We want to make sure we will succeed before we overwrite
  1331. // the user's passed-in buffers for username and password...
  1332. //
  1333. UINT uLen = wcslen(rgEncPassword);
  1334. if (uLen >= cchPassword)
  1335. {
  1336. TRACE_CRIT(L"cchPassword is too small");
  1337. fRet = FALSE;
  1338. }
  1339. uLen = wcslen(rgUserName);
  1340. if(uLen >= cchUserName)
  1341. {
  1342. TRACE_CRIT(L"cchUserName is too small");
  1343. fRet = FALSE;
  1344. }
  1345. }
  1346. if (fRet)
  1347. {
  1348. (void)StringCchCopy(szPassword, cchPassword, rgEncPassword);
  1349. (void)StringCchCopy(szUserName, cchUserName, rgUserName);
  1350. }
  1351. }
  1352. end:
  1353. SecureZeroMemory(rgClearPassword, sizeof(rgClearPassword));
  1354. TRACE_INFO("<- %!FUNC! returns %d", (int) fRet);
  1355. return fRet;
  1356. }