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.

2267 lines
71 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 "private.h"
  25. #include <winsock2.h>
  26. #include "wlbsutil.h"
  27. #include "nlbsnic.h"
  28. #include "nlbsnic.tmh"
  29. // using namespace std;
  30. // MUsingCom com;
  31. BOOL g_UpdateConfigurationEnabled = TRUE;
  32. WBEMSTATUS
  33. ProvExecStaticMethod(
  34. const BSTR bstrMethodName,
  35. CInstance *pInParams,
  36. CInstance *pOutParams
  37. );
  38. WBEMSTATUS
  39. ProvGetCompatibleAdapterGuids(
  40. CInstance *pInParams,
  41. CInstance *pOutParams
  42. );
  43. WBEMSTATUS
  44. ProvGetClusterConfiguration(
  45. CInstance *pInParams,
  46. CInstance *pOutParams
  47. );
  48. WBEMSTATUS
  49. ProvUpdateClusterConfiguration(
  50. CInstance *pInParams,
  51. CInstance *pOutParams
  52. );
  53. WBEMSTATUS
  54. ProvQueryConfigurationUpdateStatus(
  55. CInstance *pInParams,
  56. CInstance *pOutParams
  57. );
  58. WBEMSTATUS
  59. ProvControlCluster(
  60. CInstance *pInParams,
  61. CInstance *pOutParams
  62. );
  63. WBEMSTATUS
  64. ProvGetClusterMembers(
  65. CInstance *pInParams,
  66. CInstance *pOutParams
  67. );
  68. WBEMSTATUS
  69. ProvRegisterManagementApplication(
  70. CInstance *pInParams,
  71. CInstance *pOutParams
  72. );
  73. WBEMSTATUS
  74. ProvUnregisterManagementApplication(
  75. CInstance *pInParams,
  76. CInstance *pOutParams
  77. );
  78. // TO DO: Replace "NameSpace" with the appropriate namespace for your
  79. // provider instance. For instance: "root\\default or "root\\cimv2".
  80. // DONE : mhakim
  81. //===================================================================
  82. CNlbsNic MyNlbsNicSet (PROVIDER_NAME_NLBSNIC, L"root\\microsoftnlb") ;
  83. // Property names
  84. //===============
  85. const static WCHAR* cszAdapterGuid = L"AdapterGuid" ;
  86. const static WCHAR* pDependent = L"Dependent" ;
  87. const static WCHAR* pFriendlyName = L"FriendlyName" ;
  88. const static WCHAR* pFullName = L"FullName" ;
  89. const static WCHAR* pVersion = L"Version" ;
  90. /*****************************************************************************
  91. *
  92. * FUNCTION : CNlbsNic::CNlbsNic
  93. *
  94. * DESCRIPTION : Constructor
  95. *
  96. * INPUTS : none
  97. *
  98. * RETURNS : nothing
  99. *
  100. * COMMENTS : Calls the Provider constructor.
  101. *
  102. *****************************************************************************/
  103. CNlbsNic::CNlbsNic (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) :
  104. Provider(lpwszName, lpwszNameSpace),
  105. m_fDelayedInitializationComplete(FALSE)
  106. {
  107. HRESULT hr;
  108. InitializeCriticalSection(&m_Lock);
  109. //
  110. // Static Initialization of the NlbConfigurationUpdate class.
  111. //
  112. NlbConfigurationUpdate::StaticInitialize();
  113. }
  114. /*****************************************************************************
  115. *
  116. * FUNCTION : CNlbsNic::~CNlbsNic
  117. *
  118. * DESCRIPTION : Destructor
  119. *
  120. * INPUTS : none
  121. *
  122. * RETURNS : nothing
  123. *
  124. * COMMENTS :
  125. *
  126. *****************************************************************************/
  127. CNlbsNic::~CNlbsNic ()
  128. {
  129. // this->DelayedDeinitialize();
  130. //
  131. // Static Deinitialization the NlbConfigurationUpdate class.
  132. //
  133. NlbConfigurationUpdate::StaticDeinitialize();
  134. DeleteCriticalSection(&m_Lock);
  135. }
  136. BOOL
  137. CNlbsNic::DelayedInitialize(VOID)
  138. {
  139. BOOL fRet = FALSE;
  140. mfn_Lock();
  141. if (m_fDelayedInitializationComplete == FALSE)
  142. {
  143. WBEMSTATUS Status;
  144. Status = CfgUtilInitialize(
  145. TRUE, // TRUE == server
  146. TRUE // TRUE == don't use ping
  147. );
  148. if (!FAILED(Status))
  149. {
  150. m_fDelayedInitializationComplete = TRUE;
  151. }
  152. }
  153. fRet = m_fDelayedInitializationComplete;
  154. mfn_Unlock();
  155. return fRet;
  156. }
  157. VOID
  158. CNlbsNic::DelayedDeinitialize(VOID)
  159. {
  160. mfn_Lock();
  161. if (m_fDelayedInitializationComplete)
  162. {
  163. //
  164. // Prepare NlbConfigurationUpdate for deinitialization.
  165. //
  166. NlbConfigurationUpdate::PrepareForDeinitialization();
  167. //
  168. // Deinitialize the configuration utilities
  169. //
  170. CfgUtilDeitialize();
  171. m_fDelayedInitializationComplete = FALSE;
  172. }
  173. mfn_Unlock();
  174. return;
  175. }
  176. /*****************************************************************************
  177. *
  178. * FUNCTION : CNlbsNic::EnumerateInstances
  179. *
  180. * DESCRIPTION : Returns all the instances of this class.
  181. *
  182. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  183. * A long that contains the flags described in
  184. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  185. * flags are handled by (and filtered out by) WinMgmt:
  186. * WBEM_FLAG_DEEP
  187. * WBEM_FLAG_SHALLOW
  188. * WBEM_FLAG_RETURN_IMMEDIATELY
  189. * WBEM_FLAG_FORWARD_ONLY
  190. * WBEM_FLAG_BIDIRECTIONAL
  191. *
  192. * RETURNS : WBEM_S_NO_ERROR if successful
  193. *
  194. * COMMENTS : TO DO: All instances on the machine should be returned here and
  195. * all properties that this class knows how to populate must
  196. * be filled in. If there are no instances, return
  197. * WBEM_S_NO_ERROR. It is not an error to have no instances.
  198. * If you are implementing a 'method only' provider, you
  199. * should remove this method.
  200. * DONE: mhakim
  201. *
  202. *****************************************************************************/
  203. HRESULT CNlbsNic::EnumerateInstances ( MethodContext* pMethodContext, long lFlags )
  204. {
  205. return WBEM_S_NO_ERROR;
  206. }
  207. /*****************************************************************************
  208. *
  209. * FUNCTION : CNlbsNic::GetObject
  210. *
  211. * DESCRIPTION : Find a single instance based on the key properties for the
  212. * class.
  213. *
  214. * INPUTS : A pointer to a CInstance object containing the key properties.
  215. * A long that contains the flags described in
  216. * IWbemServices::GetObjectAsync.
  217. *
  218. * RETURNS : WBEM_S_NO_ERROR if the instance can be found
  219. * WBEM_E_NOT_FOUND if the instance described by the key properties
  220. * could not be found
  221. * WBEM_E_FAILED if the instance could be found but another error
  222. * occurred.
  223. *
  224. * COMMENTS : If you are implementing a 'method only' provider, you should
  225. * remove this method.
  226. *
  227. *****************************************************************************/
  228. HRESULT CNlbsNic::GetObject ( CInstance* pInstance, long lFlags )
  229. {
  230. return WBEM_E_NOT_FOUND;
  231. }
  232. /*****************************************************************************
  233. *
  234. * FUNCTION : CNlbsNic::ExecQuery
  235. *
  236. * DESCRIPTION : You are passed a method context to use in the creation of
  237. * instances that satisfy the query, and a CFrameworkQuery
  238. * which describes the query. Create and populate all
  239. * instances which satisfy the query. You may return more
  240. * instances or more properties than are requested and WinMgmt
  241. * will post filter out any that do not apply.
  242. *
  243. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  244. * A query object describing the query to satisfy.
  245. * A long that contains the flags described in
  246. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  247. * flags are handled by (and filtered out by) WinMgmt:
  248. * WBEM_FLAG_FORWARD_ONLY
  249. * WBEM_FLAG_BIDIRECTIONAL
  250. * WBEM_FLAG_ENSURE_LOCATABLE
  251. *
  252. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for
  253. * this class or if the query is too complex for this class
  254. * to interpret. The framework will call the EnumerateInstances
  255. * function instead and let Winmgmt post filter.
  256. * WBEM_E_FAILED if the query failed
  257. * WBEM_S_NO_ERROR if query was successful
  258. *
  259. * COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt
  260. * will call your enumerate function to get all the instances and perform the
  261. * filtering for you. Unless you expect SIGNIFICANT savings from implementing
  262. * queries, you should remove this method. You should also remove this method
  263. * if you are implementing a 'method only' provider.
  264. *
  265. *****************************************************************************/
  266. HRESULT CNlbsNic::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
  267. {
  268. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  269. }
  270. /*****************************************************************************
  271. *
  272. * FUNCTION : CNlbsNic::PutInstance
  273. *
  274. * DESCRIPTION : PutInstance should be used in provider classes that can
  275. * write instance information back to the hardware or
  276. * software. For example: Win32_Environment will allow a
  277. * PutInstance to create or update an environment variable.
  278. * However, a class like MotherboardDevice will not allow
  279. * editing of the number of slots, since it is difficult for
  280. * a provider to affect that number.
  281. *
  282. * INPUTS : A pointer to a CInstance object containing the key properties.
  283. * A long that contains the flags described in
  284. * IWbemServices::PutInstanceAsync.
  285. *
  286. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
  287. * WBEM_E_FAILED if there is an error delivering the instance
  288. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  289. * are incorrect.
  290. * WBEM_S_NO_ERROR if instance is properly delivered
  291. *
  292. * COMMENTS : TO DO: If you don't intend to support writing to your provider,
  293. * or are creating a 'method only' provider, remove this
  294. * method.
  295. *
  296. *****************************************************************************/
  297. HRESULT CNlbsNic::PutInstance ( const CInstance &Instance, long lFlags)
  298. {
  299. // Use the CInstance Get functions (for example, call
  300. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  301. // the client requested.
  302. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  303. }
  304. /*****************************************************************************
  305. *
  306. * FUNCTION : CNlbsNic::DeleteInstance
  307. *
  308. * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information
  309. * to the software or hardware. For most hardware devices,
  310. * DeleteInstance should not be implemented, but for software
  311. * configuration, DeleteInstance implementation is plausible.
  312. *
  313. * INPUTS : A pointer to a CInstance object containing the key properties.
  314. * A long that contains the flags described in
  315. * IWbemServices::DeleteInstanceAsync.
  316. *
  317. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
  318. * WBEM_E_FAILED if there is an error deleting the instance.
  319. * WBEM_E_INVALID_PARAMETER if any of the instance properties
  320. * are incorrect.
  321. * WBEM_S_NO_ERROR if instance is properly deleted.
  322. *
  323. * COMMENTS : TO DO: If you don't intend to support deleting instances or are
  324. * creating a 'method only' provider, remove this method.
  325. *
  326. *****************************************************************************/
  327. HRESULT CNlbsNic::DeleteInstance ( const CInstance &Instance, long lFlags )
  328. {
  329. // Use the CInstance Get functions (for example, call
  330. // GetCHString(L"Name", sTemp)) against Instance to see the key values
  331. // the client requested.
  332. return (WBEM_E_PROVIDER_NOT_CAPABLE);
  333. }
  334. BOOL g_Impersonate = TRUE;
  335. /*****************************************************************************
  336. *
  337. * FUNCTION : CNlbsNic::ExecMethod
  338. *
  339. * DESCRIPTION : Override this function to provide support for methods.
  340. * A method is an entry point for the user of your provider
  341. * to request your class perform some function above and
  342. * beyond a change of state. (A change of state should be
  343. * handled by PutInstance() )
  344. *
  345. * INPUTS : A pointer to a CInstance containing the instance the method was executed against.
  346. * A string containing the method name
  347. * A pointer to the CInstance which contains the IN parameters.
  348. * A pointer to the CInstance to contain the OUT parameters.
  349. * A set of specialized method flags
  350. *
  351. * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
  352. * WBEM_S_NO_ERROR if method executes successfully
  353. * WBEM_E_FAILED if error occurs executing method
  354. *
  355. * COMMENTS : TO DO: If you don't intend to support Methods, remove this method.
  356. *
  357. *****************************************************************************/
  358. HRESULT CNlbsNic::ExecMethod ( const CInstance& Instance,
  359. const BSTR bstrMethodName,
  360. CInstance *pInParams,
  361. CInstance *pOutParams,
  362. long lFlags)
  363. {
  364. // For non-static methods, use the CInstance Get functions (for example,
  365. // call GetCHString(L"Name", sTemp)) against Instance to see the key
  366. // values the client requested.
  367. HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE;
  368. BOOL fImpersonating = FALSE;
  369. TRACE_INFO("-> %!FUNC! Method Name : %ls", bstrMethodName);
  370. if (!DelayedInitialize())
  371. {
  372. TRACE_CRIT("%!FUNC! -- delayed initialization failed!");
  373. goto end;
  374. }
  375. //
  376. // The NLB Manager provider runs under the context of "NetworkServiceHost" and hence
  377. // may NOT have sufficient privileges to perform sensitive operations (like binding/
  378. // unbinding NLB). So, we impersonate the client in order to use the client's (potentially
  379. // higher) credentials to perform such operations.
  380. //
  381. hresult = CoImpersonateClient();
  382. // 2/13/02 JosephJ SECURITY BUGBUG: is this check for RPC_E_CALL_COMPLETE
  383. // ok?
  384. if (hresult != S_OK && hresult != RPC_E_CALL_COMPLETE)
  385. {
  386. TRACE_CRIT("%!FUNC! ERROR: CoImpersonateClient returns 0x%08lx", (UINT) hresult);
  387. goto end;
  388. }
  389. fImpersonating = TRUE;
  390. // Adding this assert since we are not sure if RPC_E_CALL_COMPLETE
  391. // could be a legitimate error. - KarthicN, 4/12/02.
  392. ASSERT(hresult != RPC_E_CALL_COMPLETE);
  393. // Check if caller is an administrator?
  394. if (mfn_IsCallerAdmin() == FALSE)
  395. {
  396. TRACE_CRIT("%!FUNC! IsCallerAdmin() returned FALSE, returning WBEM_E_ACCESS_DENIED");
  397. hresult= WBEM_E_ACCESS_DENIED;
  398. goto end;
  399. }
  400. if (!g_Impersonate)
  401. {
  402. // Revert to using server credentials
  403. CoRevertToSelf();
  404. fImpersonating = FALSE;
  405. }
  406. hresult = ProvExecStaticMethod(bstrMethodName, pInParams, pOutParams);
  407. end:
  408. if (fImpersonating)
  409. {
  410. CoRevertToSelf();
  411. }
  412. TRACE_INFO("<- %!FUNC! return : 0x%08lx", (UINT)hresult);
  413. return hresult;
  414. }
  415. ////////////////////////////////////////////////////////////////////////////////
  416. //
  417. // Name : IsCallerAdmin
  418. // Description : This function checks if the caller is a member of the
  419. // Administrators local group. Since the provider is acting on
  420. // behalf of the client, it is important to IMPERSONATE the client
  421. // BEFORE calling this function. Impersonating the client will ensure
  422. // that this function checks if the client (& NOT this process that
  423. // runs under the identity of NetworkServiceHost) is a member of
  424. // the Administrators local group.
  425. // Arguments : None.
  426. // Return Value:
  427. // TRUE - Caller is a member of Administrators local group.
  428. // FALSE - Caller is NOT a member of Administrators local group.
  429. ////////////////////////////////////////////////////////////////////////////////
  430. BOOL CNlbsNic::mfn_IsCallerAdmin(VOID)
  431. {
  432. BOOL bRet;
  433. PSID AdministratorsGroup;
  434. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  435. TRACE_VERB(L"->%!FUNC!");
  436. //
  437. // Allocate and Initialize SID for Administrators in the built-in system domain
  438. //
  439. bRet = AllocateAndInitializeSid(&NtAuthority,
  440. 2,
  441. SECURITY_BUILTIN_DOMAIN_RID, // The built-in system domain (S-1-5-32)
  442. DOMAIN_ALIAS_RID_ADMINS, // Local group used for administration of the domain
  443. 0, 0, 0, 0, 0, 0,
  444. &AdministratorsGroup);
  445. if(bRet)
  446. {
  447. //
  448. // Is SID enabled in the impersonation token of the calling thread ?
  449. //
  450. if (!CheckTokenMembership(NULL, // Use the Impersonation token of the calling thread
  451. AdministratorsGroup,
  452. &bRet))
  453. {
  454. bRet = FALSE;
  455. TRACE_CRIT(L"%!FUNC! CheckTokenMembership() failed. Error : 0x%x", GetLastError());
  456. }
  457. FreeSid(AdministratorsGroup);
  458. }
  459. else
  460. {
  461. TRACE_CRIT("%!FUNC! AllocateAndInitializeSid() failed. Error : 0x%x", GetLastError());
  462. }
  463. TRACE_VERB(L"<-%!FUNC! Returning %ls", bRet ? L"TRUE" : L"FALSE");
  464. return bRet;
  465. }
  466. ////////////////////////////////////////////////////////////////////////////////
  467. //
  468. // Check_Load_Unload_Driver_Privilege
  469. //
  470. // Purpose: This function checks if the SE_LOAD_DRIVER_NAME (= "SeLoadDriverPrivilege")
  471. // is enabled in the impersonation access token. If there is no impersonation
  472. // access token and if the global impersonation flag is set to false (used for
  473. // debug purposes), then we check the primary access token.
  474. //
  475. ////////////////////////////////////////////////////////////////////////////////
  476. BOOL Check_Load_Unload_Driver_Privilege()
  477. {
  478. PRIVILEGE_SET PrivilegeSet;
  479. DWORD dwError;
  480. LUID Luid;
  481. BOOL bResult = FALSE;
  482. HANDLE TokenHandle = NULL;
  483. TRACE_INFO("->%!FUNC!");
  484. // Look up the LUID for "SeLoadDriverPrivilege"
  485. if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
  486. SE_LOAD_DRIVER_NAME, // "SeLoadDriverPrivilege" : Load and unload device drivers
  487. &Luid)) // receives LUID of privilege
  488. {
  489. TRACE_CRIT("%!FUNC! LookupPrivilegeValue error: %u", GetLastError());
  490. TRACE_INFO("<-%!FUNC! Returning FALSE");
  491. return FALSE;
  492. }
  493. //
  494. // Get a handle to the impersonation access token with TOKEN_QUERY right.
  495. //
  496. // Note: If this thread is NOT impersonating, then, the following call
  497. // will fail with ERROR_NO_TOKEN.
  498. //
  499. if (!OpenThreadToken(GetCurrentThread(),
  500. TOKEN_QUERY,
  501. FALSE, // Use the credentials of the client that is being impersonated
  502. &TokenHandle))
  503. {
  504. dwError = GetLastError();
  505. //
  506. // We were unable to open the impersonation access token. If it is because it doesn't
  507. // exist and if the "g_Impersonate" flag is set to FALSE , then try to open the primary
  508. // access token.
  509. // This blob is mainly to handle the case where we are intentionally NOT
  510. // impersonating by setting the "g_Impersonate" to FALSE. This flag was introduced
  511. // mainly to easily switch between impersonating and not impersonating for debugging
  512. // purposes. This was needed due to the problems that we encountered when impersonating
  513. // + using "NetworkServiceHost".
  514. // --KarthicN, May 6, 2002.
  515. //
  516. if ((dwError == ERROR_NO_TOKEN) && (g_Impersonate == FALSE))
  517. {
  518. if (!OpenProcessToken(GetCurrentProcess(),
  519. TOKEN_QUERY,
  520. &TokenHandle))
  521. {
  522. TRACE_CRIT("%!FUNC! OpenProcessToken error: %u", GetLastError());
  523. TRACE_INFO("<-%!FUNC! Returning FALSE");
  524. return FALSE;
  525. }
  526. }
  527. else
  528. {
  529. TRACE_CRIT("%!FUNC! OpenThreadToken error: %u, Global Impersonation flag = %ls", dwError, g_Impersonate ? L"TRUE" : L"FALSE");
  530. TRACE_INFO("<-%!FUNC! Returning FALSE");
  531. return FALSE;
  532. }
  533. }
  534. PrivilegeSet.PrivilegeCount = 1;
  535. PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
  536. PrivilegeSet.Privilege[0].Luid = Luid;
  537. PrivilegeSet.Privilege[0].Attributes = 0;
  538. if (!PrivilegeCheck(TokenHandle, &PrivilegeSet, &bResult))
  539. {
  540. bResult = FALSE;
  541. TRACE_CRIT("%!FUNC! PrivilegeCheck error: %u", GetLastError());
  542. }
  543. CloseHandle(TokenHandle);
  544. TRACE_INFO(L"<-%!FUNC! Returning %ls", bResult ? L"TRUE" : L"FALSE");
  545. return bResult;
  546. }
  547. WBEMSTATUS
  548. ProvExecStaticMethod(
  549. const BSTR bstrMethodName,
  550. CInstance *pInParams,
  551. CInstance *pOutParams
  552. )
  553. /*
  554. If bstrMethodName is one of the recognized static methods, we execute
  555. the method. Otherwise we return WBEM_E_PROVIDER_NOT_CAPABLE
  556. */
  557. {
  558. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  559. if (!g_UpdateConfigurationEnabled)
  560. {
  561. goto end;
  562. }
  563. if (_wcsicmp(bstrMethodName, L"GetCompatibleAdapterGuids") == 0)
  564. {
  565. Status = ProvGetCompatibleAdapterGuids(
  566. pInParams,
  567. pOutParams
  568. );
  569. }
  570. else if (_wcsicmp(bstrMethodName, L"GetClusterConfiguration") == 0)
  571. {
  572. Status = ProvGetClusterConfiguration(
  573. pInParams,
  574. pOutParams
  575. );
  576. }
  577. else if (_wcsicmp(bstrMethodName, L"UpdateClusterConfiguration") == 0)
  578. {
  579. //
  580. // NOTE:
  581. // One of the functions of this method is to bind/unbind NLB to the network adapter. Since this operation involves unloading
  582. // and loading of the device driver, PnP apis (that are called), attempt to enable the "SeLoadDriverPrivilege"
  583. // privilege in the impersonation access token. Enabling a privilege is successful only when the privilege is present,
  584. // in the first place to be enabled. When the wmi client and wmi provider are in the same machine, it was observed that
  585. // the "SeLoadDriverPrivilege" privilege was NOT event present in the impersonation access token of the server. This is
  586. // because, only the enabled privileges of the client are passed along to the server.
  587. // So, we now require that the client enable the "SeLoadDriverPrivilege" privilege in its access token before calling
  588. // this method. The following call to Check_Load_Unload_Driver_Privilege() checks if "SeLoadDriverPrivilege" privilege
  589. // is enabled in the impersonation access token (except if "g_Impersonate" is false). Although the PnP apis only
  590. // require that this privilege be present, we have decided to elevate the requirement to this privilege being present
  591. // AND enabled. This is because, if the privilege is NOT enabled, the operation to enable it may or may not succeed
  592. // depending on the client's credentials.
  593. // --KarthicN, May 6, 2002.
  594. //
  595. if(!Check_Load_Unload_Driver_Privilege())
  596. {
  597. TRACE_CRIT("%!FUNC! Check_Load_Unload_Driver_Privilege() failed, Returning WBEM_E_ACCESS_DENIED !!!");
  598. Status = WBEM_E_ACCESS_DENIED;
  599. goto end;
  600. }
  601. Status = ProvUpdateClusterConfiguration(
  602. pInParams,
  603. pOutParams
  604. );
  605. }
  606. else if (_wcsicmp(bstrMethodName, L"QueryConfigurationUpdateStatus") == 0)
  607. {
  608. Status = ProvQueryConfigurationUpdateStatus(
  609. pInParams,
  610. pOutParams
  611. );
  612. }
  613. else if (_wcsicmp(bstrMethodName, L"ControlCluster") == 0)
  614. {
  615. Status = ProvControlCluster(
  616. pInParams,
  617. pOutParams
  618. );
  619. }
  620. else if (_wcsicmp(bstrMethodName, L"GetClusterMembers") == 0)
  621. {
  622. Status = ProvGetClusterMembers(
  623. pInParams,
  624. pOutParams
  625. );
  626. }
  627. else if (_wcsicmp(bstrMethodName, L"RegisterManagementApplication") == 0)
  628. {
  629. Status = ProvRegisterManagementApplication(
  630. pInParams,
  631. pOutParams
  632. );
  633. }
  634. else if (_wcsicmp(bstrMethodName, L"UnregisterManagementApplication") == 0)
  635. {
  636. Status = ProvUnregisterManagementApplication(
  637. pInParams,
  638. pOutParams
  639. );
  640. }
  641. end:
  642. return Status;
  643. }
  644. WBEMSTATUS
  645. ProvGetCompatibleAdapterGuids(
  646. CInstance *pInParams,
  647. CInstance *pOutParams
  648. )
  649. /*++
  650. Implementation of the "GetCompatibleAdapterGuids" method.
  651. --*/
  652. {
  653. LPWSTR *pszNics = NULL;
  654. UINT NumNics = 0;
  655. UINT NumNlbBound = 0;
  656. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  657. /*
  658. [OUT] String AdapterGuids[], // "{......}"
  659. [OUT] uint32 NumBoundToNlb
  660. */
  661. TRACE_VERB(L"->%!FUNC!");
  662. Status = CfgUtilsGetNlbCompatibleNics(&pszNics, &NumNics, &NumNlbBound);
  663. if (FAILED(Status))
  664. {
  665. TRACE_CRIT("CfgUtilsGetNlbCompatibleNics returns error 0x%08lx",
  666. (UINT) Status);
  667. pszNics = NULL;
  668. goto end;
  669. }
  670. //
  671. // Fill in AdapterGuids[]
  672. //
  673. {
  674. SAFEARRAY *pSA = NULL;
  675. Status = CfgUtilSafeArrayFromStrings(
  676. (LPCWSTR*) pszNics,
  677. NumNics,
  678. &pSA
  679. );
  680. if (FAILED(Status))
  681. {
  682. pSA = NULL;
  683. goto end;
  684. }
  685. pOutParams->SetStringArray(
  686. L"AdapterGuids",
  687. *pSA // pass by reference
  688. );
  689. SafeArrayDestroy(pSA);
  690. pSA = NULL;
  691. }
  692. pOutParams->SetDWORD(L"NumBoundToNlb", NumNlbBound);
  693. Status = WBEM_NO_ERROR;
  694. end:
  695. pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
  696. if (pszNics != NULL)
  697. {
  698. delete pszNics;
  699. pszNics = NULL;
  700. }
  701. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  702. return WBEM_NO_ERROR; // real status is in the "ReturnResult" outparm.
  703. }
  704. WBEMSTATUS
  705. ProvGetClusterConfiguration(
  706. CInstance *pInParams,
  707. CInstance *pOutParams
  708. )
  709. /*++
  710. WMI provider wrapper around NlbConfigurationUpdate::GetConfiguration
  711. --*/
  712. {
  713. LPCWSTR pAdapterGuid = NULL;
  714. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  715. CHString sTemp;
  716. bool fRet;
  717. NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
  718. SAFEARRAY *pSA = NULL;
  719. bool fNicNotFound = FALSE;
  720. /*
  721. [IN] String AdapterGuid,
  722. [OUT] uint32 Generation,
  723. [OUT] String NetworkAddresses[], // "10.1.1.1/255.0.0.0"
  724. [OUT] Boolean NLBBound,
  725. [OUT] Boolean DHCPEnabled,
  726. [OUT] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
  727. [OUT] String ClusterName,
  728. [OUT] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
  729. [OUT] String PortRules[],
  730. [OUT] uint32 HostPriority,
  731. [OUT] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
  732. [OUT] uint32 ClusterModeOnStart, // 0 : STOPPED, 1 : STARTED, 2 : SUSPENDED
  733. [OUT] Boolean PersistSuspendOnReboot,
  734. [OUT] Boolean RemoteControlEnabled,
  735. [OUT] uint32 HashedRemoteControlPassword
  736. */
  737. fRet = pInParams->GetCHString( L"AdapterGuid", sTemp );
  738. if (!fRet)
  739. {
  740. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  741. Status = WBEM_E_INVALID_PARAMETER;
  742. goto end;
  743. }
  744. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  745. // buffer -- see operator LPCWSTR() of WString docs.
  746. //
  747. pAdapterGuid = (LPCWSTR) sTemp;
  748. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  749. {
  750. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  751. Status = WBEM_E_INVALID_PARAMETER;
  752. goto end;
  753. }
  754. else
  755. {
  756. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  757. }
  758. Status = NlbConfigurationUpdate::GetConfiguration(
  759. pAdapterGuid,
  760. &Cfg
  761. );
  762. if (FAILED(Status))
  763. {
  764. if (Status == WBEM_E_NOT_FOUND)
  765. {
  766. fNicNotFound = TRUE;
  767. }
  768. goto end;
  769. }
  770. pOutParams->SetDWORD(L"Generation", Cfg.GetGeneration());
  771. //
  772. // Fill in NetworkAddresses[]
  773. //
  774. {
  775. Status = Cfg.GetNetworkAddressesSafeArray(
  776. &pSA
  777. );
  778. if (FAILED(Status))
  779. {
  780. TRACE_CRIT(
  781. "%!FUNC!: couldn't extract network addresses from Cfg"
  782. " for NIC %ws",
  783. pAdapterGuid
  784. );
  785. pSA = NULL;
  786. goto end;
  787. }
  788. if (pSA!=NULL)
  789. {
  790. pOutParams->SetStringArray(
  791. L"NetworkAddresses",
  792. *pSA // pass by reference
  793. );
  794. SafeArrayDestroy(pSA);
  795. pSA = NULL;
  796. }
  797. }
  798. //
  799. // Adapter Friendly Name
  800. //
  801. {
  802. LPWSTR szFriendlyName = NULL;
  803. Status = Cfg.GetFriendlyName(&szFriendlyName);
  804. if (FAILED(Status))
  805. {
  806. TRACE_CRIT(
  807. "%!FUNC!: Could not extract adapter friendly name for NIC %ws",
  808. pAdapterGuid
  809. );
  810. goto end;
  811. }
  812. pOutParams->SetCHString(L"FriendlyName", szFriendlyName);
  813. delete (szFriendlyName);
  814. szFriendlyName = NULL;
  815. }
  816. //
  817. // Set dhcp state
  818. //
  819. pOutParams->Setbool(L"DHCPEnabled", Cfg.fDHCP);
  820. if (!Cfg.IsNlbBound())
  821. {
  822. //
  823. // NLB is not bound
  824. //
  825. pOutParams->Setbool(L"NLBBound", FALSE);
  826. Status = WBEM_NO_ERROR;
  827. goto end;
  828. }
  829. //
  830. // NLB is bound
  831. //
  832. pOutParams->Setbool(L"NLBBound", TRUE);
  833. if (!Cfg.IsValidNlbConfig())
  834. {
  835. TRACE_CRIT(
  836. "%!FUNC!: NLB-specific configuration on NIC %ws is invalid",
  837. pAdapterGuid
  838. );
  839. goto end;
  840. }
  841. //
  842. // Cluster name
  843. //
  844. {
  845. LPWSTR szName = NULL;
  846. Status = Cfg.GetClusterName(&szName);
  847. if (FAILED(Status))
  848. {
  849. TRACE_CRIT(
  850. "%!FUNC!: Could not extract cluster name for NIC %ws",
  851. pAdapterGuid
  852. );
  853. goto end;
  854. }
  855. pOutParams->SetCHString(L"ClusterName", szName);
  856. delete (szName);
  857. szName = NULL;
  858. }
  859. //
  860. // Cluster and dedicated network addresses
  861. //
  862. {
  863. LPWSTR szAddress = NULL;
  864. Status = Cfg.GetClusterNetworkAddress(&szAddress);
  865. if (FAILED(Status))
  866. {
  867. TRACE_CRIT(
  868. "%!FUNC!: Could not extract cluster address for NIC %ws",
  869. pAdapterGuid
  870. );
  871. goto end;
  872. }
  873. pOutParams->SetCHString(L"ClusterNetworkAddress", szAddress);
  874. delete (szAddress);
  875. szAddress = NULL;
  876. Status = Cfg.GetDedicatedNetworkAddress(&szAddress);
  877. if (FAILED(Status))
  878. {
  879. TRACE_CRIT(
  880. "%!FUNC!: Could not extract dedicated address for NIC %ws",
  881. pAdapterGuid
  882. );
  883. goto end;
  884. }
  885. pOutParams->SetCHString(L"DedicatedNetworkAddress", szAddress);
  886. delete (szAddress);
  887. szAddress = NULL;
  888. }
  889. //
  890. // TrafficMode
  891. //
  892. {
  893. LPCWSTR szMode = NULL;
  894. switch(Cfg.GetTrafficMode())
  895. {
  896. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST:
  897. szMode = L"UNICAST";
  898. break;
  899. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST:
  900. szMode = L"MULTICAST";
  901. break;
  902. case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST:
  903. szMode = L"IGMPMULTICAST";
  904. break;
  905. default:
  906. assert(FALSE);
  907. Status = WBEM_E_CRITICAL_ERROR;
  908. goto end;
  909. }
  910. pOutParams->SetCHString(L"TrafficMode", szMode);
  911. }
  912. pOutParams->SetDWORD(L"HostPriority", Cfg.GetHostPriority());
  913. /*
  914. if (Cfg.GetClusterModeOnStart() ==
  915. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED)
  916. {
  917. pOutParams->Setbool(L"ClusterModeOnStart", TRUE);
  918. }
  919. else
  920. {
  921. pOutParams->Setbool(L"ClusterModeOnStart", FALSE);
  922. }
  923. */
  924. pOutParams->SetDWORD(L"ClusterModeOnStart", Cfg.GetClusterModeOnStart());
  925. pOutParams->Setbool(L"PersistSuspendOnReboot", Cfg.GetPersistSuspendOnReboot());
  926. pOutParams->Setbool(L"RemoteControlEnabled", Cfg.GetRemoteControlEnabled());
  927. pOutParams->SetDWORD(
  928. L"HashedRemoteControlPassword",
  929. CfgUtilGetHashedRemoteControlPassword(&Cfg.NlbParams)
  930. );
  931. //
  932. // [OUT] String PortRules[],
  933. //
  934. {
  935. LPWSTR *pszPortRules = NULL;
  936. UINT NumPortRules = 0;
  937. pSA=NULL;
  938. Status = Cfg.GetPortRules(
  939. &pszPortRules,
  940. &NumPortRules
  941. );
  942. if (FAILED(Status))
  943. {
  944. pszPortRules = NULL;
  945. goto end;
  946. }
  947. Status = CfgUtilSafeArrayFromStrings(
  948. (LPCWSTR*) pszPortRules,
  949. NumPortRules, // can be zero
  950. &pSA
  951. );
  952. if (FAILED(Status))
  953. {
  954. TRACE_CRIT(
  955. "%!FUNC!: couldn't extract port rules from Cfg"
  956. " for NIC %ws",
  957. pAdapterGuid
  958. );
  959. pSA = NULL;
  960. goto end;
  961. }
  962. if (pSA!=NULL)
  963. {
  964. pOutParams->SetStringArray(
  965. L"PortRules",
  966. *pSA // pass by reference
  967. );
  968. SafeArrayDestroy(pSA);
  969. pSA = NULL;
  970. }
  971. }
  972. Status = WBEM_NO_ERROR;
  973. end:
  974. if (FAILED(Status))
  975. {
  976. //
  977. // We want to reserve WBEM_NOT_FOUND for the SPECIFIC case
  978. // of the NIC not being found
  979. //
  980. if (Status == WBEM_E_NOT_FOUND && !fNicNotFound)
  981. {
  982. Status = WBEM_E_FAILED;
  983. }
  984. pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
  985. }
  986. else
  987. {
  988. pOutParams->SetDWORD(L"ReturnValue", (DWORD) WBEM_NO_ERROR);
  989. }
  990. if (pSA!=NULL)
  991. {
  992. SafeArrayDestroy(pSA);
  993. pSA = NULL;
  994. }
  995. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  996. return WBEM_NO_ERROR;
  997. }
  998. WBEMSTATUS
  999. ProvUpdateClusterConfiguration(
  1000. CInstance *pInParams,
  1001. CInstance *pOutParams
  1002. )
  1003. /*++
  1004. WMI provider wrapper NlbConfigurationUpdate::UpdateConfiguration
  1005. with some additional wrinkles:
  1006. we selectively update the current version.
  1007. --*/
  1008. {
  1009. LPCWSTR pAdapterGuid = NULL;
  1010. LPCWSTR pClientDescription = L"Unspecified WMI Client"; // TODO: localize
  1011. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  1012. CHString sClientDescription;
  1013. CHString sAdapterGuid;
  1014. CHString sTemp;
  1015. bool fRet;
  1016. NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
  1017. SAFEARRAY *pSA = NULL;
  1018. /*
  1019. [IN] String ClientDescription,
  1020. [IN] String AdapterGuid,
  1021. [IN] uint32 Generation,
  1022. [IN] Boolean PartialUpdate,
  1023. [IN] String NetworkAddresses[], // "10.1.1.1/255.255.255.255"
  1024. [IN] Boolean NLBBound,
  1025. [IN] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
  1026. [IN] String ClusterName,
  1027. [IN] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
  1028. [IN] String PortRules[],
  1029. [IN] uint32 HostPriority,
  1030. [IN] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
  1031. [IN] uint32 ClusterModeOnStart, // 0 : STOPPED, 1 : STARTED, 2 : SUSPENDED
  1032. [IN] Boolean PersistSuspendOnReboot,
  1033. [IN] Boolean RemoteControlEnabled,
  1034. [IN] String Password,
  1035. [OUT] uint32 NewGeneration,
  1036. [OUT] String Log
  1037. */
  1038. fRet = pInParams->GetCHString( L"ClientDescription", sClientDescription);
  1039. if (fRet)
  1040. {
  1041. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1042. pClientDescription = (LPCWSTR) sClientDescription;
  1043. }
  1044. fRet = pInParams->GetCHString( L"AdapterGuid", sAdapterGuid);
  1045. if (!fRet)
  1046. {
  1047. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  1048. Status = WBEM_E_INVALID_PARAMETER;
  1049. goto end;
  1050. }
  1051. //
  1052. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1053. // buffer -- see operator LPCWSTR() of WString docs.
  1054. //
  1055. pAdapterGuid = (LPCWSTR) sAdapterGuid;
  1056. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  1057. {
  1058. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  1059. Status = WBEM_E_INVALID_PARAMETER;
  1060. goto end;
  1061. }
  1062. else
  1063. {
  1064. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  1065. }
  1066. //
  1067. // Get the current configuration
  1068. //
  1069. Status = NlbConfigurationUpdate::GetConfiguration(
  1070. pAdapterGuid,
  1071. &Cfg
  1072. );
  1073. if (FAILED(Status))
  1074. {
  1075. goto end;
  1076. }
  1077. //
  1078. // Modify the snapshot of the current configuration with whatever
  1079. // cluster configuration information is specified in the input
  1080. // parameters
  1081. //
  1082. {
  1083. DWORD InGeneration = 0;
  1084. bool NlbBound = FALSE;
  1085. bool bResult = FALSE;
  1086. bool bPartialUpdate = FALSE;
  1087. bool bCheckForAddressConflicts = FALSE;
  1088. //
  1089. // Determine if this is a partial or full update.
  1090. // If partial update, we allow a subset of cluster configuration
  1091. // parameters to be specified, but allow only a restricted set
  1092. // of update operations.
  1093. //
  1094. // Disallowed partial update operations:
  1095. // - Transitions between bound and !bound
  1096. // - Currently bound but nlb parameters are invalid
  1097. //
  1098. // Some allowed partial updates:
  1099. // - Modifying IP address lists
  1100. // - Modifying cluster / dedicated addresses/subnets
  1101. // - Modifying existing portrules
  1102. // - Adding/deleting port rules
  1103. //
  1104. bResult = pInParams->GetDWORD(
  1105. L"Generation", // <--------------------------------
  1106. InGeneration
  1107. );
  1108. if (!bResult)
  1109. {
  1110. //
  1111. // We allow generation to be unspecified.
  1112. //
  1113. InGeneration = 0;
  1114. }
  1115. else
  1116. {
  1117. //
  1118. // If generation is specified,
  1119. // we verify that the current generation matches the
  1120. // specified generation.
  1121. // TODO: this really must be done in the context of
  1122. // mfn_Start update -- after we've acquired the global lock!
  1123. //
  1124. if (InGeneration != Cfg.GetGeneration())
  1125. {
  1126. TRACE_CRIT("Partial update: input generation(%lu) != current generation(%lu)", InGeneration, Cfg.GetGeneration());
  1127. Status = WBEM_E_HANDLE_OUT_OF_DATE;
  1128. goto end;
  1129. }
  1130. }
  1131. bResult = pInParams->Getbool(
  1132. L"CheckForAddressConflicts", // <--------------------------------
  1133. bCheckForAddressConflicts
  1134. );
  1135. if (!bResult)
  1136. {
  1137. TRACE_CRIT(L"Could not read CheckForAddressConflicts -- assuming FALSE\n");
  1138. bCheckForAddressConflicts = FALSE;
  1139. }
  1140. bResult = pInParams->Getbool(
  1141. L"NLBBound", // <--------------------------------
  1142. NlbBound
  1143. );
  1144. if (!bResult)
  1145. {
  1146. NlbBound = Cfg.IsNlbBound();
  1147. TRACE_CRIT(L"Could not read NLBBound -- assuming current state %d.",
  1148. NlbBound);
  1149. }
  1150. bResult = pInParams->GetStringArray(
  1151. L"NetworkAddresses", // <--------------------------------
  1152. pSA
  1153. );
  1154. if (!bResult)
  1155. {
  1156. //
  1157. // We set pCfg to zero addresses, which causes update to
  1158. // use it's own defaults...
  1159. //
  1160. TRACE_CRIT(L"Could not read Network addresses -- using defaults");
  1161. Status = Cfg.SetNetworkAddresses(NULL, 0);
  1162. pSA = NULL;
  1163. }
  1164. else
  1165. {
  1166. if (pSA != NULL)
  1167. {
  1168. Status = Cfg.SetNetworkAddressesSafeArray(pSA);
  1169. SafeArrayDestroy(pSA);
  1170. pSA = NULL;
  1171. }
  1172. }
  1173. if (!NlbBound)
  1174. {
  1175. // NLB is not to be bound -- no need to read the input params.
  1176. Cfg.fBound = FALSE;
  1177. Cfg.fValidNlbCfg = FALSE;
  1178. }
  1179. else
  1180. {
  1181. BOOL fNewConfig = FALSE;
  1182. bool bAddDedicatedIp = FALSE;
  1183. bool bAddClusterIps = FALSE;
  1184. if (!Cfg.fBound || Cfg.fValidNlbCfg == FALSE)
  1185. {
  1186. //
  1187. // If we were previously unbound or we were bound but with
  1188. // a bad configuration, we need to setup our
  1189. // new cfg with good defaults
  1190. //
  1191. CfgUtilInitializeParams(&Cfg.NlbParams);
  1192. Cfg.fBound = TRUE;
  1193. Cfg.fValidNlbCfg = TRUE;
  1194. fNewConfig = TRUE;
  1195. }
  1196. bResult = pInParams->Getbool(
  1197. L"AddDedicatedIp", // <------------------------
  1198. bAddDedicatedIp
  1199. );
  1200. if (!bResult)
  1201. {
  1202. TRACE_CRIT(L"Could not read AddDedicatedIp -- assuming TRUE\n");
  1203. bAddDedicatedIp = TRUE;
  1204. }
  1205. Cfg.fAddDedicatedIp = (bAddDedicatedIp!=FALSE);
  1206. bResult = pInParams->Getbool(
  1207. L"AddClusterIps", // <-------------------------
  1208. bAddClusterIps
  1209. );
  1210. if (!bResult)
  1211. {
  1212. TRACE_CRIT(L"Could not read AddClusterIps -- assuming TRUE\n");
  1213. bAddClusterIps = TRUE;
  1214. }
  1215. Cfg.fAddClusterIps = (bAddClusterIps!=FALSE);
  1216. bResult = pInParams->GetCHString(
  1217. L"ClusterNetworkAddress", // <--------------------
  1218. sTemp
  1219. );
  1220. if (!bResult)
  1221. {
  1222. if (fNewConfig)
  1223. {
  1224. //
  1225. // Cluster address MUST be specified for new config.
  1226. //
  1227. TRACE_CRIT(L"ERROR: Could not read Cluster IP for new config.");
  1228. Status = WBEM_E_INVALID_PARAMETER;
  1229. goto end;
  1230. }
  1231. TRACE_CRIT(L"Could not read Cluster IP. Keeping existing.");
  1232. }
  1233. else
  1234. {
  1235. LPCWSTR szClusterNetworkAddress = NULL;
  1236. szClusterNetworkAddress = (LPCWSTR) sTemp; // no copies here.
  1237. Cfg.SetClusterNetworkAddress(szClusterNetworkAddress);
  1238. szClusterNetworkAddress = NULL;
  1239. }
  1240. bResult = pInParams->GetCHString(
  1241. L"ClusterName", // <-------------------------
  1242. sTemp
  1243. );
  1244. if (!bResult)
  1245. {
  1246. TRACE_CRIT(L"Could not read Cluster Name. Keeping existing");
  1247. }
  1248. else
  1249. {
  1250. LPCWSTR szClusterName = NULL;
  1251. szClusterName = (LPCWSTR) sTemp; // no copies here.
  1252. Cfg.SetClusterName(szClusterName);
  1253. szClusterName = NULL;
  1254. }
  1255. //
  1256. // Traffic mode
  1257. //
  1258. {
  1259. bResult = pInParams->GetCHString(
  1260. L"TrafficMode", // <-------------------------
  1261. sTemp
  1262. );
  1263. if (!bResult)
  1264. {
  1265. TRACE_CRIT(L"Could not read TrafficMode. Keeping existing");
  1266. }
  1267. else
  1268. {
  1269. LPCWSTR szTrafficMode = NULL;
  1270. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode
  1271. = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  1272. szTrafficMode = (LPCWSTR) sTemp; // no copies here.
  1273. if (!_wcsicmp(szTrafficMode, L"UNICAST"))
  1274. {
  1275. TrafficMode =
  1276. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
  1277. }
  1278. else if (!_wcsicmp(szTrafficMode, L"MULTICAST"))
  1279. {
  1280. TrafficMode =
  1281. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST;
  1282. }
  1283. else if (!_wcsicmp(szTrafficMode, L"IGMPMULTICAST"))
  1284. {
  1285. TrafficMode =
  1286. NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST;
  1287. }
  1288. else
  1289. {
  1290. TRACE_CRIT("Invalid TrafficMode: %ws", szTrafficMode);
  1291. Status = WBEM_E_INVALID_PARAMETER;
  1292. goto end;
  1293. }
  1294. Cfg.SetTrafficMode(TrafficMode);
  1295. szTrafficMode = NULL;
  1296. }
  1297. }
  1298. //
  1299. // String PortRules[]
  1300. //
  1301. bResult = pInParams->GetStringArray(
  1302. L"PortRules", // <--------------------------------
  1303. pSA
  1304. );
  1305. if (!bResult)
  1306. {
  1307. //
  1308. // We set pCfg to zero port rules
  1309. //
  1310. TRACE_CRIT(L"Could not read port rules-- assuming ZERO");
  1311. Status = Cfg.SetPortRules(NULL, 0);
  1312. pSA = NULL;
  1313. }
  1314. else
  1315. {
  1316. if (pSA != NULL)
  1317. {
  1318. LPWSTR *pStrings=NULL;
  1319. UINT NumStrings = 0;
  1320. Status = CfgUtilStringsFromSafeArray(
  1321. pSA,
  1322. &pStrings, // delete when done
  1323. &NumStrings
  1324. );
  1325. if (FAILED(Status))
  1326. {
  1327. pStrings=NULL;
  1328. TRACE_CRIT(L"Could not extract port rules");
  1329. goto end;
  1330. }
  1331. Status = Cfg.SetPortRules(
  1332. (LPCWSTR*)pStrings,
  1333. NumStrings
  1334. );
  1335. delete pStrings;
  1336. SafeArrayDestroy(pSA);
  1337. pSA = NULL;
  1338. }
  1339. }
  1340. DWORD HostPriority = 0;
  1341. bResult = pInParams->GetDWORD(
  1342. L"HostPriority", // <---------------------------
  1343. HostPriority
  1344. );
  1345. if (!bResult)
  1346. {
  1347. TRACE_CRIT(L"Could not read HostPriority. Keeping existing");
  1348. }
  1349. else
  1350. {
  1351. Cfg.SetHostPriority(HostPriority);
  1352. }
  1353. bResult = pInParams->GetCHString(
  1354. L"DedicatedNetworkAddress", // <-----------------
  1355. sTemp
  1356. );
  1357. if (!bResult)
  1358. {
  1359. TRACE_CRIT(L"Could not dedicated IP. Keeping existing");
  1360. }
  1361. else
  1362. {
  1363. LPCWSTR szAddress = NULL;
  1364. szAddress = (LPCWSTR) sTemp; // no copies here.
  1365. Cfg.SetDedicatedNetworkAddress(szAddress);
  1366. szAddress = NULL;
  1367. }
  1368. //
  1369. // StartMode
  1370. //
  1371. {
  1372. DWORD ClusterModeOnStart = FALSE;
  1373. bResult = pInParams->GetDWORD(
  1374. L"ClusterModeOnStart", // <-----------------
  1375. ClusterModeOnStart
  1376. );
  1377. if (!bResult)
  1378. {
  1379. TRACE_CRIT(L"Could not read StartMode. Keeping existing");
  1380. }
  1381. else
  1382. {
  1383. /*
  1384. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
  1385. ClusterModeOnStart;
  1386. if (StartMode)
  1387. {
  1388. ClusterModeOnStart =
  1389. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED;
  1390. }
  1391. else
  1392. {
  1393. ClusterModeOnStart =
  1394. NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
  1395. }
  1396. */
  1397. Cfg.SetClusterModeOnStart(ClusterModeOnStart);
  1398. }
  1399. }
  1400. //
  1401. // Persist Suspend on Reboot
  1402. //
  1403. {
  1404. bool bPersistSuspendOnReboot;
  1405. bResult = pInParams->Getbool(
  1406. L"PersistSuspendOnReboot", // <---------------
  1407. bPersistSuspendOnReboot
  1408. );
  1409. if (!bResult)
  1410. {
  1411. TRACE_CRIT(L"Could not read PersistSuspendOnReboot. Keeping existing");
  1412. }
  1413. else
  1414. {
  1415. Cfg.SetPersistSuspendOnReboot(bPersistSuspendOnReboot);
  1416. }
  1417. }
  1418. //
  1419. // Remote control enabled
  1420. //
  1421. {
  1422. bool bRemoteControlEnabled;
  1423. bResult = pInParams->Getbool(
  1424. L"RemoteControlEnabled", // <---------------
  1425. bRemoteControlEnabled
  1426. );
  1427. if (!bResult)
  1428. {
  1429. TRACE_CRIT(L"Could not read RemoteControlEnabled. Keeping existing");
  1430. }
  1431. else
  1432. {
  1433. Cfg.SetRemoteControlEnabled(bRemoteControlEnabled!=FALSE);
  1434. if (bRemoteControlEnabled)
  1435. {
  1436. DWORD dwPwd;
  1437. LPCWSTR szPwd = NULL;
  1438. //
  1439. // Now read and set string or hashed version of password
  1440. // if either are specified.
  1441. //
  1442. bResult = pInParams->GetCHString(
  1443. L"RemoteControlPassword", // <-----------------
  1444. sTemp
  1445. );
  1446. if (bResult)
  1447. {
  1448. szPwd = (LPCWSTR) sTemp; // no copies here.
  1449. (VOID) CfgUtilSetRemotePassword(&Cfg.NlbParams, szPwd);
  1450. }
  1451. if (szPwd == NULL)
  1452. {
  1453. //
  1454. // Only look for hashed pwd if the real pwd is
  1455. // not specified.
  1456. //
  1457. bResult = pInParams->GetDWORD(
  1458. L"HashedRemoteControlPassword", // <-----------------
  1459. dwPwd
  1460. );
  1461. if (bResult)
  1462. {
  1463. CfgUtilSetHashedRemoteControlPassword(
  1464. &Cfg.NlbParams,
  1465. dwPwd
  1466. );
  1467. }
  1468. }
  1469. }
  1470. }
  1471. }
  1472. //
  1473. // TODO: if PartialUpdate is specified, we need to
  1474. // make sure that fValidNlbCfg is already set.
  1475. //
  1476. Cfg.fValidNlbCfg = TRUE;
  1477. } while (FALSE) ;
  1478. }
  1479. //
  1480. // Call NlbConfigurationUpdate::DuUpdate to do the actual work.
  1481. //
  1482. UINT NewGeneration = 0;
  1483. LPWSTR pLog = NULL;
  1484. try
  1485. {
  1486. Status = NlbConfigurationUpdate::DoUpdate(
  1487. pAdapterGuid,
  1488. pClientDescription,
  1489. &Cfg,
  1490. &NewGeneration,
  1491. &pLog
  1492. );
  1493. }
  1494. catch (...)
  1495. {
  1496. TRACE_CRIT(L"%!FUNC! Caught exception!\n");
  1497. ASSERT(!"Caught exception!");
  1498. throw;
  1499. }
  1500. //
  1501. // Fill out the out parameters: status new generation and log
  1502. //
  1503. pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
  1504. pOutParams->SetDWORD(L"NewGeneration", (DWORD) NewGeneration);
  1505. if (pLog != NULL)
  1506. {
  1507. pOutParams->SetCHString(L"Log", pLog);
  1508. delete pLog;
  1509. pLog = NULL;
  1510. }
  1511. //
  1512. // If we've actually called DoUpdate,
  1513. // we always return WBEM_NO_ERROR. The return value has the
  1514. // real result.
  1515. //
  1516. Status = WBEM_NO_ERROR;
  1517. end:
  1518. if (pSA!=NULL)
  1519. {
  1520. SafeArrayDestroy(pSA);
  1521. pSA = NULL;
  1522. }
  1523. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1524. return Status;
  1525. }
  1526. WBEMSTATUS
  1527. ProvQueryConfigurationUpdateStatus(
  1528. CInstance *pInParams,
  1529. CInstance *pOutParams
  1530. )
  1531. /*++
  1532. WMI provider wrapper around NlbConfigurationUpdate::GetUpdateStatus
  1533. --*/
  1534. {
  1535. LPCWSTR pAdapterGuid = NULL;
  1536. WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
  1537. CHString sTemp;
  1538. bool fRet;
  1539. DWORD Generation = 0;
  1540. /*
  1541. [IN] String AdapterGuid,
  1542. [IN] uint32 Generation,
  1543. [OUT] String Log
  1544. */
  1545. fRet = pInParams->GetCHString( L"AdapterGuid", sTemp);
  1546. if (!fRet)
  1547. {
  1548. TRACE_CRIT("->%!FUNC!: Missing adapter guid!");
  1549. Status = WBEM_E_INVALID_PARAMETER;
  1550. goto end;
  1551. }
  1552. //
  1553. // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
  1554. // buffer -- see operator LPCWSTR() of WString docs.
  1555. //
  1556. pAdapterGuid = (LPCWSTR) sTemp;
  1557. if (pAdapterGuid == NULL || *pAdapterGuid == 0)
  1558. {
  1559. TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!");
  1560. Status = WBEM_E_INVALID_PARAMETER;
  1561. goto end;
  1562. }
  1563. else
  1564. {
  1565. TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid);
  1566. }
  1567. fRet = pInParams->GetDWORD(
  1568. L"Generation", // <--------------------------------
  1569. Generation
  1570. );
  1571. if (!fRet)
  1572. {
  1573. TRACE_CRIT("%!FUNC!: Missing generation!");
  1574. Status = WBEM_E_INVALID_PARAMETER;
  1575. goto end;
  1576. }
  1577. //
  1578. // Call NlbConfigurationUpdate::GetUpdateResult to do the actual work.
  1579. //
  1580. LPWSTR pLog = NULL;
  1581. WBEMSTATUS CompletionStatus = WBEM_NO_ERROR;
  1582. Status = NlbConfigurationUpdate::GetUpdateStatus(
  1583. pAdapterGuid,
  1584. Generation,
  1585. FALSE, // FALSE == Don't delete completion record
  1586. &CompletionStatus,
  1587. &pLog
  1588. );
  1589. if (!FAILED(Status))
  1590. {
  1591. //
  1592. // Fill out the out parameters: status new generation and log
  1593. //
  1594. pOutParams->SetDWORD(L"ReturnValue", (DWORD) CompletionStatus);
  1595. if (pLog != NULL)
  1596. {
  1597. pOutParams->SetCHString(L"Log", pLog);
  1598. delete pLog;
  1599. pLog = NULL;
  1600. }
  1601. }
  1602. end:
  1603. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1604. return Status;
  1605. }
  1606. WBEMSTATUS
  1607. ProvControlCluster(
  1608. CInstance *pInParams,
  1609. CInstance *pOutParams
  1610. )
  1611. /*++
  1612. WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
  1613. TODO:
  1614. Implement NlbConfigurationUpdate::ProvControlCluster,
  1615. which should be a wrapper around around WlbsControlCluster where
  1616. the work is actually done (WlbsControlCluster will take the
  1617. handle to the device).
  1618. --*/
  1619. {
  1620. LPCWSTR szAdapterGuid, szVip;
  1621. CHString sAdapterGuid, sVip;
  1622. bool fRet;
  1623. DWORD dwPort, dwRetVal, dwVip, dwHostMap, dwStatus;
  1624. WBEMSTATUS Status;
  1625. WLBS_OPERATION_CODES Opcode;
  1626. TRACE_VERB(L"->%!FUNC!");
  1627. dwRetVal = dwStatus = WLBS_FAILURE;
  1628. dwHostMap = 0;
  1629. Status = WBEM_NO_ERROR;
  1630. szVip = NULL;
  1631. dwVip = dwPort = 0;
  1632. // Get the Adapter GUID
  1633. fRet = pInParams->GetCHString(L"AdapterGuid", sAdapterGuid);
  1634. if (!fRet)
  1635. {
  1636. TRACE_CRIT(L"%!FUNC!: Missing adapter guid!");
  1637. Status = WBEM_E_INVALID_PARAMETER;
  1638. goto end;
  1639. }
  1640. else
  1641. {
  1642. szAdapterGuid = (LPCWSTR) sAdapterGuid;
  1643. if (szAdapterGuid == NULL || *szAdapterGuid == UNICODE_NULL)
  1644. {
  1645. TRACE_CRIT(L"%!FUNC!: Null or empty adapter guid!");
  1646. Status = WBEM_E_INVALID_PARAMETER;
  1647. goto end;
  1648. }
  1649. }
  1650. // Get the operation to be performed
  1651. DWORD dwOperation;
  1652. fRet = pInParams->GetDWORD(L"Operation", dwOperation);
  1653. if (!fRet)
  1654. {
  1655. TRACE_CRIT("%!FUNC!: Missing operation!");
  1656. Status = WBEM_E_INVALID_PARAMETER;
  1657. goto end;
  1658. }
  1659. Opcode = (WLBS_OPERATION_CODES)dwOperation;
  1660. // If present, get the Virtual IP Address
  1661. fRet = pInParams->GetCHString( L"VirtualIpAddress", sVip);
  1662. if (fRet)
  1663. {
  1664. szVip = (LPCWSTR) sVip;
  1665. // Check for an empty string
  1666. if (szVip != NULL && *szVip == UNICODE_NULL)
  1667. {
  1668. szVip = NULL;
  1669. }
  1670. // Check for null
  1671. if (szVip != NULL)
  1672. {
  1673. // If the VIP is "All Vip", then, fill in the numeric value
  1674. // directly from the macro, else use the conversion function.
  1675. // This is 'cos INADDR_NONE, the return value of inet_addr
  1676. // function (called by IpAddressFromAbcdWsz) in the failure
  1677. // case, is equivalent to the numeric value of CVY_DEF_ALL_VIP
  1678. if (_wcsicmp(szVip, CVY_DEF_ALL_VIP) == 0)
  1679. {
  1680. dwVip = CVY_ALL_VIP_NUMERIC_VALUE;
  1681. }
  1682. else
  1683. {
  1684. dwVip = IpAddressFromAbcdWsz(szVip);
  1685. if (dwVip == INADDR_NONE)
  1686. {
  1687. TRACE_CRIT("%!FUNC! Invalid value (%ls) passed for Vip",szVip);
  1688. Status = WBEM_E_INVALID_PARAMETER;
  1689. goto end;
  1690. }
  1691. }
  1692. }
  1693. }
  1694. // If present, Get the port number
  1695. // The return value fRet is used in the switch statement further down, so
  1696. // do NOT re-assign/change it
  1697. fRet = pInParams->GetDWORD(L"Port", dwPort);
  1698. switch(Opcode)
  1699. {
  1700. case WLBS_START:
  1701. case WLBS_STOP:
  1702. case WLBS_DRAIN:
  1703. case WLBS_SUSPEND:
  1704. case WLBS_RESUME:
  1705. CfgUtilControlCluster( szAdapterGuid, Opcode, 0, 0, NULL, &dwRetVal );
  1706. CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwStatus );
  1707. // Fill the out parameter: Host Map
  1708. pOutParams->SetDWORD(L"HostMap", (DWORD) dwHostMap);
  1709. break;
  1710. case WLBS_PORT_ENABLE:
  1711. case WLBS_PORT_DISABLE:
  1712. case WLBS_PORT_DRAIN:
  1713. if ((szVip == NULL) || !fRet)
  1714. {
  1715. TRACE_CRIT("%!FUNC! Virtual IP Address or Port NOT passed for port operation : 0x%x", Opcode);
  1716. Status = WBEM_E_INVALID_PARAMETER;
  1717. goto end;
  1718. }
  1719. CfgUtilControlCluster( szAdapterGuid, Opcode, dwVip, dwPort, NULL, &dwRetVal );
  1720. CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY_PORT_STATE, dwVip, dwPort, NULL, &dwStatus );
  1721. break;
  1722. case WLBS_QUERY:
  1723. CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwStatus );
  1724. // Fill the out parameter: Host Map
  1725. pOutParams->SetDWORD(L"HostMap", (DWORD) dwHostMap);
  1726. dwRetVal = WLBS_OK;
  1727. break;
  1728. case WLBS_QUERY_PORT_STATE:
  1729. CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY_PORT_STATE, dwVip, dwPort, NULL, &dwStatus );
  1730. dwRetVal = WLBS_OK;
  1731. break;
  1732. default:
  1733. TRACE_CRIT("%!FUNC! Invalid value (0x%x) passed for Operation",Opcode);
  1734. Status = WBEM_E_INVALID_PARAMETER;
  1735. goto end;
  1736. }
  1737. //
  1738. // Fill out the out parameters: return value, cluster/port status
  1739. //
  1740. pOutParams->SetDWORD(L"ReturnValue", dwRetVal);
  1741. pOutParams->SetDWORD(L"CurrentState", dwStatus);
  1742. end:
  1743. TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
  1744. return Status;
  1745. }
  1746. WBEMSTATUS
  1747. ProvGetClusterMembers(
  1748. CInstance *pInParams,
  1749. CInstance *pOutParams
  1750. )
  1751. /*++
  1752. WMI provider wrapper around NlbConfigurationUpdate::ProvGetClusterMembers
  1753. --*/
  1754. {
  1755. WBEMSTATUS Status;
  1756. LPCWSTR szAdapterGuid;
  1757. CHString sAdapterGuid;
  1758. bool fRet;
  1759. NLB_CLUSTER_MEMBER_INFO *pMembers = NULL;
  1760. DWORD dwRetVal, dwStatus, dwNumHosts;
  1761. LPWSTR *ppwszHostId = NULL;
  1762. LPWSTR *ppwszDedicatedIpAddress= NULL;
  1763. LPWSTR *ppwszHostName = NULL;
  1764. SAFEARRAY *pSAHostId = NULL;
  1765. SAFEARRAY *pSADedicatedIpAddress = NULL;
  1766. SAFEARRAY *pSAHostName = NULL;
  1767. TRACE_VERB(L"->");
  1768. dwRetVal = dwStatus = WLBS_FAILURE;
  1769. Status = WBEM_NO_ERROR;
  1770. // Get the Adapter GUID
  1771. fRet = pInParams->GetCHString(L"AdapterGuid", sAdapterGuid);
  1772. if (!fRet)
  1773. {
  1774. TRACE_CRIT(L"Missing adapter guid!");
  1775. Status = WBEM_E_INVALID_PARAMETER;
  1776. goto end;
  1777. }
  1778. else
  1779. {
  1780. szAdapterGuid = (LPCWSTR) sAdapterGuid;
  1781. if (szAdapterGuid == NULL || *szAdapterGuid == UNICODE_NULL)
  1782. {
  1783. TRACE_CRIT(L"Null or empty adapter guid!");
  1784. Status = WBEM_E_INVALID_PARAMETER;
  1785. goto end;
  1786. }
  1787. }
  1788. dwStatus = CfgUtilGetClusterMembers(szAdapterGuid, &dwNumHosts, &pMembers);
  1789. pOutParams->SetDWORD(L"ReturnValue", dwStatus);
  1790. if (dwStatus != WBEM_S_NO_ERROR)
  1791. {
  1792. dwNumHosts = 0;
  1793. pMembers = NULL;
  1794. TRACE_CRIT(L"CfgUtilGetClusterMembers failed with 0x%x", dwStatus);
  1795. goto end;
  1796. }
  1797. ASSERT (pMembers != NULL);
  1798. #define MY_MAX_HOSTID_DIGITS 3
  1799. ppwszHostId = CfgUtilsAllocateStringArray(dwNumHosts, MY_MAX_HOSTID_DIGITS);
  1800. ppwszDedicatedIpAddress = CfgUtilsAllocateStringArray(dwNumHosts, WLBS_MAX_CL_IP_ADDR);
  1801. ppwszHostName = CfgUtilsAllocateStringArray(dwNumHosts, CVY_MAX_FQDN + 1);
  1802. if (ppwszHostId == NULL || ppwszDedicatedIpAddress == NULL || ppwszHostName == NULL)
  1803. {
  1804. TRACE_CRIT(L"Memory allocation failed for strings of host information");
  1805. Status = WBEM_E_OUT_OF_MEMORY;
  1806. goto end;
  1807. }
  1808. //
  1809. // Copy the cluster member information into the string arrays for the caller
  1810. //
  1811. for (int i=0; i < dwNumHosts; i++)
  1812. {
  1813. ASSERT (pMembers[i].HostId <= WLBS_MAX_HOSTS);
  1814. if (pMembers[i].HostId > WLBS_MAX_HOSTS)
  1815. {
  1816. TRACE_CRIT(L"Illegal host id %d obatined from query to cluster", pMembers[i].HostId);
  1817. Status = WBEM_E_FAILED;
  1818. goto end;
  1819. }
  1820. _itow(pMembers[i].HostId, ppwszHostId[i], 10);
  1821. wcsncpy(ppwszDedicatedIpAddress[i], pMembers[i].DedicatedIpAddress, WLBS_MAX_CL_IP_ADDR);
  1822. (ppwszDedicatedIpAddress[i])[WLBS_MAX_CL_IP_ADDR - 1] = L'\0';
  1823. wcsncpy(ppwszHostName[i], pMembers[i].HostName, CVY_MAX_FQDN + 1);
  1824. (ppwszHostName[i])[CVY_MAX_FQDN] = L'\0';
  1825. }
  1826. Status = CfgUtilSafeArrayFromStrings(
  1827. (LPCWSTR *) ppwszHostId,
  1828. dwNumHosts,
  1829. &pSAHostId
  1830. );
  1831. if (FAILED(Status))
  1832. {
  1833. TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszHostId failed with 0x%x", Status);
  1834. pSAHostId = NULL;
  1835. goto end;
  1836. }
  1837. Status = CfgUtilSafeArrayFromStrings(
  1838. (LPCWSTR *) ppwszDedicatedIpAddress,
  1839. dwNumHosts,
  1840. &pSADedicatedIpAddress
  1841. );
  1842. if (FAILED(Status))
  1843. {
  1844. TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszDedicatedIpAddress failed with 0x%x", Status);
  1845. pSADedicatedIpAddress = NULL;
  1846. goto end;
  1847. }
  1848. Status = CfgUtilSafeArrayFromStrings(
  1849. (LPCWSTR *) ppwszHostName,
  1850. dwNumHosts,
  1851. &pSAHostName
  1852. );
  1853. if (FAILED(Status))
  1854. {
  1855. TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszHostName failed with 0x%x", Status);
  1856. pSAHostName = NULL;
  1857. goto end;
  1858. }
  1859. if (pSAHostId != NULL)
  1860. {
  1861. pOutParams->SetStringArray(L"HostIds", *pSAHostId);
  1862. }
  1863. if (pSADedicatedIpAddress != NULL)
  1864. {
  1865. pOutParams->SetStringArray(L"DedicatedIpAddresses", *pSADedicatedIpAddress);
  1866. }
  1867. if (pSAHostName != NULL)
  1868. {
  1869. pOutParams->SetStringArray(L"HostNames", *pSAHostName);
  1870. }
  1871. //
  1872. // Everything is cool. Reset the status in case the last call gave it some funky, non-failure value.
  1873. //
  1874. Status = WBEM_NO_ERROR;
  1875. end:
  1876. if (pSAHostId != NULL)
  1877. {
  1878. SafeArrayDestroy(pSAHostId);
  1879. pSAHostId = NULL;
  1880. }
  1881. if (pSADedicatedIpAddress != NULL)
  1882. {
  1883. SafeArrayDestroy(pSADedicatedIpAddress);
  1884. pSADedicatedIpAddress = NULL;
  1885. }
  1886. if (pSAHostName != NULL)
  1887. {
  1888. SafeArrayDestroy(pSAHostName);
  1889. pSAHostName = NULL;
  1890. }
  1891. if (ppwszHostId != NULL)
  1892. {
  1893. delete [] ppwszHostId;
  1894. ppwszHostId = NULL;
  1895. }
  1896. if (ppwszDedicatedIpAddress != NULL)
  1897. {
  1898. delete [] ppwszDedicatedIpAddress;
  1899. ppwszDedicatedIpAddress = NULL;
  1900. }
  1901. if (ppwszHostName != NULL)
  1902. {
  1903. delete [] ppwszHostName;
  1904. ppwszHostName = NULL;
  1905. }
  1906. if (pMembers != NULL)
  1907. {
  1908. delete [] pMembers;
  1909. }
  1910. TRACE_VERB(L"<-returns 0x%08lx", (UINT) Status);
  1911. return Status;
  1912. }
  1913. WBEMSTATUS
  1914. ProvRegisterManagementApplication(
  1915. CInstance *pInParams,
  1916. CInstance *pOutParams
  1917. )
  1918. /*++
  1919. WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
  1920. TODO:
  1921. Read from NLB registry location to see if a differnt GUID is already
  1922. register -- if so fail, else set this information, else
  1923. return failure and set the out params to the existing application
  1924. name and company name.
  1925. --*/
  1926. {
  1927. return WBEM_E_PROVIDER_NOT_CAPABLE;
  1928. }
  1929. WBEMSTATUS
  1930. ProvUnregisterManagementApplication(
  1931. CInstance *pInParams,
  1932. CInstance *pOutParams
  1933. )
  1934. /*++
  1935. WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
  1936. TODO:
  1937. Read from NLB registry location to see if a the specified GUID is
  1938. is registered if so remove the stuff from the registry.
  1939. --*/
  1940. {
  1941. return WBEM_E_PROVIDER_NOT_CAPABLE;
  1942. }