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.

1809 lines
54 KiB

  1. /******************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. NlbsNic.CPP -- WMI provider class implementation
  4. Generated by Microsoft WMI Code Generation Engine
  5. TO DO: - See individual function headers
  6. - When linking, make sure you link to framedyd.lib &
  7. msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).
  8. Description:
  9. ******************************************************************/
  10. // History:
  11. // --------
  12. //
  13. // Revised by : mhakim
  14. // Date : 02-12-01
  15. // Reason : Added password support.
  16. //
  17. // Revised by : mhakim
  18. // Date : 02-16-01
  19. // Reason : Added friendly name support.
  20. //
  21. // Reason : filling out version info. This was being not
  22. // done previously in GetObject.
  23. #include <fwcommon.h> // This must be the first include.
  24. #include "NlbsNic.h"
  25. #include "NICCard.h"
  26. #include "MNicInfo.h"
  27. #include "MIPAddressAdmin.h"
  28. #include "MNLBProviderSetting.h"
  29. #include "Common.h"
  30. #include "MUsingCom.h"
  31. #include "WTokens.h"
  32. #include "MNLBMachine.h"
  33. #include <winbase.h> // For Sleep
  34. #include <windows.h> // For Sleep
  35. #include <string>
  36. //#include <wlbsiocl.h>
  37. #include "wlbsconfig.h"
  38. #include "myntrtl.h"
  39. #include "wlbsparm.h"
  40. #include "cfgutils.h"
  41. #include "updatecfg.h"
  42. #include "nlbsnic.tmh"
  43. using namespace std;
  44. MUsingCom com;
  45. BOOL g_UpdateConfigurationEnabled = FALSE;
  46. WBEMSTATUS
  47. ProvGetClusterConfiguration(
  48. CInstance *pInParams,
  49. CInstance *pOutParams
  50. );
  51. WBEMSTATUS
  52. ProvUpdateClusterConfiguration(
  53. CInstance *pInParams,
  54. CInstance *pOutParams
  55. );
  56. WBEMSTATUS
  57. ProvQueryConfigurationUpdateStatus(
  58. CInstance *pInParams,
  59. CInstance *pOutParams
  60. );
  61. WCHAR*
  62. CNlbsNic::version = L"03-09-2001";
  63. // TO DO: Replace "NameSpace" with the appropriate namespace for your
  64. // provider instance. For instance: "root\\default or "root\\cimv2".
  65. // DONE : mhakim
  66. //===================================================================
  67. CNlbsNic MyNlbsNicSet (PROVIDER_NAME_NLBSNIC, L"root\\microsoftnlb") ;
  68. // Property names
  69. //===============
  70. const static WCHAR* pAdapterGuid = L"AdapterGuid" ;
  71. const static WCHAR* pDependent = L"Dependent" ;
  72. const static WCHAR* pFriendlyName = L"FriendlyName" ;
  73. const static WCHAR* pFullName = L"FullName" ;
  74. const static WCHAR* pVersion = L"Version" ;
  75. /*****************************************************************************
  76. *
  77. * FUNCTION : CNlbsNic::CNlbsNic
  78. *
  79. * DESCRIPTION : Constructor
  80. *
  81. * INPUTS : none
  82. *
  83. * RETURNS : nothing
  84. *
  85. * COMMENTS : Calls the Provider constructor.
  86. *
  87. *****************************************************************************/
  88. CNlbsNic::CNlbsNic (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) :
  89. Provider(lpwszName, lpwszNameSpace)
  90. {
  91. //
  92. // Enable WMI event tracing
  93. //
  94. WPP_INIT_TRACING(L"Microsoft\\NLB\\TPROV");
  95. if (g_UpdateConfigurationEnabled)
  96. {
  97. //
  98. // Initialize update config
  99. //
  100. NlbConfigurationUpdate::Initialize();
  101. }
  102. }
  103. /*****************************************************************************
  104. *
  105. * FUNCTION : CNlbsNic::~CNlbsNic
  106. *
  107. * DESCRIPTION : Destructor
  108. *
  109. * INPUTS : none
  110. *
  111. * RETURNS : nothing
  112. *
  113. * COMMENTS :
  114. *
  115. *****************************************************************************/
  116. CNlbsNic::~CNlbsNic ()
  117. {
  118. if (g_UpdateConfigurationEnabled)
  119. {
  120. //
  121. // Deinitialize update config code
  122. //
  123. NlbConfigurationUpdate::Deinitialize();
  124. }
  125. //
  126. // Disable WMI event tracing
  127. //
  128. WPP_CLEANUP();
  129. }
  130. /*****************************************************************************
  131. *
  132. * FUNCTION : CNlbsNic::EnumerateInstances
  133. *
  134. * DESCRIPTION : Returns all the instances of this class.
  135. *
  136. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  137. * A long that contains the flags described in
  138. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  139. * flags are handled by (and filtered out by) WinMgmt:
  140. * WBEM_FLAG_DEEP
  141. * WBEM_FLAG_SHALLOW
  142. * WBEM_FLAG_RETURN_IMMEDIATELY
  143. * WBEM_FLAG_FORWARD_ONLY
  144. * WBEM_FLAG_BIDIRECTIONAL
  145. *
  146. * RETURNS : WBEM_S_NO_ERROR if successful
  147. *
  148. * COMMENTS : TO DO: All instances on the machine should be returned here and
  149. * all properties that this class knows how to populate must
  150. * be filled in. If there are no instances, return
  151. * WBEM_S_NO_ERROR. It is not an error to have no instances.
  152. * If you are implementing a 'method only' provider, you
  153. * should remove this method.
  154. * DONE: mhakim
  155. *
  156. *****************************************************************************/
  157. HRESULT CNlbsNic::EnumerateInstances ( MethodContext* pMethodContext, long lFlags )
  158. {
  159. HRESULT hRes = WBEM_S_NO_ERROR;
  160. // get information about all nics on the machine.
  161. //
  162. NICCard::NICCard_Error errN;
  163. vector< NICCard::Info > nicList;
  164. errN = NICCard::getNics( &nicList );
  165. if( errN != NICCard::NICCard_SUCCESS )
  166. {
  167. return WBEM_E_NOT_FOUND;
  168. }
  169. // populate all instances.
  170. //
  171. for( int i = 0; i < nicList.size(); ++i )
  172. {
  173. CInstance* pInstance = CreateNewInstance(pMethodContext);
  174. pInstance->SetCHString(pAdapterGuid, nicList[i].guid.c_str() );
  175. pInstance->SetCHString(pFriendlyName, nicList[i].friendlyName.c_str() );
  176. pInstance->SetCHString(pFullName, nicList[i].fullName.c_str() );
  177. pInstance->SetCHString(pVersion, version );
  178. hRes = pInstance->Commit();
  179. pInstance->Release();
  180. }
  181. hRes = WBEM_S_NO_ERROR;
  182. return hRes ;
  183. }
  184. /*****************************************************************************
  185. *
  186. * FUNCTION : CNlbsNic::GetObject
  187. *
  188. * DESCRIPTION : Find a single instance based on the key properties for the
  189. * class.
  190. *
  191. * INPUTS : A pointer to a CInstance object containing the key properties.
  192. * A long that contains the flags described in
  193. * IWbemServices::GetObjectAsync.
  194. *
  195. * RETURNS : WBEM_S_NO_ERROR if the instance can be found
  196. * WBEM_E_NOT_FOUND if the instance described by the key properties
  197. * could not be found
  198. * WBEM_E_FAILED if the instance could be found but another error
  199. * occurred.
  200. *
  201. * COMMENTS : If you are implementing a 'method only' provider, you should
  202. * remove this method.
  203. *
  204. *****************************************************************************/
  205. HRESULT CNlbsNic::GetObject ( CInstance* pInstance, long lFlags )
  206. {
  207. HRESULT hr = WBEM_E_NOT_FOUND;
  208. CHString sTemp;
  209. pInstance->GetCHString( L"FullName",
  210. sTemp );
  211. wstring fullName = sTemp;
  212. NICCard::NICCard_Error errN;
  213. vector< NICCard::Info > nicList;
  214. errN = NICCard::getNics( &nicList );
  215. if( errN != NICCard::NICCard_SUCCESS )
  216. {
  217. return WBEM_E_NOT_FOUND;
  218. }
  219. // populate all instances.
  220. //
  221. hr = WBEM_E_NOT_FOUND;
  222. for( int i = 0; i < nicList.size(); ++i )
  223. {
  224. if( nicList[i].fullName == fullName )
  225. {
  226. // found specific instance.
  227. //
  228. pInstance->SetCHString(pAdapterGuid, nicList[i].guid.c_str() );
  229. pInstance->SetCHString(pFriendlyName, nicList[i].friendlyName.c_str() );
  230. pInstance->SetCHString(pFullName, nicList[i].fullName.c_str() );
  231. pInstance->SetCHString(pVersion, version );
  232. hr = WBEM_S_NO_ERROR;
  233. break;
  234. }
  235. }
  236. return hr;
  237. }
  238. /*****************************************************************************
  239. *
  240. * FUNCTION : CNlbsNic::ExecQuery
  241. *
  242. * DESCRIPTION : You are passed a method context to use in the creation of
  243. * instances that satisfy the query, and a CFrameworkQuery
  244. * which describes the query. Create and populate all
  245. * instances which satisfy the query. You may return more
  246. * instances or more properties than are requested and WinMgmt
  247. * will post filter out any that do not apply.
  248. *
  249. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  250. * A query object describing the query to satisfy.
  251. * A long that contains the flags described in
  252. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  253. * flags are handled by (and filtered out by) WinMgmt:
  254. * WBEM_FLAG_FORWARD_ONLY
  255. * WBEM_FLAG_BIDIRECTIONAL
  256. * WBEM_FLAG_ENSURE_LOCATABLE
  257. *
  258. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for
  259. * this class or if the query is too complex for this class
  260. * to interpret. The framework will call the EnumerateInstances
  261. * function instead and let Winmgmt post filter.
  262. * WBEM_E_FAILED if the query failed
  263. * WBEM_S_NO_ERROR if query was successful
  264. *
  265. * COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt
  266. * will call your enumerate function to get all the instances and perform the
  267. * filtering for you. Unless you expect SIGNIFICANT savings from implementing
  268. * queries, you should remove this method. You should also remove this method
  269. * if you are implementing a 'method only' provider.
  270. *
  271. *****************************************************************************/
  272. HRESULT CNlbsNic::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
  273. {
  274. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  275. }
  276. /*****************************************************************************
  277. *
  278. * FUNCTION : CNlbsNic::PutInstance
  279. *
  280. * DESCRIPTION : PutInstance should be used in provider classes that can
  281. * write instance information back to the hardware or
  282. * software. For example: Win32_Environment will allow a
  283. * PutInstance to create or update an environment variable.
  284. * However, a class like MotherboardDevice will not allow
  285. * editing of the number of slots, since it is difficult for
  286. * a provider to affect that number.
  287. *
  288. * INPUTS : A pointer to a CInstance object containing the key properties.
  289. * A long that contains the flags described in
  290. * IWbemServices::PutInstanceAsync.
  291. *
  292. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
  293. * WBEM_E_FAILED if there is an error delivering the instance
  294. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  295. * are incorrect.
  296. * WBEM_S_NO_ERROR if instance is properly delivered
  297. *
  298. * COMMENTS : TO DO: If you don't intend to support writing to your provider,
  299. * or are creating a 'method only' provider, remove this
  300. * method.
  301. *
  302. *****************************************************************************/
  303. HRESULT CNlbsNic::PutInstance ( const CInstance &Instance, long lFlags)
  304. {
  305. // Use the CInstance Get functions (for example, call
  306. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  307. // the client requested.
  308. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  309. }
  310. /*****************************************************************************
  311. *
  312. * FUNCTION : CNlbsNic::DeleteInstance
  313. *
  314. * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information
  315. * to the software or hardware. For most hardware devices,
  316. * DeleteInstance should not be implemented, but for software
  317. * configuration, DeleteInstance implementation is plausible.
  318. *
  319. * INPUTS : A pointer to a CInstance object containing the key properties.
  320. * A long that contains the flags described in
  321. * IWbemServices::DeleteInstanceAsync.
  322. *
  323. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
  324. * WBEM_E_FAILED if there is an error deleting the instance.
  325. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  326. * are incorrect.
  327. * WBEM_S_NO_ERROR if instance is properly deleted.
  328. *
  329. * COMMENTS : TO DO: If you don't intend to support deleting instances or are
  330. * creating a 'method only' provider, remove this method.
  331. *
  332. *****************************************************************************/
  333. HRESULT CNlbsNic::DeleteInstance ( const CInstance &Instance, long lFlags )
  334. {
  335. // Use the CInstance Get functions (for example, call
  336. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  337. // the client requested.
  338. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  339. }
  340. /*****************************************************************************
  341. *
  342. * FUNCTION : CNlbsNic::ExecMethod
  343. *
  344. * DESCRIPTION : Override this function to provide support for methods.
  345. * A method is an entry point for the user of your provider
  346. * to request your class perform some function above and
  347. * beyond a change of state. (A change of state should be
  348. * handled by PutInstance() )
  349. *
  350. * INPUTS : A pointer to a CInstance containing the instance the method was executed against.
  351. * A string containing the method name
  352. * A pointer to the CInstance which contains the IN parameters.
  353. * A pointer to the CInstance to contain the OUT parameters.
  354. * A set of specialized method flags
  355. *
  356. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
  357. * WBEM_S_NO_ERROR if method executes successfully
  358. * WBEM_E_FAILED if error occurs executing method
  359. *
  360. * COMMENTS : TO DO: If you don't intend to support Methods, remove this method.
  361. *
  362. *****************************************************************************/
  363. HRESULT CNlbsNic::ExecMethod ( const CInstance& Instance,
  364. const BSTR bstrMethodName,
  365. CInstance *pInParams,
  366. CInstance *pOutParams,
  367. long lFlags)
  368. {
  369. // For non-static methods, use the CInstance Get functions (for example,
  370. // call GetCHString(L"Name", sTemp)) against Instance to see the key
  371. // values the client requested.
  372. HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
  373. CHString sTemp;
  374. wstring fullName;
  375. wstring clusterIPAddress;
  376. wstring clusterNetworkMask;
  377. wstring clusterName;
  378. wstring password;
  379. _variant_t hostPriority;
  380. wstring dedicatedIPAddress;
  381. wstring dedicatedNetworkMask;
  382. bool retBool;
  383. Instance.GetCHString( L"FullName",
  384. sTemp );
  385. fullName = sTemp;
  386. NICCard nic( NICCard::fullName,
  387. fullName );
  388. NICCard::NICCard_Error err;
  389. DWORD retValue= 100;
  390. if (_wcsicmp(bstrMethodName, L"IsBound") == 0)
  391. {
  392. // check if bound or not.
  393. err = nic.isBoundTo( L"ms_wlbs");
  394. if( err == NICCard::BOUND )
  395. {
  396. retValue = 1;
  397. }
  398. else if( err == NICCard::UNBOUND )
  399. {
  400. retValue = 0;
  401. }
  402. else if( err == NICCard::NO_SUCH_NIC )
  403. {
  404. retValue = 20;
  405. }
  406. else if( err == NICCard::NO_SUCH_COMPONENT )
  407. {
  408. retValue = 30;
  409. }
  410. else
  411. {
  412. retValue = 40;
  413. }
  414. hresult = WBEM_S_NO_ERROR;
  415. pOutParams->SetDWORD(L"ReturnValue", retValue);
  416. return hresult;
  417. }
  418. else if (_wcsicmp(bstrMethodName, L"Bind") == 0)
  419. {
  420. // bind nlbs to the nic.
  421. err = nic.bind( L"ms_wlbs" );
  422. if( err == NICCard::NICCard_SUCCESS )
  423. {
  424. retValue = 0;
  425. }
  426. else if( err == NICCard::NO_SUCH_NIC )
  427. {
  428. retValue = 20;
  429. }
  430. else if( err == NICCard::NO_SUCH_COMPONENT )
  431. {
  432. retValue = 30;
  433. }
  434. else
  435. {
  436. retValue = 40;
  437. }
  438. hresult = WBEM_S_NO_ERROR;
  439. pOutParams->SetDWORD(L"ReturnValue", retValue);
  440. return hresult;
  441. }
  442. else if (_wcsicmp(bstrMethodName, L"Unbind") == 0)
  443. {
  444. // unbind nlbs from nic
  445. err = nic.unbind( L"ms_wlbs" );
  446. if( err == NICCard::NICCard_SUCCESS )
  447. {
  448. retValue = 0;
  449. }
  450. else if( err == NICCard::NO_SUCH_NIC )
  451. {
  452. retValue = 20;
  453. }
  454. else if( err == NICCard::NO_SUCH_COMPONENT )
  455. {
  456. retValue = 30;
  457. }
  458. else
  459. {
  460. retValue = 40;
  461. }
  462. hresult = WBEM_S_NO_ERROR;
  463. pOutParams->SetDWORD(L"ReturnValue", retValue);
  464. return hresult;
  465. }
  466. else if (_wcsicmp(bstrMethodName, L"BindAndConfigure") == 0)
  467. {
  468. // here we need to be passed everything
  469. // required to configure cluster completely
  470. // on this machine.
  471. // bind nlbs to the nic.
  472. err = nic.bind( L"ms_wlbs" );
  473. if( err == NICCard::NICCard_SUCCESS )
  474. {
  475. MNLBProviderSetting nlbs( fullName.c_str() );
  476. // remove all old port rules.
  477. // removing LB port rules
  478. vector<MNLBPortRuleLoadBalanced> portLB;
  479. nlbs.getPortRulesLoadBalanced( &portLB );
  480. for( int i = 0; i < portLB.size(); ++i )
  481. {
  482. nlbs.removePortRuleLoadBalanced( portLB[i] );
  483. }
  484. // removing D port rules
  485. vector<MNLBPortRuleDisabled> portD;
  486. nlbs.getPortRulesDisabled( &portD );
  487. for( int i = 0; i < portD.size(); ++i )
  488. {
  489. nlbs.removePortRuleDisabled( portD[i] );
  490. }
  491. // removing Failover port rules
  492. vector<MNLBPortRuleFailover> portF;
  493. nlbs.getPortRulesFailover( &portF );
  494. for( int i = 0; i < portF.size(); ++i )
  495. {
  496. nlbs.removePortRuleFailover( portF[i] );
  497. }
  498. //
  499. // get port rules to configure.
  500. //
  501. SAFEARRAY* portRulesArray;
  502. SAFEARRAYBOUND sb;
  503. sb.lLbound = 0;
  504. sb.cElements = 100;
  505. portRulesArray = SafeArrayCreate( VT_BSTR, 1, &sb );
  506. pInParams->GetStringArray( L"PortRules",
  507. portRulesArray );
  508. vector<_bstr_t> portRulesVector;
  509. GetVectorFromSafeArray( portRulesArray,
  510. portRulesVector );
  511. ClusterData clusterData;
  512. FillInPortRules( &clusterData,
  513. L"rashuma",
  514. portRulesVector );
  515. // add all new port rules.
  516. // equal load balanced.
  517. map< long, PortDataELB>::iterator topELB;
  518. for( topELB = clusterData.portELB.begin();
  519. topELB != clusterData.portELB.end();
  520. ++topELB )
  521. {
  522. nlbs.addPortRuleLoadBalanced(
  523. (*topELB).second );
  524. }
  525. // unequal load balanced
  526. map< long, PortDataULB>::iterator topULB;
  527. for( topULB = clusterData.portULB.begin();
  528. topULB != clusterData.portULB.end();
  529. ++topULB )
  530. {
  531. MNLBPortRuleLoadBalanced portRuleULB = (*topULB).second;
  532. portRuleULB._load =
  533. (*topULB).second.machineMapToLoadWeight[L"rashuma"];
  534. nlbs.addPortRuleLoadBalanced(
  535. portRuleULB );
  536. }
  537. // disabled
  538. map< long, PortDataD>::iterator topD;
  539. for( topD = clusterData.portD.begin();
  540. topD != clusterData.portD.end();
  541. ++topD )
  542. {
  543. nlbs.addPortRuleDisabled(
  544. (*topD).second );
  545. }
  546. // failover
  547. map< long, PortDataF>::iterator topF;
  548. for( topF = clusterData.portF.begin();
  549. topF != clusterData.portF.end();
  550. ++topF )
  551. {
  552. MNLBPortRuleFailover portRuleF = (*topF).second;
  553. portRuleF._priority =
  554. (*topF).second.machineMapToPriority[ L"rashuma" ];
  555. nlbs.addPortRuleFailover( portRuleF );
  556. }
  557. //
  558. // set host properties.
  559. //
  560. HostProperties hp;
  561. // host priority
  562. pInParams->GetVariant( L"HostPriority",
  563. hostPriority );
  564. hp.hID = hostPriority;
  565. // dip
  566. pInParams->GetCHString( L"DedicatedIPAddress",
  567. sTemp );
  568. dedicatedIPAddress = sTemp;
  569. hp.hIP = dedicatedIPAddress.c_str();
  570. // dsn
  571. pInParams->GetCHString( L"DedicatedNetworkMask",
  572. sTemp );
  573. dedicatedNetworkMask = sTemp;
  574. hp.hSubnetMask = dedicatedNetworkMask.c_str();
  575. // initial state ?
  576. pInParams->Getbool( L"ClusterModeOnStart",
  577. hp.initialClusterStateActive );
  578. unsigned long retVal;
  579. nlbs.setHostProperties( hp,
  580. &retVal );
  581. //
  582. // set cluster properties.
  583. //
  584. ClusterProperties cp;
  585. RetreiveAndSetClusterProperties(pInParams, nlbs, cp, fullName );
  586. //
  587. // if initial state active start cluster
  588. // else stop cluster.
  589. //
  590. MNLBMachine nlbMachine( cp.cIP );
  591. if( hp.initialClusterStateActive == true )
  592. {
  593. nlbMachine.start( Common::THIS_HOST, &retVal );
  594. }
  595. else
  596. {
  597. nlbMachine.stop( Common::THIS_HOST, &retVal );
  598. }
  599. retValue = 0;
  600. }
  601. else if( err == NICCard::NO_SUCH_NIC )
  602. {
  603. retValue = 20;
  604. }
  605. else if( err == NICCard::NO_SUCH_COMPONENT )
  606. {
  607. retValue = 30;
  608. }
  609. else
  610. {
  611. retValue = 40;
  612. }
  613. hresult = WBEM_S_NO_ERROR;
  614. pOutParams->SetDWORD(L"ReturnValue", retValue);
  615. return hresult;
  616. }
  617. else if (_wcsicmp(bstrMethodName, L"ModifyClusterProperties") == 0)
  618. {
  619. // check if nic is bound to adapter or not.
  620. err = nic.isBoundTo( L"ms_wlbs" );
  621. if( err == NICCard::BOUND )
  622. {
  623. MNLBProviderSetting nlbs( fullName.c_str() );
  624. //
  625. // set cluster properties.
  626. //
  627. ClusterProperties cp;
  628. RetreiveAndSetClusterProperties(pInParams, nlbs, cp, fullName);
  629. }
  630. else if( err == NICCard::UNBOUND )
  631. {
  632. retValue = 10;
  633. }
  634. else if( err == NICCard::NO_SUCH_NIC )
  635. {
  636. retValue = 20;
  637. }
  638. else if( err == NICCard::NO_SUCH_COMPONENT )
  639. {
  640. retValue = 30;
  641. }
  642. else
  643. {
  644. retValue = 40;
  645. }
  646. hresult = WBEM_S_NO_ERROR;
  647. pOutParams->SetDWORD(L"ReturnValue", retValue);
  648. return hresult;
  649. }
  650. else if (_wcsicmp(bstrMethodName, L"GetClusterConfiguration") == 0)
  651. {
  652. hresult = ProvGetClusterConfiguration(
  653. pInParams,
  654. pOutParams
  655. );
  656. return hresult;
  657. }
  658. else if (_wcsicmp(bstrMethodName, L"UpdateClusterConfiguration") == 0)
  659. {
  660. hresult = ProvUpdateClusterConfiguration(
  661. pInParams,
  662. pOutParams
  663. );
  664. return hresult;
  665. }
  666. else if (_wcsicmp(bstrMethodName, L"QueryConfigurationUpdateStatus") == 0)
  667. {
  668. hresult = ProvQueryConfigurationUpdateStatus(
  669. pInParams,
  670. pOutParams
  671. );
  672. return hresult;
  673. }
  674. else
  675. {
  676. // unknown call, we do not support this.
  677. hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
  678. pOutParams->SetDWORD(L"ReturnValue", retValue);
  679. return hresult;
  680. }
  681. }
  682. void
  683. CNlbsNic::RetreiveAndSetClusterProperties(CInstance *pInParams,
  684. MNLBProviderSetting &nlbs,
  685. ClusterProperties& cp,
  686. const wstring& fullName )
  687. {
  688. CHString sTemp;
  689. wstring clusterIPAddress;
  690. wstring clusterNetworkMask;
  691. wstring clusterName;
  692. wstring password;
  693. // cip
  694. pInParams->GetCHString( L"ClusterIPAddress", sTemp );
  695. clusterIPAddress = sTemp;
  696. cp.cIP = clusterIPAddress.c_str();
  697. // csn
  698. pInParams->GetCHString( L"ClusterNetworkMask", sTemp );
  699. clusterNetworkMask = sTemp;
  700. cp.cSubnetMask = clusterNetworkMask.c_str();
  701. // full internet name
  702. pInParams->GetCHString( L"ClusterName", sTemp );
  703. clusterName = sTemp;
  704. cp.cFullInternetName = clusterName.c_str();
  705. // igmp support?
  706. pInParams->Getbool( L"IGMPSupport", cp.igmpSupportEnabled );
  707. // multicast enabled?
  708. pInParams->Getbool( L"MulticastSupportEnabled", cp.multicastSupportEnabled );
  709. // remote control enabled?
  710. pInParams->Getbool( L"RemoteControlEnabled", cp.remoteControlEnabled );
  711. // password
  712. pInParams->GetCHString( L"Password", sTemp );
  713. password = sTemp;
  714. cp.password = password.c_str();
  715. unsigned long retVal;
  716. try
  717. {
  718. nlbs.setClusterProperties( cp, &retVal );
  719. }
  720. catch( _com_error e )
  721. {
  722. }
  723. // set password.
  724. try
  725. {
  726. if( cp.remoteControlEnabled == true )
  727. {
  728. nlbs.setPassword( cp.password,
  729. &retVal );
  730. }
  731. }
  732. catch( _com_error e )
  733. {
  734. }
  735. //
  736. // add cluster ip
  737. //
  738. MIPAddressAdmin ipAdmin( fullName.c_str() );
  739. long SleepDuration = 0;
  740. while ((ipAdmin.addIPAddress(cp.cIP, cp.cSubnetMask) != MIPAddressAdmin::MIPAddressAdmin_SUCCESS)
  741. &&(SleepDuration < PROTOCOL_BIND_DELAY))
  742. {
  743. SleepDuration += PROTOCOL_BIND_WAIT_INCREMENT;
  744. Sleep(PROTOCOL_BIND_WAIT_INCREMENT);
  745. }
  746. }
  747. void
  748. CNlbsNic::GetVectorFromSafeArray( SAFEARRAY*& stringArray,
  749. vector<_bstr_t>& strings )
  750. {
  751. LONG count = stringArray->rgsabound[0].cElements;
  752. BSTR* pbstr;
  753. HRESULT hr;
  754. if( SUCCEEDED( SafeArrayAccessData( stringArray, ( void **) &pbstr)))
  755. {
  756. for( LONG x = 0; x < count; x++ )
  757. {
  758. strings.push_back( pbstr[x] );
  759. }
  760. hr = SafeArrayUnaccessData( stringArray );
  761. }
  762. }
  763. void
  764. CNlbsNic::FillInPortRules( ClusterData* p_clusterData,
  765. const _bstr_t& myMachine,
  766. const vector<_bstr_t>& portRules )
  767. {
  768. wchar_t portBuf[1000];
  769. wstring temp;
  770. WTokens tok;
  771. vector<wstring> tokens;
  772. for( int i = 0; i < portRules.size(); ++i )
  773. {
  774. wcscpy( portBuf, portRules[i] );
  775. tok.init( portBuf, L"\t");
  776. tokens = tok.tokenize();
  777. if( tokens[3] == L"Multiple" )
  778. {
  779. if( tokens[5] == L"Equal" )
  780. {
  781. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() );
  782. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() );
  783. if( tokens[2] == L"Both" )
  784. {
  785. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both;
  786. }
  787. else if( tokens[2] == L"TCP" )
  788. {
  789. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp;
  790. }
  791. else
  792. {
  793. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp;
  794. }
  795. if( tokens[6] == L"Single" )
  796. {
  797. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::single;
  798. }
  799. else if( tokens[6] == L"None" )
  800. {
  801. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::none;
  802. }
  803. else
  804. {
  805. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::classC;
  806. }
  807. p_clusterData->portELB[ _wtoi( tokens[0].c_str()) ]._isEqualLoadBalanced = true;
  808. }
  809. else
  810. {
  811. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() );
  812. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() );
  813. if( tokens[2] == L"Both" )
  814. {
  815. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both;
  816. }
  817. else if( tokens[2] == L"TCP" )
  818. {
  819. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp;
  820. }
  821. else
  822. {
  823. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp;
  824. }
  825. if( tokens[6] == L"Single" )
  826. {
  827. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::single;
  828. }
  829. else if( tokens[6] == L"None" )
  830. {
  831. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::none;
  832. }
  833. else
  834. {
  835. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._affinity = MNLBPortRule::classC;
  836. }
  837. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ]._isEqualLoadBalanced = false;
  838. p_clusterData->portULB[ _wtoi( tokens[0].c_str()) ].machineMapToLoadWeight[myMachine] =
  839. _wtoi( tokens[5].c_str() );
  840. }
  841. }
  842. else if ( tokens[3] == L"Single" )
  843. {
  844. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() );
  845. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() );
  846. if( tokens[2] == L"Both" )
  847. {
  848. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both;
  849. }
  850. else if( tokens[2] == L"TCP" )
  851. {
  852. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp;
  853. }
  854. else
  855. {
  856. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp;
  857. }
  858. p_clusterData->portF[ _wtoi( tokens[0].c_str()) ].machineMapToPriority[myMachine] =
  859. _wtoi( tokens[4].c_str() );
  860. }
  861. else
  862. {
  863. p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._startPort = _wtoi( tokens[0].c_str() );
  864. p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._endPort = _wtoi( tokens[1].c_str() );
  865. if( tokens[2] == L"Both" )
  866. {
  867. p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::both;
  868. }
  869. else if( tokens[2] == L"TCP" )
  870. {
  871. p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::tcp;
  872. }
  873. else
  874. {
  875. p_clusterData->portD[ _wtoi( tokens[0].c_str()) ]._trafficToHandle = MNLBPortRule::udp;
  876. }
  877. }
  878. }
  879. }
  880. WBEMSTATUS
  881. ProvGetClusterConfiguration(
  882. CInstance *pInParams,
  883. CInstance *pOutParams
  884. )
  885. /*++
  886. WMI provider wrapper around NlbConfigurationUpdate::GetConfiguration
  887. --*/
  888. {
  889. if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
  890. LPCWSTR pAdapterGuid = NULL;
  891. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  892. CHString sTemp;
  893. bool fRet;
  894. NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
  895. SAFEARRAY *pSA = NULL;
  896. /*
  897. [IN] String AdapterGuid,
  898. [OUT] uint32 Generation,
  899. [OUT] String NetworkAddresses[], // "10.1.1.1/255.0.0.0"
  900. [OUT] Boolean NLBBound,
  901. [OUT] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
  902. [OUT] String ClusterName,
  903. [OUT] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
  904. [OUT] String PortRules[],
  905. [OUT] uint32 HostPriority,
  906. [OUT] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
  907. [OUT] Boolean ClusterModeOnStart,
  908. [OUT] Boolean RemoteControlEnabled
  909. */
  910. fRet = pInParams->GetCHString( L"AdapterGuid", sTemp );
  911. if (!fRet)
  912. {
  913. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  914. Status = WBEM_E_INVALID_PARAMETER;
  915. goto end;
  916. }
  917. //
  918. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  919. // buffer -- see operator LPCWSTR() of WString docs.
  920. //
  921. pAdapterGuid = (LPCWSTR) sTemp;
  922. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  923. {
  924. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  925. Status = WBEM_E_INVALID_PARAMETER;
  926. goto end;
  927. }
  928. else
  929. {
  930. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  931. }
  932. Status = NlbConfigurationUpdate::GetConfiguration(
  933. pAdapterGuid,
  934. &Cfg
  935. );
  936. if (FAILED(Status))
  937. {
  938. goto end;
  939. }
  940. pOutParams->SetDWORD(L"ReturnValue", (DWORD) WBEM_NO_ERROR);
  941. pOutParams->SetDWORD(L"Generation", Cfg.GetGeneration());
  942. //
  943. // Fill in NetworkAddresses[]
  944. //
  945. {
  946. Status = Cfg.GetNetworkAddressesSafeArray(
  947. &pSA
  948. );
  949. if (FAILED(Status))
  950. {
  951. TRACE_CRIT(
  952. "%!FUNC!: couldn't extract network addresses from Cfg"
  953. " for NIC %ws",
  954. pAdapterGuid
  955. );
  956. goto end;
  957. }
  958. if (pSA!=NULL)
  959. {
  960. pOutParams->SetStringArray(
  961. L"NetworkAddresses",
  962. *pSA // pass by reference
  963. );
  964. SafeArrayDestroy(pSA);
  965. pSA = NULL;
  966. }
  967. }
  968. if (!Cfg.IsNlbBound())
  969. {
  970. //
  971. // NLB is bound
  972. //
  973. pOutParams->Setbool(L"NLBBound", FALSE);
  974. Status = WBEM_NO_ERROR;
  975. goto end;
  976. }
  977. //
  978. // NLB is bound
  979. //
  980. pOutParams->Setbool(L"NLBBound", TRUE);
  981. if (!Cfg.IsValidNlbConfig())
  982. {
  983. TRACE_CRIT(
  984. "%!FUNC!: NLB-specific configuration on NIC %ws is invalid",
  985. pAdapterGuid
  986. );
  987. goto end;
  988. }
  989. //
  990. // Cluster name
  991. //
  992. {
  993. LPWSTR szName = NULL;
  994. Status = Cfg.GetClusterName(&szName);
  995. if (FAILED(Status))
  996. {
  997. TRACE_CRIT(
  998. "%!FUNC!: Could not extract cluster name for NIC %ws",
  999. pAdapterGuid
  1000. );
  1001. goto end;
  1002. }
  1003. pOutParams->SetCHString(L"ClusterName", szName);
  1004. delete (szName);
  1005. szName = NULL;
  1006. }
  1007. //
  1008. // Cluster and dedicated network addresses
  1009. //
  1010. {
  1011. LPWSTR szAddress = NULL;
  1012. Status = Cfg.GetClusterNetworkAddress(&szAddress);
  1013. if (FAILED(Status))
  1014. {
  1015. TRACE_CRIT(
  1016. "%!FUNC!: Could not extract cluster address for NIC %ws",
  1017. pAdapterGuid
  1018. );
  1019. goto end;
  1020. }
  1021. pOutParams->SetCHString(L"ClusterNetworkAddress", szAddress);
  1022. delete (szAddress);
  1023. szAddress = NULL;
  1024. Status = Cfg.GetDedicatedNetworkAddress(&szAddress);
  1025. if (FAILED(Status))
  1026. {
  1027. TRACE_CRIT(
  1028. "%!FUNC!: Could not extract dedicated address for NIC %ws",
  1029. pAdapterGuid
  1030. );
  1031. goto end;
  1032. }
  1033. pOutParams->SetCHString(L"DedicatedNetworkAddress", szAddress);
  1034. delete (szAddress);
  1035. szAddress = NULL;
  1036. }
  1037. //
  1038. // TrafficMode
  1039. //
  1040. {
  1041. LPCWSTR szMode = NULL;
  1042. switch(Cfg.GetTrafficMode())
  1043. {
  1044. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST:
  1045. szMode = L"UNICAST";
  1046. break;
  1047. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST:
  1048. szMode = L"MULTICAST";
  1049. break;
  1050. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST:
  1051. szMode = L"IGMPMULTICAST";
  1052. break;
  1053. default:
  1054. assert(FALSE);
  1055. Status = WBEM_E_CRITICAL_ERROR;
  1056. goto end;
  1057. }
  1058. pOutParams->SetCHString(L"TrafficMode", szMode);
  1059. }
  1060. pOutParams->SetDWORD(L"HostPriority", Cfg.GetHostPriority());
  1061. if (Cfg.GetClusterModeOnStart() ==
  1062. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED)
  1063. {
  1064. pOutParams->Setbool(L"ClusterModeOnStart", TRUE);
  1065. }
  1066. else
  1067. {
  1068. pOutParams->Setbool(L"ClusterModeOnStart", FALSE);
  1069. }
  1070. pOutParams->Setbool(L"RemoteControlEnabled", Cfg.GetRemoteControlEnabled());
  1071. //
  1072. // TODO: get port rules
  1073. // [OUT] String PortRules[],
  1074. //
  1075. Status = WBEM_NO_ERROR;
  1076. end:
  1077. if (pSA!=NULL)
  1078. {
  1079. SafeArrayDestroy(pSA);
  1080. pSA = NULL;
  1081. }
  1082. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1083. return Status;
  1084. }
  1085. WBEMSTATUS
  1086. ProvUpdateClusterConfiguration(
  1087. CInstance *pInParams,
  1088. CInstance *pOutParams
  1089. )
  1090. /*++
  1091. WMI provider wrapper NlbConfigurationUpdate::UpdateConfiguration
  1092. with some additional wrinkles:
  1093. we selectively update the current version.
  1094. --*/
  1095. {
  1096. if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
  1097. LPCWSTR pAdapterGuid = NULL;
  1098. LPCWSTR pClientDescription = L"Unspecified WMI Client"; // TODO: localize
  1099. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  1100. CHString sClientDescription;
  1101. CHString sAdapterGuid;
  1102. CHString sTemp;
  1103. bool fRet;
  1104. NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
  1105. SAFEARRAY *pSA = NULL;
  1106. /*
  1107. [IN] String ClientDescription,
  1108. [IN] String AdapterGuid,
  1109. [IN] uint32 Generation,
  1110. [IN] Boolean PartialUpdate,
  1111. [IN] String NetworkAddresses[], // "10.1.1.1/255.255.255.255"
  1112. [IN] Boolean NLBBound,
  1113. [IN] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
  1114. [IN] String ClusterName,
  1115. [IN] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
  1116. [IN] String PortRules[],
  1117. [IN] uint32 HostPriority,
  1118. [IN] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
  1119. [IN] Boolean ClusterModeOnStart,
  1120. [IN] Boolean RemoteControlEnabled,
  1121. [IN] String Password,
  1122. [OUT] uint32 NewGeneration,
  1123. [OUT] String Log
  1124. */
  1125. fRet = pInParams->GetCHString( L"ClientDescription", sClientDescription);
  1126. if (fRet)
  1127. {
  1128. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1129. pClientDescription = (LPCWSTR) sClientDescription;
  1130. }
  1131. fRet = pInParams->GetCHString( L"AdapterGuid", sAdapterGuid);
  1132. if (!fRet)
  1133. {
  1134. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  1135. Status = WBEM_E_INVALID_PARAMETER;
  1136. goto end;
  1137. }
  1138. //
  1139. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1140. // buffer -- see operator LPCWSTR() of WString docs.
  1141. //
  1142. pAdapterGuid = (LPCWSTR) sAdapterGuid;
  1143. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  1144. {
  1145. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  1146. Status = WBEM_E_INVALID_PARAMETER;
  1147. goto end;
  1148. }
  1149. else
  1150. {
  1151. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  1152. }
  1153. //
  1154. // Get the current configuration
  1155. //
  1156. Status = NlbConfigurationUpdate::GetConfiguration(
  1157. pAdapterGuid,
  1158. &Cfg
  1159. );
  1160. if (FAILED(Status))
  1161. {
  1162. goto end;
  1163. }
  1164. //
  1165. // Modify the snapshot of the current configuration with whatever
  1166. // cluster configuration information is specified in the input
  1167. // parameters
  1168. //
  1169. {
  1170. DWORD InGeneration = 0;
  1171. bool NlbBound = FALSE;
  1172. bool bResult = FALSE;
  1173. bool bPartialUpdate = FALSE;
  1174. //
  1175. // Determine if this is a partial or full update.
  1176. // If partial update, we allow a subset of cluster configuration
  1177. // parameters to be specified, but allow only a restricted set
  1178. // of update operations.
  1179. //
  1180. // Disallowed partial update operations:
  1181. // - Transitions between bound and !bound
  1182. // - Currently bound but nlb parameters are invalid
  1183. //
  1184. // Some allowed partial updates:
  1185. // - Modifying IP address lists
  1186. // - Modifying cluster / dedicated addresses/subnets
  1187. // - Modifying existing portrules
  1188. // - Adding/deleting port rules
  1189. //
  1190. bResult = pInParams->GetDWORD(
  1191. L"Generation", // <--------------------------------
  1192. InGeneration
  1193. );
  1194. if (!bResult)
  1195. {
  1196. //
  1197. // We allow generation to be unspecified.
  1198. //
  1199. InGeneration = 0;
  1200. }
  1201. else
  1202. {
  1203. //
  1204. // If generation is specified,
  1205. // we verify that the current generation matches the
  1206. // specified generation.
  1207. // TODO: this really must be done in the context of
  1208. // mfn_Start update -- after we've acquired the global lock!
  1209. //
  1210. if (InGeneration != Cfg.GetGeneration())
  1211. {
  1212. TRACE_CRIT("Partial update: input generation(%lu) != current generation(%lu)", InGeneration, Cfg.GetGeneration());
  1213. Status = WBEM_E_HANDLE_OUT_OF_DATE;
  1214. goto end;
  1215. }
  1216. }
  1217. bResult = pInParams->Getbool(
  1218. L"NLBBound", // <--------------------------------
  1219. NlbBound
  1220. );
  1221. if (!bResult)
  1222. {
  1223. NlbBound = Cfg.IsNlbBound();
  1224. TRACE_CRIT(L"Could not read NLBBound -- assuming current state %d.",
  1225. NlbBound);
  1226. }
  1227. bResult = pInParams->GetStringArray(
  1228. L"NetworkAddresses", // <--------------------------------
  1229. pSA
  1230. );
  1231. if (!bResult)
  1232. {
  1233. //
  1234. // We set pCfg to zero addresses, which causes update to
  1235. // use it's own defaults...
  1236. //
  1237. TRACE_CRIT(L"Could not read Network addresses -- using defaults");
  1238. Status = Cfg.SetNetworkAddresses(NULL, 0);
  1239. pSA = NULL;
  1240. }
  1241. else
  1242. {
  1243. if (pSA != NULL)
  1244. {
  1245. Status = Cfg.SetNetworkAddressesSafeArray(pSA);
  1246. SafeArrayDestroy(pSA);
  1247. pSA = NULL;
  1248. }
  1249. }
  1250. if (!NlbBound)
  1251. {
  1252. // NLB is not to be bound -- no need to read the input params.
  1253. Cfg.fBound = FALSE;
  1254. Cfg.fValidNlbCfg = FALSE;
  1255. }
  1256. else
  1257. {
  1258. BOOL fNewConfig = FALSE;
  1259. if (!Cfg.fBound || Cfg.fValidNlbCfg == FALSE)
  1260. {
  1261. //
  1262. // If we were previously unbound or we were bound but with
  1263. // a bad configuration, we need to setup our
  1264. // new cfg with good defaults
  1265. //
  1266. CfgUtilInitializeParams(&Cfg.NlbParams);
  1267. Cfg.fBound = TRUE;
  1268. Cfg.fValidNlbCfg = TRUE;
  1269. fNewConfig = TRUE;
  1270. }
  1271. bResult = pInParams->GetCHString(
  1272. L"ClusterNetworkAddress", // <--------------------
  1273. sTemp
  1274. );
  1275. if (!bResult)
  1276. {
  1277. if (fNewConfig)
  1278. {
  1279. //
  1280. // Cluster address MUST be specified for new config.
  1281. //
  1282. TRACE_CRIT(L"ERROR: Could not read Cluster IP for new config.");
  1283. Status = WBEM_E_INVALID_PARAMETER;
  1284. goto end;
  1285. }
  1286. TRACE_CRIT(L"Could not read Cluster IP. Keeping existing.");
  1287. }
  1288. else
  1289. {
  1290. LPCWSTR szClusterNetworkAddress = NULL;
  1291. szClusterNetworkAddress = (LPCWSTR) sTemp; // no copies here.
  1292. Cfg.SetClusterNetworkAddress(szClusterNetworkAddress);
  1293. szClusterNetworkAddress = NULL;
  1294. }
  1295. bResult = pInParams->GetCHString(
  1296. L"ClusterName", // <-------------------------
  1297. sTemp
  1298. );
  1299. if (!bResult)
  1300. {
  1301. TRACE_CRIT(L"Could not read Cluster Name. Keeping existing");
  1302. }
  1303. else
  1304. {
  1305. LPCWSTR szClusterName = NULL;
  1306. szClusterName = (LPCWSTR) sTemp; // no copies here.
  1307. Cfg.SetClusterName(szClusterName);
  1308. szClusterName = NULL;
  1309. }
  1310. //
  1311. // Traffic mode
  1312. //
  1313. {
  1314. bResult = pInParams->GetCHString(
  1315. L"TrafficMode", // <-------------------------
  1316. sTemp
  1317. );
  1318. if (!bResult)
  1319. {
  1320. TRACE_CRIT(L"Could not read TrafficMode. Keeping existing");
  1321. }
  1322. else
  1323. {
  1324. LPCWSTR szTrafficMode = NULL;
  1325. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode
  1326. = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  1327. szTrafficMode = (LPCWSTR) sTemp; // no copies here.
  1328. if (!_wcsicmp(szTrafficMode, L"UNICAST"))
  1329. {
  1330. TrafficMode =
  1331. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  1332. }
  1333. else if (!_wcsicmp(szTrafficMode, L"MULTICAST"))
  1334. {
  1335. TrafficMode =
  1336. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST;
  1337. }
  1338. else if (!_wcsicmp(szTrafficMode, L"IGMPMULTICAST"))
  1339. {
  1340. TrafficMode =
  1341. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST;
  1342. }
  1343. else
  1344. {
  1345. TRACE_CRIT("Invalid TrafficMode: %ws", szTrafficMode);
  1346. Status = WBEM_E_INVALID_PARAMETER;
  1347. goto end;
  1348. }
  1349. Cfg.SetTrafficMode(TrafficMode);
  1350. szTrafficMode = NULL;
  1351. }
  1352. }
  1353. //
  1354. // TODO: process port rules.
  1355. // [OUT] String PortRules[]
  1356. //
  1357. DWORD HostPriority = 0;
  1358. bResult = pInParams->GetDWORD(
  1359. L"HostPriority", // <---------------------------
  1360. HostPriority
  1361. );
  1362. if (!bResult)
  1363. {
  1364. TRACE_CRIT(L"Could not read HostPriority. Keeping existing");
  1365. }
  1366. else
  1367. {
  1368. Cfg.SetHostPriority(HostPriority);
  1369. }
  1370. bResult = pInParams->GetCHString(
  1371. L"DedicatedNetworkAddress", // <-----------------
  1372. sTemp
  1373. );
  1374. if (!bResult)
  1375. {
  1376. TRACE_CRIT(L"Could not dedicated IP. Keeping existing");
  1377. }
  1378. else
  1379. {
  1380. LPCWSTR szAddress = NULL;
  1381. szAddress = (LPCWSTR) sTemp; // no copies here.
  1382. Cfg.SetDedicatedNetworkAddress(szAddress);
  1383. //
  1384. // For now, we'll always try to add the dedicated IP address
  1385. // to the NIC.
  1386. //
  1387. Cfg.fAddDedicatedIp = TRUE;
  1388. szAddress = NULL;
  1389. }
  1390. //
  1391. // StartMode
  1392. //
  1393. {
  1394. bool StartMode = FALSE;
  1395. bResult = pInParams->Getbool(
  1396. L"ClusterModeOnStart", // <-----------------
  1397. StartMode
  1398. );
  1399. if (!bResult)
  1400. {
  1401. TRACE_CRIT(L"Could not read StartMode. Keeping existing");
  1402. }
  1403. else
  1404. {
  1405. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
  1406. ClusterModeOnStart;
  1407. if (StartMode)
  1408. {
  1409. ClusterModeOnStart =
  1410. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED;
  1411. }
  1412. else
  1413. {
  1414. ClusterModeOnStart =
  1415. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
  1416. }
  1417. Cfg.SetClusterModeOnStart(ClusterModeOnStart);
  1418. }
  1419. }
  1420. //
  1421. // Remote control enabled
  1422. //
  1423. {
  1424. bool bRemoteControlEnabled;
  1425. bResult = pInParams->Getbool(
  1426. L"RemoteControlEnabled", // <---------------
  1427. bRemoteControlEnabled
  1428. );
  1429. if (!bResult)
  1430. {
  1431. TRACE_CRIT(L"Could not read RemoteControlEnabled. Keeping existing");
  1432. }
  1433. else
  1434. {
  1435. Cfg.SetRemoteControlEnabled(bRemoteControlEnabled!=FALSE);
  1436. }
  1437. }
  1438. //
  1439. // TODO: if PartialUpdate is specified, we need to
  1440. // make sure that fValidNlbCfg is already set.
  1441. //
  1442. Cfg.fValidNlbCfg = TRUE;
  1443. } while (FALSE) ;
  1444. }
  1445. //
  1446. // Call NlbConfigurationUpdate::DuUpdate to do the actual work.
  1447. //
  1448. UINT NewGeneration = 0;
  1449. LPWSTR pLog = NULL;
  1450. Status = NlbConfigurationUpdate::DoUpdate(
  1451. pAdapterGuid,
  1452. pClientDescription,
  1453. &Cfg,
  1454. &NewGeneration,
  1455. &pLog
  1456. );
  1457. //
  1458. // Fill out the out parameters: status new generation and log
  1459. //
  1460. pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
  1461. pOutParams->SetDWORD(L"NewGeneration", (DWORD) NewGeneration);
  1462. if (pLog != NULL)
  1463. {
  1464. pOutParams->SetCHString(L"Log", pLog);
  1465. delete pLog;
  1466. pLog = NULL;
  1467. }
  1468. //
  1469. // If we've actually called DoUpdate,
  1470. // we always return WBEM_NO_ERROR. The return value has the
  1471. // real result.
  1472. //
  1473. Status = WBEM_NO_ERROR;
  1474. end:
  1475. if (pSA!=NULL)
  1476. {
  1477. SafeArrayDestroy(pSA);
  1478. pSA = NULL;
  1479. }
  1480. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1481. return Status;
  1482. }
  1483. WBEMSTATUS
  1484. ProvQueryConfigurationUpdateStatus(
  1485. CInstance *pInParams,
  1486. CInstance *pOutParams
  1487. )
  1488. /*++
  1489. WMI provider wrapper around NlbConfigurationUpdate::GetUpdateStatus
  1490. --*/
  1491. {
  1492. if (!g_UpdateConfigurationEnabled) return WBEM_E_PROVIDER_NOT_CAPABLE;
  1493. LPCWSTR pAdapterGuid = NULL;
  1494. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  1495. CHString sTemp;
  1496. bool fRet;
  1497. DWORD Generation = 0;
  1498. /*
  1499. [IN] String AdapterGuid,
  1500. [IN] uint32 Generation,
  1501. [OUT] String Log
  1502. */
  1503. fRet = pInParams->GetCHString( L"AdapterGuid", sTemp);
  1504. if (!fRet)
  1505. {
  1506. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  1507. Status = WBEM_E_INVALID_PARAMETER;
  1508. goto end;
  1509. }
  1510. //
  1511. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1512. // buffer -- see operator LPCWSTR() of WString docs.
  1513. //
  1514. pAdapterGuid = (LPCWSTR) sTemp;
  1515. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  1516. {
  1517. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  1518. Status = WBEM_E_INVALID_PARAMETER;
  1519. goto end;
  1520. }
  1521. else
  1522. {
  1523. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  1524. }
  1525. fRet = pInParams->GetDWORD(
  1526. L"Generation", // <--------------------------------
  1527. Generation
  1528. );
  1529. if (!fRet)
  1530. {
  1531. TRACE_CRIT("%!FUNC!: Missing generation!");
  1532. Status = WBEM_E_INVALID_PARAMETER;
  1533. goto end;
  1534. }
  1535. //
  1536. // Call NlbConfigurationUpdate::GetUpdateResult to do the actual work.
  1537. //
  1538. LPWSTR pLog = NULL;
  1539. WBEMSTATUS CompletionStatus = WBEM_NO_ERROR;
  1540. Status = NlbConfigurationUpdate::GetUpdateStatus(
  1541. pAdapterGuid,
  1542. Generation,
  1543. FALSE, // FALSE == Don't delete completion record
  1544. &CompletionStatus,
  1545. &pLog
  1546. );
  1547. if (!FAILED(Status))
  1548. {
  1549. //
  1550. // Fill out the out parameters: status new generation and log
  1551. //
  1552. pOutParams->SetDWORD(L"ReturnValue", (DWORD) CompletionStatus);
  1553. if (pLog != NULL)
  1554. {
  1555. pOutParams->SetCHString(L"Log", pLog);
  1556. delete pLog;
  1557. pLog = NULL;
  1558. }
  1559. }
  1560. end:
  1561. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1562. return Status;
  1563. }