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.

4414 lines
106 KiB

  1. //***************************************************************************
  2. //
  3. // CFGUTILS.CPP
  4. //
  5. // Module: WMI Framework Instance provider
  6. //
  7. // Purpose: Low-level utilities to configure NICs -- bind/unbind,
  8. // get/set IP address lists, and get/set NLB cluster params.
  9. //
  10. // Copyright (c)2001 Microsoft Corporation, All Rights Reserved
  11. //
  12. // History:
  13. //
  14. // 04/05/01 JosephJ Created
  15. //
  16. //***************************************************************************
  17. #include "private.h"
  18. #include <netcfgx.h>
  19. #include <devguid.h>
  20. #include <cfg.h>
  21. #include "..\..\..\inc\wlbsiocl.h"
  22. #include "..\..\..\api\control.h"
  23. #include "cfgutils.tmh"
  24. //
  25. // This magic has the side effect defining "smart pointers"
  26. // IWbemServicesPtr
  27. // IWbemLocatorPtr
  28. // IWbemClassObjectPtr
  29. // IEnumWbemClassObjectPtr
  30. // IWbemCallResultPtr
  31. // IWbemStatusCodeTextPtr
  32. //
  33. // These types automatically call the COM Release function when the
  34. // objects go out of scope.
  35. //
  36. _COM_SMARTPTR_TYPEDEF(IWbemServices, __uuidof(IWbemServices));
  37. _COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator));
  38. _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
  39. _COM_SMARTPTR_TYPEDEF(IWbemCallResult, __uuidof(IWbemCallResult));
  40. _COM_SMARTPTR_TYPEDEF(IWbemStatusCodeText, __uuidof(IWbemStatusCodeText));
  41. WBEMSTATUS
  42. CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj(
  43. IN IWbemClassObjectPtr spObj, // smart pointer
  44. OUT IWbemClassObjectPtr &spAdapterObj // smart pointer, by reference
  45. );
  46. WBEMSTATUS
  47. get_string_parameter(
  48. IN IWbemClassObjectPtr spObj,
  49. IN LPCWSTR szParameterName,
  50. OUT LPWSTR *ppStringValue
  51. );
  52. WBEMSTATUS
  53. get_nic_instance(
  54. IN IWbemServicesPtr spWbemServiceIF,
  55. IN LPCWSTR szNicGuid,
  56. OUT IWbemClassObjectPtr &sprefObj
  57. );
  58. WBEMSTATUS
  59. get_multi_string_parameter(
  60. IN IWbemClassObjectPtr spObj,
  61. IN LPCWSTR szParameterName,
  62. IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
  63. OUT UINT *pNumItems,
  64. OUT LPCWSTR *ppStringValue
  65. );
  66. WBEMSTATUS
  67. set_string_parameter(
  68. IN IWbemClassObjectPtr spObj,
  69. IN LPCWSTR szParameterName,
  70. IN LPCWSTR szValue
  71. );
  72. WBEMSTATUS
  73. set_multi_string_parameter(
  74. IN IWbemClassObjectPtr spObj,
  75. IN LPCWSTR szParameterName,
  76. IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
  77. IN UINT NumItems,
  78. IN LPCWSTR pStringValue
  79. );
  80. //
  81. // This locally-defined class implements interfaces to WMI, NetConfig,
  82. // and low-level NLB APIs.
  83. //
  84. class CfgUtils
  85. {
  86. public:
  87. //
  88. // Initialization function -- call before using any other functions
  89. //
  90. WBEMSTATUS
  91. Initialize(
  92. VOID
  93. );
  94. //
  95. // Deinitialization function -- call after using any other functions
  96. //
  97. VOID
  98. Deinitialize(
  99. VOID
  100. );
  101. //
  102. // Constructor and distructor.
  103. //
  104. CfgUtils(VOID)
  105. {
  106. //
  107. // WARNING: We do a blanked zero memory initialization of our entire
  108. // structure. Any other initialization should go into the
  109. // Initialize() function.
  110. //
  111. ZeroMemory(this, sizeof(*this));
  112. InitializeCriticalSection(&m_Crit);
  113. }
  114. ~CfgUtils()
  115. {
  116. DeleteCriticalSection(&m_Crit);
  117. }
  118. //
  119. // Check if we're initialized
  120. //
  121. BOOL
  122. IsInitalized(VOID)
  123. {
  124. return m_ComInitialized && m_WmiInitialized && m_NLBApisInitialized;
  125. }
  126. IWbemStatusCodeTextPtr m_spWbemStatusIF; // Smart pointer
  127. IWbemServicesPtr m_spWbemServiceIF; // Smart pointer
  128. CWlbsControl *m_pWlbsControl;
  129. WBEMSTATUS
  130. GetClusterFromGuid(
  131. IN LPCWSTR szGuid,
  132. OUT CWlbsCluster **pCluster
  133. );
  134. private:
  135. //
  136. // A single lock serialzes all access.
  137. // Use mfn_Lock and mfn_Unlock.
  138. //
  139. CRITICAL_SECTION m_Crit;
  140. BOOL m_ComInitialized;
  141. BOOL m_WmiInitialized;
  142. BOOL m_NLBApisInitialized;
  143. VOID
  144. mfn_Lock(
  145. VOID
  146. )
  147. {
  148. EnterCriticalSection(&m_Crit);
  149. }
  150. VOID
  151. mfn_Unlock(
  152. VOID
  153. )
  154. {
  155. LeaveCriticalSection(&m_Crit);
  156. }
  157. };
  158. //
  159. // This class manages NetCfg interfaces
  160. //
  161. class MyNetCfg
  162. {
  163. public:
  164. MyNetCfg(VOID)
  165. {
  166. m_pINetCfg = NULL;
  167. m_pLock = NULL;
  168. }
  169. ~MyNetCfg()
  170. {
  171. ASSERT(m_pINetCfg==NULL);
  172. ASSERT(m_pLock==NULL);
  173. }
  174. WBEMSTATUS
  175. Initialize(
  176. BOOL fWriteLock
  177. );
  178. VOID
  179. Deinitialize(
  180. VOID
  181. );
  182. WBEMSTATUS
  183. GetNlbCompatibleNics(
  184. OUT LPWSTR **ppszNics,
  185. OUT UINT *pNumNics,
  186. OUT UINT *pNumBoundToNlb // OPTIONAL
  187. );
  188. WBEMSTATUS
  189. GetNicIF(
  190. IN LPCWSTR szNicGuid,
  191. OUT INetCfgComponent **ppINic
  192. );
  193. WBEMSTATUS
  194. GetBindingIF(
  195. IN LPCWSTR szComponent,
  196. OUT INetCfgComponentBindings **ppIBinding
  197. );
  198. typedef enum
  199. {
  200. NOOP,
  201. BIND,
  202. UNBIND
  203. } UPDATE_OP;
  204. WBEMSTATUS
  205. UpdateBindingState(
  206. IN LPCWSTR szNic,
  207. IN LPCWSTR szComponent,
  208. IN UPDATE_OP Op,
  209. OUT BOOL *pfBound
  210. );
  211. private:
  212. INetCfg *m_pINetCfg;
  213. INetCfgLock *m_pLock;
  214. }; // Class MyNetCfg
  215. //
  216. // We keep a single global instance of this class around currently...
  217. //
  218. CfgUtils g_CfgUtils;
  219. WBEMSTATUS
  220. CfgUtilInitialize(VOID)
  221. {
  222. return g_CfgUtils.Initialize();
  223. }
  224. VOID
  225. CfgUtilDeitialize(VOID)
  226. {
  227. return g_CfgUtils.Deinitialize();
  228. }
  229. WBEMSTATUS
  230. CfgUtils::Initialize(
  231. VOID
  232. )
  233. {
  234. WBEMSTATUS Status = WBEM_E_INITIALIZATION_FAILURE;
  235. HRESULT hr;
  236. TRACE_INFO(L"-> CfgUtils::Initialize");
  237. mfn_Lock();
  238. //
  239. // Initialize COM
  240. //
  241. {
  242. HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
  243. if ( FAILED(hr) )
  244. {
  245. TRACE_CRIT(L"CfgUtils: Failed to initialize COM library (hr=0x%08lx)", hr);
  246. goto end;
  247. }
  248. m_ComInitialized = TRUE;
  249. }
  250. //
  251. // WMI Initialization
  252. //
  253. {
  254. IWbemLocatorPtr spWbemLocatorIF = NULL; // Smart pointer
  255. //
  256. // Get error text generator interface
  257. //
  258. SCODE sc = CoCreateInstance(
  259. CLSID_WbemStatusCodeText,
  260. 0,
  261. CLSCTX_INPROC_SERVER,
  262. IID_IWbemStatusCodeText,
  263. (LPVOID *) &m_spWbemStatusIF
  264. );
  265. if( sc != S_OK )
  266. {
  267. ASSERT(m_spWbemStatusIF == NULL); // smart pointer
  268. TRACE_CRIT(L"CfgUtils: CoCreateInstance IWbemStatusCodeText failure\n");
  269. goto end;
  270. }
  271. TRACE_INFO(L"CfgUtils: m_spIWbemStatusIF=0x%p\n", (PVOID) m_spWbemStatusIF);
  272. //
  273. // Get "locator" interface
  274. //
  275. hr = CoCreateInstance(
  276. CLSID_WbemLocator, 0,
  277. CLSCTX_INPROC_SERVER,
  278. IID_IWbemLocator,
  279. (LPVOID *) &spWbemLocatorIF
  280. );
  281. if (FAILED(hr))
  282. {
  283. ASSERT(spWbemLocatorIF == NULL); // smart pointer
  284. TRACE_CRIT(L"CoCreateInstance IWebmLocator failed 0x%08lx", (UINT)hr);
  285. goto end;
  286. }
  287. //
  288. // Get interface to provider for NetworkAdapter class objects
  289. // on the local machine
  290. //
  291. _bstr_t serverPath = L"root\\cimv2";
  292. hr = spWbemLocatorIF->ConnectServer(
  293. serverPath,
  294. NULL, // strUser,
  295. NULL, // strPassword,
  296. NULL,
  297. 0,
  298. NULL,
  299. NULL,
  300. &m_spWbemServiceIF
  301. );
  302. if (FAILED(hr))
  303. {
  304. ASSERT(m_spWbemServiceIF == NULL); // smart pointer
  305. TRACE_CRIT(L"ConnectServer to cimv2 failed 0x%08lx", (UINT)hr);
  306. goto end;
  307. }
  308. TRACE_INFO(L"CfgUtils: m_spIWbemServiceIF=0x%p\n", (PVOID) m_spWbemServiceIF);
  309. hr = CoSetProxyBlanket(
  310. m_spWbemServiceIF,
  311. RPC_C_AUTHN_WINNT,
  312. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
  313. COLE_DEFAULT_PRINCIPAL, // NULL,
  314. RPC_C_AUTHN_LEVEL_DEFAULT,
  315. RPC_C_IMP_LEVEL_IMPERSONATE,
  316. COLE_DEFAULT_AUTHINFO, // NULL,
  317. EOAC_DEFAULT // EOAC_NONE
  318. );
  319. if (FAILED(hr))
  320. {
  321. TRACE_INFO(L"Error 0x%08lx setting proxy blanket", (UINT) hr);
  322. goto end;
  323. }
  324. //
  325. // Release locator interface.
  326. //
  327. // <NO need to do this explicitly, because this is a smart pointer>
  328. //
  329. spWbemLocatorIF = NULL;
  330. m_WmiInitialized = TRUE;
  331. }
  332. //
  333. // Netconfig Initialization
  334. //
  335. {
  336. // Nothing to do here...
  337. }
  338. //
  339. // WLBS API Initialization
  340. //
  341. {
  342. CWlbsControl *pWlbsControl = NULL;
  343. pWlbsControl = new CWlbsControl;
  344. if (pWlbsControl == NULL)
  345. {
  346. TRACE_CRIT("Could not initialize wlbs control!");
  347. goto end;
  348. }
  349. DWORD dwRet = pWlbsControl->Initialize();
  350. if (dwRet == WLBS_INIT_ERROR)
  351. {
  352. TRACE_CRIT("Error initializing WLBS Control!");
  353. delete pWlbsControl;
  354. pWlbsControl = NULL;
  355. goto end;
  356. }
  357. else
  358. {
  359. TRACE_INFO("WlbsControl (0x%p) Initialize returns 0x%08lx",
  360. (PVOID) pWlbsControl, dwRet);
  361. }
  362. m_pWlbsControl = pWlbsControl;
  363. m_NLBApisInitialized = TRUE;
  364. }
  365. Status = WBEM_NO_ERROR;
  366. end:
  367. mfn_Unlock();
  368. if (FAILED(Status))
  369. {
  370. TRACE_CRIT("CfgUtil -- FAILING INITIALIZATION! Status=0x%08lx",
  371. (UINT) Status);
  372. CfgUtils::Deinitialize();
  373. }
  374. TRACE_INFO(L"<- CfgUtils::Initialize(Status=0x%08lx)", (UINT) Status);
  375. return Status;
  376. }
  377. VOID
  378. CfgUtils::Deinitialize(
  379. VOID
  380. )
  381. //
  382. // NOTE: can be called in the context of a failed initialization.
  383. //
  384. {
  385. TRACE_INFO(L"-> CfgUtils::Deinitialize");
  386. mfn_Lock();
  387. //
  388. // De-initialize WLBS API
  389. //
  390. if (m_NLBApisInitialized)
  391. {
  392. delete m_pWlbsControl;
  393. m_pWlbsControl = NULL;
  394. m_NLBApisInitialized = FALSE;
  395. }
  396. //
  397. // Deinitialize Netconfig
  398. //
  399. //
  400. // Deinitialize WMI
  401. //
  402. {
  403. //
  404. // Release interface to NetworkAdapter provider
  405. //
  406. if (m_spWbemStatusIF!= NULL)
  407. {
  408. // Smart pointer.
  409. m_spWbemStatusIF= NULL;
  410. }
  411. if (m_spWbemServiceIF!= NULL)
  412. {
  413. // Smart pointer.
  414. m_spWbemServiceIF= NULL;
  415. }
  416. m_WmiInitialized = FALSE;
  417. }
  418. //
  419. // Deinitialize COM.
  420. //
  421. if (m_ComInitialized)
  422. {
  423. TRACE_CRIT(L"CfgUtils: Deinitializing COM");
  424. CoUninitialize();
  425. m_ComInitialized = FALSE;
  426. }
  427. mfn_Unlock();
  428. TRACE_INFO(L"<- CfgUtils::Deinitialize");
  429. }
  430. WBEMSTATUS
  431. CfgUtils::GetClusterFromGuid(
  432. IN LPCWSTR szGuid,
  433. OUT CWlbsCluster **ppCluster
  434. )
  435. {
  436. GUID Guid;
  437. WBEMSTATUS Status = WBEM_NO_ERROR;
  438. CWlbsCluster *pCluster = NULL;
  439. GUID AdapterGuid;
  440. HRESULT hr;
  441. hr = CLSIDFromString((LPWSTR)szGuid, &Guid);
  442. if (FAILED(hr))
  443. {
  444. TRACE_CRIT(
  445. "CWlbsControl::Initialize failed at CLSIDFromString %ws",
  446. szGuid
  447. );
  448. Status = WBEM_E_INVALID_PARAMETER;
  449. goto end;
  450. }
  451. mfn_Lock(); // TODO: This is not really that effective because we still
  452. // refer to pCluster outside this function.
  453. g_CfgUtils.m_pWlbsControl->ReInitialize();
  454. pCluster = m_pWlbsControl->GetClusterFromAdapter(Guid);
  455. mfn_Unlock();
  456. if (pCluster == NULL)
  457. {
  458. TRACE_CRIT("ERROR: Couldn't find cluster with Nic GUID %ws", szGuid);
  459. Status = WBEM_E_NOT_FOUND;
  460. goto end;
  461. }
  462. Status = WBEM_NO_ERROR;
  463. end:
  464. *ppCluster = pCluster;
  465. return Status;
  466. }
  467. //
  468. // Gets the list of statically-bound IP addresses for the NIC.
  469. // Sets *pNumIpAddresses to 0 if DHCP
  470. //
  471. WBEMSTATUS
  472. CfgUtilGetIpAddressesAndFriendlyName(
  473. IN LPCWSTR szNic,
  474. OUT UINT *pNumIpAddresses,
  475. OUT NLB_IP_ADDRESS_INFO **ppIpInfo, // Free using c++ delete operator.
  476. OUT LPWSTR *pszFriendlyName // Optional, Free using c++ delete
  477. )
  478. {
  479. WBEMSTATUS Status = WBEM_NO_ERROR;
  480. IWbemClassObjectPtr spObj = NULL; // smart pointer
  481. HRESULT hr;
  482. LPCWSTR pAddrs = NULL;
  483. LPCWSTR pSubnets = NULL;
  484. UINT AddrCount = 0;
  485. NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
  486. TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
  487. *pNumIpAddresses = NULL;
  488. *ppIpInfo = NULL;
  489. if (pszFriendlyName!=NULL)
  490. {
  491. *pszFriendlyName = NULL;
  492. }
  493. //
  494. // If not initialized, fail...
  495. //
  496. if (!g_CfgUtils.IsInitalized())
  497. {
  498. TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic);
  499. Status = WBEM_E_INITIALIZATION_FAILURE;
  500. goto end;
  501. }
  502. //
  503. // Get WMI instance to specific NIC
  504. //
  505. Status = get_nic_instance(
  506. g_CfgUtils.m_spWbemServiceIF,
  507. szNic,
  508. spObj // pass by reference
  509. );
  510. if (FAILED(Status))
  511. {
  512. ASSERT(spObj == NULL);
  513. goto end;
  514. }
  515. //
  516. // Extract IP addresses and subnets.
  517. //
  518. {
  519. //
  520. // This gets the ip addresses in a 2D WCHAR array -- inner dimension
  521. // is WLBS_MAX_CLI_IP_ADDR.
  522. //
  523. Status = get_multi_string_parameter(
  524. spObj,
  525. L"IPAddress", // szParameterName,
  526. WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
  527. &AddrCount,
  528. &pAddrs
  529. );
  530. if (FAILED(Status))
  531. {
  532. pAddrs = NULL;
  533. goto end;
  534. }
  535. else
  536. {
  537. TRACE_INFO("GOT %lu IP ADDRESSES!", AddrCount);
  538. }
  539. UINT SubnetCount;
  540. Status = get_multi_string_parameter(
  541. spObj,
  542. L"IPSubnet", // szParameterName,
  543. WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
  544. &SubnetCount,
  545. &pSubnets
  546. );
  547. if (FAILED(Status))
  548. {
  549. pSubnets = NULL;
  550. goto end;
  551. }
  552. else if (SubnetCount != AddrCount)
  553. {
  554. TRACE_CRIT("FAILING SubnetCount!=AddressCount!");
  555. goto end;
  556. }
  557. }
  558. //
  559. // Convert IP addresses to our internal form.
  560. //
  561. if (AddrCount != 0)
  562. {
  563. pIpInfo = new NLB_IP_ADDRESS_INFO[AddrCount];
  564. if (pIpInfo == NULL)
  565. {
  566. TRACE_CRIT("get_multi_str_parm: Alloc failure!");
  567. Status = WBEM_E_OUT_OF_MEMORY;
  568. goto end;
  569. }
  570. ZeroMemory(pIpInfo, AddrCount*sizeof(*pIpInfo));
  571. for (UINT u=0;u<AddrCount; u++)
  572. {
  573. //
  574. // We extrace each IP address and it's corresponding subnet mask
  575. // from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
  576. // structure.
  577. //
  578. LPCWSTR pIp = pAddrs+u*WLBS_MAX_CL_IP_ADDR;
  579. LPCWSTR pSub = pSubnets+u*WLBS_MAX_CL_NET_MASK;
  580. TRACE_INFO("IPaddress: %ws; SubnetMask:%ws", pIp, pSub);
  581. UINT len = wcslen(pIp);
  582. UINT len1 = wcslen(pSub);
  583. if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK))
  584. {
  585. CopyMemory(pIpInfo[u].IpAddress, pIp, (len+1)*sizeof(WCHAR));
  586. CopyMemory(pIpInfo[u].SubnetMask, pSub, (len1+1)*sizeof(WCHAR));
  587. }
  588. else
  589. {
  590. //
  591. // This would be an implementation error in get_multi_string_...
  592. //
  593. ASSERT(FALSE);
  594. Status = WBEM_E_CRITICAL_ERROR;
  595. goto end;
  596. }
  597. }
  598. }
  599. //
  600. // If requested, get friendly name.
  601. // We don't fail if there's an error, just return the empty "" string.
  602. //
  603. if (pszFriendlyName != NULL)
  604. {
  605. IWbemClassObjectPtr spAdapterObj = NULL; // smart pointer
  606. LPWSTR szFriendlyName = NULL;
  607. WBEMSTATUS TmpStatus;
  608. do
  609. {
  610. TmpStatus = CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj(
  611. spObj,
  612. spAdapterObj // passed by ref
  613. );
  614. if (FAILED(TmpStatus))
  615. {
  616. break;
  617. }
  618. TmpStatus = CfgUtilGetWmiStringParam(
  619. spAdapterObj,
  620. L"NetConnectionID",
  621. &szFriendlyName
  622. );
  623. if (FAILED(TmpStatus))
  624. {
  625. TRACE_CRIT("%!FUNC! Get NetConnectionID failed error=0x%08lx\n",
  626. (UINT) TmpStatus);
  627. }
  628. } while (FALSE);
  629. if (szFriendlyName == NULL)
  630. {
  631. //
  632. // Try to put an empty string.
  633. //
  634. szFriendlyName = new WCHAR[1];
  635. if (szFriendlyName == NULL)
  636. {
  637. Status = WBEM_E_OUT_OF_MEMORY;
  638. TRACE_CRIT("%!FUNC! Alloc failure!");
  639. goto end;
  640. }
  641. *szFriendlyName = 0; // Empty string
  642. }
  643. *pszFriendlyName = szFriendlyName;
  644. szFriendlyName = NULL;
  645. }
  646. end:
  647. if (pAddrs != NULL)
  648. {
  649. delete pAddrs;
  650. }
  651. if (pSubnets != NULL)
  652. {
  653. delete pSubnets;
  654. }
  655. if (FAILED(Status))
  656. {
  657. if (pIpInfo != NULL)
  658. {
  659. delete pIpInfo;
  660. pIpInfo = NULL;
  661. }
  662. AddrCount = 0;
  663. }
  664. *pNumIpAddresses = AddrCount;
  665. *ppIpInfo = pIpInfo;
  666. spObj = NULL; // smart pointer
  667. TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
  668. return Status;
  669. }
  670. #if OBSOLETE
  671. //
  672. // Sets the list of statically-bound IP addresses for the NIC.
  673. // if NumIpAddresses is 0, the NIC is configured for DHCP.
  674. //
  675. WBEMSTATUS
  676. CfgUtilSetStaticIpAddressesOld(
  677. IN LPCWSTR szNic,
  678. IN UINT NumIpAddresses,
  679. IN NLB_IP_ADDRESS_INFO *pIpInfo
  680. )
  681. {
  682. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  683. IWbemClassObjectPtr spNicClassObj = NULL; // smart pointer
  684. IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
  685. HRESULT hr;
  686. WCHAR *rgIpAddresses = NULL;
  687. WCHAR *rgIpSubnets = NULL;
  688. LPWSTR pRelPath = NULL;
  689. TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
  690. //
  691. // If not initialized, fail...
  692. //
  693. if (!g_CfgUtils.IsInitalized())
  694. {
  695. TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic);
  696. Status = WBEM_E_INITIALIZATION_FAILURE;
  697. goto end;
  698. }
  699. if (NumIpAddresses != 0)
  700. {
  701. //
  702. // Convert IP addresses from our internal form into 2D arrays.
  703. //
  704. rgIpAddresses = new WCHAR[NumIpAddresses * WLBS_MAX_CL_IP_ADDR];
  705. rgIpSubnets = new WCHAR[NumIpAddresses * WLBS_MAX_CL_NET_MASK];
  706. if (rgIpAddresses == NULL || rgIpSubnets == NULL)
  707. {
  708. TRACE_CRIT("SetStaticIpAddresses: Alloc failure!");
  709. Status = WBEM_E_OUT_OF_MEMORY;
  710. goto end;
  711. }
  712. for (UINT u=0;u<NumIpAddresses; u++)
  713. {
  714. //
  715. // We extrace each IP address and it's corresponding subnet mask
  716. // from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
  717. // structure.
  718. //
  719. LPWSTR pIpDest = rgIpAddresses+u*WLBS_MAX_CL_IP_ADDR;
  720. LPWSTR pSubDest = rgIpSubnets+u*WLBS_MAX_CL_NET_MASK;
  721. LPCWSTR pIpSrc = pIpInfo[u].IpAddress;
  722. LPCWSTR pSubSrc = pIpInfo[u].SubnetMask;
  723. UINT len = wcslen(pIpSrc);
  724. UINT len1 = wcslen(pSubSrc);
  725. if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK))
  726. {
  727. CopyMemory(pIpDest, pIpSrc, (len+1)*sizeof(WCHAR));
  728. CopyMemory(pSubDest, pSubSrc, (len1+1)*sizeof(WCHAR));
  729. }
  730. else
  731. {
  732. //
  733. // This would be an implementation error in get_multi_string_...
  734. //
  735. ASSERT(FALSE);
  736. goto end;
  737. }
  738. }
  739. }
  740. //
  741. // Get WMI path to specific NIC
  742. //
  743. {
  744. IWbemClassObjectPtr spNicObj = NULL; // smart pointer
  745. pRelPath = NULL;
  746. Status = get_nic_instance(
  747. g_CfgUtils.m_spWbemServiceIF,
  748. szNic,
  749. spNicObj // pass by reference
  750. );
  751. if (FAILED(Status))
  752. {
  753. ASSERT(spObj == NULL);
  754. goto end;
  755. }
  756. //
  757. // Extract the relative path, needed for ExecMethod.
  758. //
  759. Status = get_string_parameter(
  760. spNicObj,
  761. L"__RELPATH", // szParameterName
  762. &pRelPath // Delete when done.
  763. );
  764. if (FAILED(Status))
  765. {
  766. TRACE_CRIT("Couldn't get rel path");
  767. pRelPath = NULL;
  768. goto end;
  769. }
  770. else
  771. {
  772. if (pRelPath==NULL)
  773. {
  774. ASSERT(FALSE); // we don't expect this!
  775. goto end;
  776. }
  777. TRACE_CRIT("GOT RELATIVE PATH for %ws: %ws", szNic, pRelPath);
  778. }
  779. }
  780. //
  781. // Get NIC CLASS object
  782. //
  783. {
  784. hr = g_CfgUtils.m_spWbemServiceIF->GetObject(
  785. _bstr_t(L"Win32_NetworkAdapterConfiguration"),
  786. 0,
  787. NULL,
  788. &spNicClassObj,
  789. NULL
  790. );
  791. if (FAILED(hr))
  792. {
  793. TRACE_CRIT("Couldn't get nic class object pointer");
  794. goto end;
  795. }
  796. }
  797. //
  798. // Set up input parameters to the call to Enable static.
  799. //
  800. {
  801. IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
  802. // check if any input parameters specified.
  803. hr = spNicClassObj->GetMethod(
  804. L"EnableStatic",
  805. 0,
  806. &spWbemInput,
  807. NULL
  808. );
  809. if( FAILED( hr) )
  810. {
  811. TRACE_CRIT("IWbemClassObject::GetMethod failure");
  812. goto end;
  813. }
  814. hr = spWbemInput->SpawnInstance( 0, &spWbemInputInstance );
  815. if( FAILED( hr) )
  816. {
  817. TRACE_CRIT("IWbemClassObject::SpawnInstance failure. Unable to spawn instance." );
  818. goto end;
  819. }
  820. //
  821. // This gets the ip addresses in a 2D WCHAR array -- inner dimension
  822. // is WLBS_MAX_CLI_IP_ADDR.
  823. //
  824. Status = set_multi_string_parameter(
  825. spWbemInputInstance,
  826. L"IPAddress", // szParameterName,
  827. WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
  828. NumIpAddresses,
  829. rgIpAddresses
  830. );
  831. if (FAILED(Status))
  832. {
  833. goto end;
  834. }
  835. else
  836. {
  837. TRACE_INFO("SET %lu IP ADDRESSES!", NumIpAddresses);
  838. }
  839. Status = set_multi_string_parameter(
  840. spWbemInputInstance,
  841. L"SubnetMask", // szParameterName,
  842. WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
  843. NumIpAddresses,
  844. rgIpSubnets
  845. );
  846. if (FAILED(Status))
  847. {
  848. goto end;
  849. }
  850. }
  851. //
  852. // execute method and get the output result
  853. // WARNING: we try this a few times because the wmi call apperears to
  854. // suffer from a recoverable error. TODO: Need to get to the bottom of
  855. // this.
  856. //
  857. for (UINT NumTries=10; NumTries--;)
  858. {
  859. IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
  860. _variant_t v_retVal;
  861. TRACE_CRIT("Going to call EnableStatic");
  862. hr = g_CfgUtils.m_spWbemServiceIF->ExecMethod(
  863. _bstr_t(pRelPath),
  864. L"EnableStatic",
  865. 0,
  866. NULL,
  867. spWbemInputInstance,
  868. &spWbemOutput,
  869. NULL
  870. );
  871. TRACE_CRIT("EnableStatic returns");
  872. if( FAILED( hr) )
  873. {
  874. TRACE_CRIT("IWbemServices::ExecMethod failure 0x%08lx", (UINT) hr);
  875. goto end;
  876. }
  877. hr = spWbemOutput->Get(
  878. L"ReturnValue",
  879. 0,
  880. &v_retVal,
  881. NULL,
  882. NULL
  883. );
  884. if( FAILED( hr) )
  885. {
  886. TRACE_CRIT("IWbemClassObject::Get failure");
  887. goto end;
  888. }
  889. LONG lRet = (LONG) v_retVal;
  890. v_retVal.Clear();
  891. if (lRet == 0)
  892. {
  893. TRACE_INFO("EnableStatic returns SUCCESS!");
  894. Status = WBEM_NO_ERROR;
  895. break;
  896. }
  897. else if (lRet == 0x51) // This appears to be a recoverable error
  898. {
  899. TRACE_INFO(
  900. "EnableStatic on NIC %ws returns recoverable FAILURE:0x%08lx!",
  901. szNic,
  902. lRet
  903. );
  904. Sleep(1000);
  905. Status = WBEM_E_CRITICAL_ERROR;
  906. }
  907. else
  908. {
  909. TRACE_INFO(
  910. "EnableStatic on NIC %ws returns FAILURE:0x%08lx!",
  911. szNic,
  912. lRet
  913. );
  914. Status = WBEM_E_CRITICAL_ERROR;
  915. }
  916. }
  917. end:
  918. if (rgIpAddresses != NULL)
  919. {
  920. delete rgIpAddresses;
  921. }
  922. if (rgIpSubnets != NULL)
  923. {
  924. delete rgIpSubnets;
  925. }
  926. if (pRelPath != NULL)
  927. {
  928. delete pRelPath;
  929. }
  930. spNicClassObj = NULL; // smart pointer
  931. spWbemInputInstance = NULL;
  932. TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
  933. return Status;
  934. }
  935. #endif // OBSOLETE
  936. //
  937. // Sets the list of statically-bound IP addresses for the NIC.
  938. // if NumIpAddresses is 0, the NIC is configured for DHCP.
  939. //
  940. WBEMSTATUS
  941. CfgUtilSetStaticIpAddresses(
  942. IN LPCWSTR szNic,
  943. IN UINT NumIpAddresses,
  944. IN NLB_IP_ADDRESS_INFO *pIpInfo
  945. )
  946. {
  947. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  948. IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
  949. WCHAR *rgIpAddresses = NULL;
  950. WCHAR *rgIpSubnets = NULL;
  951. LPWSTR pRelPath = NULL;
  952. TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
  953. //
  954. // If not initialized, fail...
  955. //
  956. if (!g_CfgUtils.IsInitalized())
  957. {
  958. TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic);
  959. Status = WBEM_E_INITIALIZATION_FAILURE;
  960. goto end;
  961. }
  962. if (NumIpAddresses != 0)
  963. {
  964. //
  965. // Convert IP addresses from our internal form into 2D arrays.
  966. //
  967. rgIpAddresses = new WCHAR[NumIpAddresses * WLBS_MAX_CL_IP_ADDR];
  968. rgIpSubnets = new WCHAR[NumIpAddresses * WLBS_MAX_CL_NET_MASK];
  969. if (rgIpAddresses == NULL || rgIpSubnets == NULL)
  970. {
  971. TRACE_CRIT("SetStaticIpAddresses: Alloc failure!");
  972. Status = WBEM_E_OUT_OF_MEMORY;
  973. goto end;
  974. }
  975. for (UINT u=0;u<NumIpAddresses; u++)
  976. {
  977. //
  978. // We extrace each IP address and it's corresponding subnet mask
  979. // from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
  980. // structure.
  981. //
  982. LPWSTR pIpDest = rgIpAddresses+u*WLBS_MAX_CL_IP_ADDR;
  983. LPWSTR pSubDest = rgIpSubnets+u*WLBS_MAX_CL_NET_MASK;
  984. LPCWSTR pIpSrc = pIpInfo[u].IpAddress;
  985. LPCWSTR pSubSrc = pIpInfo[u].SubnetMask;
  986. UINT len = wcslen(pIpSrc);
  987. UINT len1 = wcslen(pSubSrc);
  988. if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK))
  989. {
  990. CopyMemory(pIpDest, pIpSrc, (len+1)*sizeof(WCHAR));
  991. CopyMemory(pSubDest, pSubSrc, (len1+1)*sizeof(WCHAR));
  992. }
  993. else
  994. {
  995. //
  996. // This would be an implementation error in get_multi_string_...
  997. //
  998. ASSERT(FALSE);
  999. goto end;
  1000. }
  1001. }
  1002. }
  1003. //
  1004. // Get input instance and relpath...
  1005. //
  1006. Status = CfgUtilGetWmiInputInstanceAndRelPath(
  1007. g_CfgUtils.m_spWbemServiceIF,
  1008. L"Win32_NetworkAdapterConfiguration", // szClassName
  1009. L"SettingID", // szPropertyName
  1010. szNic, // szPropertyValue
  1011. L"EnableStatic", // szMethodName,
  1012. spWbemInputInstance, // smart pointer
  1013. &pRelPath // free using delete
  1014. );
  1015. if (FAILED(Status))
  1016. {
  1017. goto end;
  1018. }
  1019. //
  1020. // Set up input parameters to the call to Enable static.
  1021. //
  1022. {
  1023. //
  1024. // This gets the ip addresses in a 2D WCHAR array -- inner dimension
  1025. // is WLBS_MAX_CLI_IP_ADDR.
  1026. //
  1027. Status = set_multi_string_parameter(
  1028. spWbemInputInstance,
  1029. L"IPAddress", // szParameterName,
  1030. WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
  1031. NumIpAddresses,
  1032. rgIpAddresses
  1033. );
  1034. if (FAILED(Status))
  1035. {
  1036. goto end;
  1037. }
  1038. else
  1039. {
  1040. TRACE_INFO("SET %lu IP ADDRESSES!", NumIpAddresses);
  1041. }
  1042. Status = set_multi_string_parameter(
  1043. spWbemInputInstance,
  1044. L"SubnetMask", // szParameterName,
  1045. WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
  1046. NumIpAddresses,
  1047. rgIpSubnets
  1048. );
  1049. if (FAILED(Status))
  1050. {
  1051. goto end;
  1052. }
  1053. }
  1054. //
  1055. // execute method and get the output result
  1056. // WARNING: we try this a few times because the wmi call apperears to
  1057. // suffer from a recoverable error. TODO: Need to get to the bottom of
  1058. // this.
  1059. //
  1060. for (UINT NumTries=10; NumTries--;)
  1061. {
  1062. HRESULT hr;
  1063. IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
  1064. _variant_t v_retVal;
  1065. TRACE_CRIT("Going to call EnableStatic");
  1066. hr = g_CfgUtils.m_spWbemServiceIF->ExecMethod(
  1067. _bstr_t(pRelPath),
  1068. L"EnableStatic",
  1069. 0,
  1070. NULL,
  1071. spWbemInputInstance,
  1072. &spWbemOutput,
  1073. NULL
  1074. );
  1075. TRACE_CRIT("EnableStatic returns");
  1076. if( FAILED( hr) )
  1077. {
  1078. TRACE_CRIT("IWbemServices::ExecMethod failure 0x%08lx", (UINT) hr);
  1079. goto end;
  1080. }
  1081. hr = spWbemOutput->Get(
  1082. L"ReturnValue",
  1083. 0,
  1084. &v_retVal,
  1085. NULL,
  1086. NULL
  1087. );
  1088. if( FAILED( hr) )
  1089. {
  1090. TRACE_CRIT("IWbemClassObject::Get failure");
  1091. goto end;
  1092. }
  1093. LONG lRet = (LONG) v_retVal;
  1094. v_retVal.Clear();
  1095. if (lRet == 0)
  1096. {
  1097. TRACE_INFO("EnableStatic returns SUCCESS!");
  1098. Status = WBEM_NO_ERROR;
  1099. break;
  1100. }
  1101. else if (lRet == 0x51) // This appears to be a recoverable error
  1102. {
  1103. TRACE_INFO(
  1104. "EnableStatic on NIC %ws returns recoverable FAILURE:0x%08lx!",
  1105. szNic,
  1106. lRet
  1107. );
  1108. Sleep(1000);
  1109. Status = WBEM_E_CRITICAL_ERROR;
  1110. }
  1111. else
  1112. {
  1113. TRACE_INFO(
  1114. "EnableStatic on NIC %ws returns FAILURE:0x%08lx!",
  1115. szNic,
  1116. lRet
  1117. );
  1118. Status = WBEM_E_CRITICAL_ERROR;
  1119. }
  1120. }
  1121. end:
  1122. if (rgIpAddresses != NULL)
  1123. {
  1124. delete rgIpAddresses;
  1125. }
  1126. if (rgIpSubnets != NULL)
  1127. {
  1128. delete rgIpSubnets;
  1129. }
  1130. if (pRelPath != NULL)
  1131. {
  1132. delete pRelPath;
  1133. }
  1134. spWbemInputInstance = NULL;
  1135. TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
  1136. return Status;
  1137. }
  1138. //
  1139. // Determines whether NLB is bound to the specified NIC.
  1140. //
  1141. WBEMSTATUS
  1142. CfgUtilCheckIfNlbBound(
  1143. IN LPCWSTR szNic,
  1144. OUT BOOL *pfBound
  1145. )
  1146. {
  1147. WBEMSTATUS Status = WBEM_NO_ERROR;
  1148. BOOL fNetCfgInitialized = FALSE;
  1149. MyNetCfg NetCfg;
  1150. BOOL fBound = FALSE;
  1151. //
  1152. // Get and initialize interface to netcfg
  1153. //
  1154. Status = NetCfg.Initialize(FALSE); // FALSE == don't get write lock.
  1155. if (FAILED(Status))
  1156. {
  1157. goto end;
  1158. }
  1159. fNetCfgInitialized = TRUE;
  1160. //
  1161. //
  1162. //
  1163. Status = NetCfg.UpdateBindingState(
  1164. szNic,
  1165. L"ms_wlbs",
  1166. MyNetCfg::NOOP,
  1167. &fBound
  1168. );
  1169. end:
  1170. if (fNetCfgInitialized)
  1171. {
  1172. NetCfg.Deinitialize();
  1173. }
  1174. *pfBound = fBound;
  1175. return Status;
  1176. }
  1177. //
  1178. // Binds/unbinds NLB to the specified NIC.
  1179. //
  1180. WBEMSTATUS
  1181. CfgUtilChangeNlbBindState(
  1182. IN LPCWSTR szNic,
  1183. IN BOOL fBind
  1184. )
  1185. {
  1186. WBEMSTATUS Status = WBEM_NO_ERROR;
  1187. BOOL fNetCfgInitialized = FALSE;
  1188. MyNetCfg NetCfg;
  1189. BOOL fBound = FALSE;
  1190. //
  1191. // Get and initialize interface to netcfg
  1192. //
  1193. Status = NetCfg.Initialize(TRUE); // TRUE == get write lock.
  1194. if (FAILED(Status))
  1195. {
  1196. goto end;
  1197. }
  1198. fNetCfgInitialized = TRUE;
  1199. //
  1200. //
  1201. //
  1202. Status = NetCfg.UpdateBindingState(
  1203. szNic,
  1204. L"ms_wlbs",
  1205. fBind ? MyNetCfg::BIND : MyNetCfg::UNBIND,
  1206. &fBound
  1207. );
  1208. end:
  1209. if (fNetCfgInitialized)
  1210. {
  1211. NetCfg.Deinitialize();
  1212. }
  1213. return Status;
  1214. }
  1215. //
  1216. // Gets the current NLB configuration for the specified NIC
  1217. //
  1218. WBEMSTATUS
  1219. CfgUtilGetNlbConfig(
  1220. IN LPCWSTR szNic,
  1221. OUT WLBS_REG_PARAMS *pParams
  1222. )
  1223. {
  1224. GUID Guid;
  1225. WBEMSTATUS Status = WBEM_NO_ERROR;
  1226. CWlbsCluster *pCluster = NULL;
  1227. // g_CfgUtils.mfn_Lock(); // Because pCluster is not protected...
  1228. Status = g_CfgUtils.GetClusterFromGuid(
  1229. szNic,
  1230. &pCluster
  1231. );
  1232. if (FAILED(Status))
  1233. {
  1234. goto end;
  1235. }
  1236. //
  1237. // Read the configuration.
  1238. //
  1239. DWORD dwRet = pCluster->ReadConfig(pParams);
  1240. if (dwRet != WLBS_OK)
  1241. {
  1242. TRACE_CRIT("Could not read NLB configuration for %wsz", szNic);
  1243. Status = WBEM_E_CRITICAL_ERROR;
  1244. goto end;
  1245. }
  1246. Status = WBEM_NO_ERROR;
  1247. end:
  1248. // g_CfgUtils.mfn_Unlock();
  1249. return Status;
  1250. }
  1251. //
  1252. // Sets the current NLB configuration for the specified NIC. This
  1253. // includes notifying the driver if required.
  1254. //
  1255. WBEMSTATUS
  1256. CfgUtilSetNlbConfig(
  1257. IN LPCWSTR szNic,
  1258. IN WLBS_REG_PARAMS *pParams
  1259. )
  1260. {
  1261. GUID Guid;
  1262. WBEMSTATUS Status = WBEM_NO_ERROR;
  1263. CWlbsCluster *pCluster = NULL;
  1264. DWORD dwRet = 0;
  1265. // NOTE: we assume pCluster won't go away -- i.e. no one is trying
  1266. // to unbind in this process' context.
  1267. // someone else remove it say fron netconfig UI?
  1268. Status = g_CfgUtils.GetClusterFromGuid(
  1269. szNic,
  1270. &pCluster
  1271. );
  1272. if (FAILED(Status))
  1273. {
  1274. goto end;
  1275. }
  1276. //
  1277. // Write the configuration.
  1278. //
  1279. dwRet = pCluster->WriteConfig(pParams);
  1280. if (dwRet != WLBS_OK)
  1281. {
  1282. TRACE_CRIT("Could not write NLB configuration for %wsz. Err=0x%08lx",
  1283. szNic, dwRet);
  1284. Status = WBEM_E_CRITICAL_ERROR;
  1285. goto end;
  1286. }
  1287. //
  1288. // Commit the changes.
  1289. //
  1290. dwRet = pCluster->CommitChanges(g_CfgUtils.m_pWlbsControl);
  1291. if (dwRet != WLBS_OK)
  1292. {
  1293. TRACE_CRIT("Could not commit changes to NLB configuration for %wsz. Err=0x%08lx",
  1294. szNic, dwRet);
  1295. Status = WBEM_E_CRITICAL_ERROR;
  1296. goto end;
  1297. }
  1298. Status = WBEM_NO_ERROR;
  1299. end:
  1300. return Status;
  1301. }
  1302. WBEMSTATUS
  1303. CfgUtilsAnalyzeNlbUpdate(
  1304. IN WLBS_REG_PARAMS *pCurrentParams, OPTIONAL
  1305. IN WLBS_REG_PARAMS *pNewParams,
  1306. OUT BOOL *pfConnectivityChange
  1307. )
  1308. {
  1309. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1310. BOOL fConnectivityChange = FALSE;
  1311. //
  1312. // If not initialized, fail...
  1313. //
  1314. if (!g_CfgUtils.IsInitalized())
  1315. {
  1316. TRACE_CRIT(L"%!FUNC! FAILING because uninitialized");
  1317. Status = WBEM_E_INITIALIZATION_FAILURE;
  1318. goto end;
  1319. }
  1320. if (pCurrentParams != NULL)
  1321. {
  1322. //
  1323. // If the structures have identical content, we return S_FALSE.
  1324. // We do this check before we call ValidateParm below, because
  1325. // ValidateParam has the side effect of filling out / modifying
  1326. // certain fields.
  1327. //
  1328. if (memcmp(pCurrentParams, pNewParams, sizeof(*pCurrentParams))==0)
  1329. {
  1330. Status = WBEM_S_FALSE;
  1331. goto end;
  1332. }
  1333. }
  1334. //
  1335. // Validate pNewParams -- this may also modify pNewParams slightly, by
  1336. // re-formatting ip addresses into canonical format.
  1337. //
  1338. BOOL fRet = g_CfgUtils.m_pWlbsControl->ValidateParam(pNewParams);
  1339. if (!fRet)
  1340. {
  1341. TRACE_CRIT(L"%!FUNC!FAILING because New params are invalid");
  1342. Status = WBEM_E_INVALID_PARAMETER;
  1343. goto end;
  1344. }
  1345. Status = WBEM_NO_ERROR;
  1346. if (pCurrentParams == NULL)
  1347. {
  1348. //
  1349. // NLB was not previously bound.
  1350. //
  1351. fConnectivityChange = TRUE;
  1352. goto end;
  1353. }
  1354. //
  1355. // Change in multicast modes or mac address.
  1356. //
  1357. if ( (pCurrentParams->mcast_support != pNewParams->mcast_support)
  1358. || _wcsicmp(pCurrentParams->cl_mac_addr, pNewParams->cl_mac_addr)!=0)
  1359. {
  1360. fConnectivityChange = TRUE;
  1361. }
  1362. //
  1363. // Change in primary cluster ip or subnet mask
  1364. //
  1365. if ( _wcsicmp(pCurrentParams->cl_ip_addr,pNewParams->cl_ip_addr)!=0
  1366. || _wcsicmp(pCurrentParams->cl_net_mask,pNewParams->cl_net_mask)!=0)
  1367. {
  1368. fConnectivityChange = TRUE;
  1369. }
  1370. end:
  1371. *pfConnectivityChange = fConnectivityChange;
  1372. return Status;
  1373. }
  1374. WBEMSTATUS
  1375. CfgUtilsValidateNicGuid(
  1376. IN LPCWSTR szGuid
  1377. )
  1378. //
  1379. //
  1380. {
  1381. //
  1382. // Sample GUID: {EBE09517-07B4-4E88-AAF1-E06F5540608B}
  1383. //
  1384. WBEMSTATUS Status = WBEM_E_INVALID_PARAMETER;
  1385. UINT Length = wcslen(szGuid);
  1386. if (Length != NLB_GUID_LEN)
  1387. {
  1388. TRACE_CRIT("Length != %d", NLB_GUID_LEN);
  1389. goto end;
  1390. }
  1391. //
  1392. // Open tcpip's registry key and look for guid there -- if not found,
  1393. // we'll return WBEM_E_NOT_FOUND
  1394. //
  1395. {
  1396. WCHAR szKey[128]; // This is enough for the tcpip+guid key
  1397. wcscpy(szKey,
  1398. L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"
  1399. );
  1400. wcscat(szKey, szGuid);
  1401. HKEY hKey = NULL;
  1402. LONG lRet;
  1403. lRet = RegOpenKeyEx(
  1404. HKEY_LOCAL_MACHINE, // handle to an open key
  1405. szKey, // address of subkey name
  1406. 0, // reserved
  1407. KEY_QUERY_VALUE, // desired security access
  1408. &hKey // address of buffer for opened handle
  1409. );
  1410. if (lRet != ERROR_SUCCESS)
  1411. {
  1412. TRACE_CRIT("Guid %ws doesn't exist under tcpip", szGuid);
  1413. Status = WBEM_E_NOT_FOUND;
  1414. goto end;
  1415. }
  1416. RegCloseKey(hKey);
  1417. }
  1418. Status = WBEM_NO_ERROR;
  1419. end:
  1420. return Status;
  1421. }
  1422. WBEMSTATUS
  1423. get_string_parameter(
  1424. IN IWbemClassObjectPtr spObj,
  1425. IN LPCWSTR szParameterName,
  1426. OUT LPWSTR *ppStringValue
  1427. )
  1428. {
  1429. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  1430. WCHAR *pStringValue = NULL;
  1431. _variant_t v_value;
  1432. CIMTYPE v_type;
  1433. HRESULT hr;
  1434. hr = spObj->Get(
  1435. _bstr_t(szParameterName), // Name
  1436. 0, // Reserved, must be 0
  1437. &v_value, // Place to store value
  1438. &v_type, // Type of value
  1439. NULL // Flavor (unused)
  1440. );
  1441. if (FAILED(hr))
  1442. {
  1443. // Couldn't read the Setting ID field!
  1444. //
  1445. TRACE_CRIT(
  1446. "get_str_parm:Couldn't retrieve %ws from 0x%p",
  1447. szParameterName,
  1448. (PVOID) spObj
  1449. );
  1450. goto end;
  1451. }
  1452. else
  1453. {
  1454. if (v_type != VT_BSTR)
  1455. {
  1456. TRACE_CRIT(
  1457. "get_str_parm: Parm value not of string type %ws from 0x%p",
  1458. szParameterName,
  1459. (PVOID) spObj
  1460. );
  1461. Status = WBEM_E_INVALID_PARAMETER;
  1462. }
  1463. else
  1464. {
  1465. _bstr_t bstrNicGuid(v_value);
  1466. LPCWSTR sz = bstrNicGuid; // Pointer to internal buffer.
  1467. if (sz==NULL)
  1468. {
  1469. // hmm.. null value
  1470. Status = WBEM_NO_ERROR;
  1471. }
  1472. else
  1473. {
  1474. UINT len = wcslen(sz);
  1475. pStringValue = new WCHAR[len+1];
  1476. if (pStringValue == NULL)
  1477. {
  1478. TRACE_CRIT("get_str_parm: Alloc failure!");
  1479. Status = WBEM_E_OUT_OF_MEMORY;
  1480. }
  1481. else
  1482. {
  1483. CopyMemory(pStringValue, sz, (len+1)*sizeof(WCHAR));
  1484. Status = WBEM_NO_ERROR;
  1485. }
  1486. }
  1487. TRACE_VERB(
  1488. "get_str_parm: String parm %ws of 0x%p is %ws",
  1489. szParameterName,
  1490. (PVOID) spObj,
  1491. (sz==NULL) ? L"<null>" : sz
  1492. );
  1493. }
  1494. v_value.Clear(); // Must be cleared after each call to Get.
  1495. }
  1496. end:
  1497. *ppStringValue = pStringValue;
  1498. return Status;
  1499. }
  1500. WBEMSTATUS
  1501. get_nic_instance(
  1502. IN IWbemServicesPtr spWbemServiceIF,
  1503. IN LPCWSTR szNicGuid,
  1504. OUT IWbemClassObjectPtr &sprefObj
  1505. )
  1506. {
  1507. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  1508. IWbemClassObjectPtr spObj = NULL; // smart pointer.
  1509. Status = CfgUtilGetWmiObjectInstance(
  1510. spWbemServiceIF,
  1511. L"Win32_NetworkAdapterConfiguration", // szClassName
  1512. L"SettingID", // szParameterName
  1513. szNicGuid, // ParameterValue
  1514. spObj // smart pointer, passed by ref
  1515. );
  1516. if (FAILED(Status))
  1517. {
  1518. ASSERT(spObj == NULL);
  1519. goto end;
  1520. }
  1521. end:
  1522. if (FAILED(Status))
  1523. {
  1524. sprefObj = NULL;
  1525. }
  1526. else
  1527. {
  1528. sprefObj = spObj; // smart pointer.
  1529. }
  1530. return Status;
  1531. }
  1532. WBEMSTATUS
  1533. get_multi_string_parameter(
  1534. IN IWbemClassObjectPtr spObj,
  1535. IN LPCWSTR szParameterName,
  1536. IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
  1537. OUT UINT *pNumItems,
  1538. OUT LPCWSTR *ppStringValue
  1539. )
  1540. {
  1541. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  1542. WCHAR *pStringValue = NULL;
  1543. _variant_t v_value;
  1544. CIMTYPE v_type;
  1545. HRESULT hr;
  1546. LONG count = 0;
  1547. *ppStringValue = NULL;
  1548. *pNumItems = 0;
  1549. hr = spObj->Get(
  1550. _bstr_t(szParameterName),
  1551. 0, // Reserved, must be 0
  1552. &v_value, // Place to store value
  1553. &v_type, // Type of value
  1554. NULL // Flavor (unused)
  1555. );
  1556. if (FAILED(hr))
  1557. {
  1558. // Couldn't read the requested parameter.
  1559. //
  1560. TRACE_CRIT(
  1561. "get_multi_str_parm:Couldn't retrieve %ws from 0x%p",
  1562. szParameterName,
  1563. (PVOID) spObj
  1564. );
  1565. goto end;
  1566. }
  1567. {
  1568. VARIANT ipsV = v_value.Detach();
  1569. do // while false
  1570. {
  1571. BSTR* pbstr;
  1572. if (ipsV.vt == VT_NULL)
  1573. {
  1574. //
  1575. // NULL string -- this is ok
  1576. //
  1577. count = 0;
  1578. }
  1579. else
  1580. {
  1581. count = ipsV.parray->rgsabound[0].cElements;
  1582. }
  1583. if (count==0)
  1584. {
  1585. Status = WBEM_NO_ERROR;
  1586. break;
  1587. }
  1588. pStringValue = new WCHAR[count*MaxStringLen];
  1589. if (pStringValue == NULL)
  1590. {
  1591. TRACE_CRIT("get_multi_str_parm: Alloc failure!");
  1592. Status = WBEM_E_OUT_OF_MEMORY;
  1593. break;
  1594. }
  1595. ZeroMemory(pStringValue, sizeof(WCHAR)*count*MaxStringLen);
  1596. hr = SafeArrayAccessData(ipsV.parray, ( void **) &pbstr);
  1597. if(FAILED(hr))
  1598. {
  1599. Status = WBEM_E_INVALID_PARAMETER; // TODO: pick better error
  1600. break;
  1601. }
  1602. Status = WBEM_NO_ERROR;
  1603. for( LONG x = 0; x < count; x++ )
  1604. {
  1605. LPCWSTR sz = pbstr[x]; // Pointer to internal buffer.
  1606. if (sz==NULL)
  1607. {
  1608. // hmm.. null value
  1609. continue;
  1610. }
  1611. else
  1612. {
  1613. UINT len = wcslen(sz);
  1614. if ((len+1) > MaxStringLen)
  1615. {
  1616. TRACE_CRIT("get_str_parm: string size too long!");
  1617. Status = WBEM_E_INVALID_PARAMETER;
  1618. break;
  1619. }
  1620. else
  1621. {
  1622. WCHAR *pDest = pStringValue+x*MaxStringLen;
  1623. CopyMemory(pDest, sz, (len+1)*sizeof(WCHAR));
  1624. }
  1625. }
  1626. }
  1627. (VOID) SafeArrayUnaccessData( ipsV.parray );
  1628. } while (FALSE);
  1629. VariantClear( &ipsV );
  1630. }
  1631. if (FAILED(Status))
  1632. {
  1633. if (pStringValue!=NULL)
  1634. {
  1635. delete pStringValue;
  1636. *pStringValue = NULL;
  1637. }
  1638. }
  1639. else
  1640. {
  1641. *ppStringValue = pStringValue;
  1642. *pNumItems = count;
  1643. }
  1644. end:
  1645. return Status;
  1646. }
  1647. WBEMSTATUS
  1648. MyNetCfg::Initialize(
  1649. BOOL fWriteLock
  1650. )
  1651. {
  1652. HRESULT hr;
  1653. INetCfg *pnc = NULL;
  1654. INetCfgLock *pncl = NULL;
  1655. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1656. BOOL fLocked = FALSE;
  1657. BOOL fInitialized=FALSE;
  1658. if (m_pINetCfg != NULL || m_pLock != NULL)
  1659. {
  1660. ASSERT(FALSE);
  1661. goto end;
  1662. }
  1663. hr = CoCreateInstance( CLSID_CNetCfg,
  1664. NULL,
  1665. CLSCTX_SERVER,
  1666. IID_INetCfg,
  1667. (void **) &pnc);
  1668. if( !SUCCEEDED( hr ) )
  1669. {
  1670. // failure to create instance.
  1671. TRACE_CRIT("ERROR: could not get interface to Net Config");
  1672. goto end;
  1673. }
  1674. //
  1675. // If require, get the write lock
  1676. //
  1677. if (fWriteLock)
  1678. {
  1679. WCHAR *szLockedBy = NULL;
  1680. hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl );
  1681. if( !SUCCEEDED( hr ) )
  1682. {
  1683. TRACE_CRIT("ERROR: could not get interface to NetCfg Lock");
  1684. goto end;
  1685. }
  1686. hr = pncl->AcquireWriteLock( 1, // One Second
  1687. L"NLBManager",
  1688. &szLockedBy);
  1689. if( hr != S_OK )
  1690. {
  1691. TRACE_CRIT("Could not get write lock. Lock held by %ws",
  1692. (szLockedBy!=NULL) ? szLockedBy : L"<null>");
  1693. goto end;
  1694. }
  1695. }
  1696. // Initializes network configuration by loading into
  1697. // memory all basic networking information
  1698. //
  1699. hr = pnc->Initialize( NULL );
  1700. if( !SUCCEEDED( hr ) )
  1701. {
  1702. // failure to Initialize
  1703. TRACE_CRIT("INetCfg::Initialize failure ");
  1704. goto end;
  1705. }
  1706. Status = WBEM_NO_ERROR;
  1707. end:
  1708. if (FAILED(Status))
  1709. {
  1710. if (pncl!=NULL)
  1711. {
  1712. if (fLocked)
  1713. {
  1714. pncl->ReleaseWriteLock();
  1715. }
  1716. pncl->Release();
  1717. pncl=NULL;
  1718. }
  1719. if( pnc != NULL)
  1720. {
  1721. if (fInitialized)
  1722. {
  1723. pnc->Uninitialize();
  1724. }
  1725. pnc->Release();
  1726. pnc= NULL;
  1727. }
  1728. }
  1729. else
  1730. {
  1731. m_pINetCfg = pnc;
  1732. m_pLock = pncl;
  1733. }
  1734. return Status;
  1735. }
  1736. VOID
  1737. MyNetCfg::Deinitialize(
  1738. VOID
  1739. )
  1740. {
  1741. if (m_pLock!=NULL)
  1742. {
  1743. m_pLock->ReleaseWriteLock();
  1744. m_pLock->Release();
  1745. m_pLock=NULL;
  1746. }
  1747. if( m_pINetCfg != NULL)
  1748. {
  1749. m_pINetCfg->Uninitialize();
  1750. m_pINetCfg->Release();
  1751. m_pINetCfg= NULL;
  1752. }
  1753. }
  1754. WBEMSTATUS
  1755. MyNetCfg::GetNicIF(
  1756. IN LPCWSTR szNicGuid,
  1757. OUT INetCfgComponent **ppINic
  1758. )
  1759. {
  1760. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1761. INetCfgComponent *pncc = NULL;
  1762. HRESULT hr;
  1763. IEnumNetCfgComponent* pencc = NULL;
  1764. ULONG countToFetch = 1;
  1765. ULONG countFetched;
  1766. DWORD characteristics;
  1767. if (m_pINetCfg == NULL)
  1768. {
  1769. //
  1770. // This means we're not initialized
  1771. //
  1772. ASSERT(FALSE);
  1773. goto end;
  1774. }
  1775. hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc );
  1776. if( !SUCCEEDED( hr ) )
  1777. {
  1778. // failure to Enumerate net components
  1779. TRACE_CRIT("Could not enum netcfg adapters");
  1780. pencc = NULL;
  1781. goto end;
  1782. }
  1783. while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK )
  1784. {
  1785. LPWSTR szName = NULL;
  1786. hr = pncc->GetBindName( &szName );
  1787. if (!SUCCEEDED(hr))
  1788. {
  1789. TRACE_CRIT("WARNING: couldn't get bind name for 0x%p, ignoring",
  1790. (PVOID) pncc);
  1791. continue;
  1792. }
  1793. if(!_wcsicmp(szName, szNicGuid))
  1794. {
  1795. //
  1796. // Got this one!
  1797. //
  1798. CoTaskMemFree( szName );
  1799. break;
  1800. }
  1801. CoTaskMemFree( szName );
  1802. pncc->Release();
  1803. pncc=NULL;
  1804. }
  1805. if (pncc == NULL)
  1806. {
  1807. TRACE_CRIT("Could not find NIC %ws", szNicGuid);
  1808. Status = WBEM_E_NOT_FOUND;
  1809. }
  1810. else
  1811. {
  1812. Status = WBEM_NO_ERROR;
  1813. }
  1814. end:
  1815. if (pencc != NULL)
  1816. {
  1817. pencc->Release();
  1818. }
  1819. *ppINic = pncc;
  1820. return Status;
  1821. }
  1822. LPWSTR *
  1823. CfgUtilsAllocateStringArray(
  1824. UINT NumStrings,
  1825. UINT MaxStringLen // excluding ending NULL
  1826. )
  1827. /*
  1828. Allocate a single chunk of memory using the new LPWSTR[] operator.
  1829. The first NumStrings LPWSTR values of this operator contain an array
  1830. of pointers to WCHAR strings. Each of these strings
  1831. is of size (MaxStringLen+1) WCHARS.
  1832. The rest of the memory contains the strings themselve.
  1833. Return NULL if NumStrings==0 or on allocation failure.
  1834. Each of the strings are initialized to be empty strings (first char is 0).
  1835. */
  1836. {
  1837. LPWSTR *pStrings = NULL;
  1838. UINT TotalSize = 0;
  1839. if (NumStrings == 0)
  1840. {
  1841. goto end;
  1842. }
  1843. //
  1844. // Note - even if MaxStringLen is 0 we will allocate space for NumStrings
  1845. // pointers and NumStrings empty (first char is 0) strings.
  1846. //
  1847. //
  1848. // Calculate space for the array of pointers to strings...
  1849. //
  1850. TotalSize = NumStrings*sizeof(LPWSTR);
  1851. //
  1852. // Calculate space for the strings themselves...
  1853. // Remember to add +1 for each ending 0 character.
  1854. //
  1855. TotalSize += NumStrings*(MaxStringLen+1)*sizeof(WCHAR);
  1856. //
  1857. // Allocate space for *both* the array of pointers and the strings
  1858. // in one shot -- we're doing a new of type LPWSTR[] for the whole
  1859. // lot, so need to specify the size in units of LPWSTR (with an
  1860. // additional +1 in case there's roundoff.
  1861. //
  1862. pStrings = new LPWSTR[(TotalSize/sizeof(LPWSTR))+1];
  1863. if (pStrings == NULL)
  1864. {
  1865. goto end;
  1866. }
  1867. //
  1868. // Make sz point to the start of the place where we'll be placing
  1869. // the string data.
  1870. //
  1871. LPWSTR sz = (LPWSTR) (pStrings+NumStrings);
  1872. for (UINT u=0; u<NumStrings; u++)
  1873. {
  1874. *sz=NULL;
  1875. pStrings[u] = sz;
  1876. sz+=(MaxStringLen+1); // +1 for ending NULL
  1877. }
  1878. end:
  1879. return pStrings;
  1880. }
  1881. WBEMSTATUS
  1882. MyNetCfg::GetNlbCompatibleNics(
  1883. OUT LPWSTR **ppszNics,
  1884. OUT UINT *pNumNics,
  1885. OUT UINT *pNumBoundToNlb // OPTIONAL
  1886. )
  1887. /*
  1888. Returns an array of pointers to string-version of GUIDS
  1889. that represent the set of alive and healthy NICS that are
  1890. suitable for NLB to bind to -- basically alive ethernet NICs.
  1891. Delete ppNics using the delete WCHAR[] operator. Do not
  1892. delete the individual strings.
  1893. */
  1894. {
  1895. #define MY_GUID_LENGTH 38
  1896. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  1897. HRESULT hr;
  1898. IEnumNetCfgComponent* pencc = NULL;
  1899. INetCfgComponent *pncc = NULL;
  1900. ULONG countToFetch = 1;
  1901. ULONG countFetched;
  1902. DWORD characteristics;
  1903. UINT NumNics = 0;
  1904. LPWSTR *pszNics = NULL;
  1905. INetCfgComponentBindings *pINlbBinding=NULL;
  1906. UINT NumNlbBoundNics = 0;
  1907. typedef struct _MYNICNODE MYNICNODE;
  1908. typedef struct _MYNICNODE
  1909. {
  1910. LPWSTR szNicGuid;
  1911. MYNICNODE *pNext;
  1912. } MYNICNODE;
  1913. MYNICNODE *pNicNodeList = NULL;
  1914. MYNICNODE *pNicNode = NULL;
  1915. *ppszNics = NULL;
  1916. *pNumNics = 0;
  1917. if (pNumBoundToNlb != NULL)
  1918. {
  1919. *pNumBoundToNlb = 0;
  1920. }
  1921. if (m_pINetCfg == NULL)
  1922. {
  1923. //
  1924. // This means we're not initialized
  1925. //
  1926. ASSERT(FALSE);
  1927. goto end;
  1928. }
  1929. hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc );
  1930. if( !SUCCEEDED( hr ) )
  1931. {
  1932. // failure to Enumerate net components
  1933. TRACE_CRIT("%!FUNC! Could not enum netcfg adapters");
  1934. pencc = NULL;
  1935. goto end;
  1936. }
  1937. //
  1938. // Check if nlb is bound to the nlb component.
  1939. //
  1940. //
  1941. // If we need to count of NLB-bound nics, get instance of the nlb component
  1942. //
  1943. if (pNumBoundToNlb != NULL)
  1944. {
  1945. Status = GetBindingIF(L"ms_wlbs", &pINlbBinding);
  1946. if (FAILED(Status))
  1947. {
  1948. TRACE_CRIT("%!FUNC! WARNING: NLB doesn't appear to be installed on this machine");
  1949. pINlbBinding = NULL;
  1950. }
  1951. }
  1952. while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK )
  1953. {
  1954. LPWSTR szName = NULL;
  1955. hr = pncc->GetBindName( &szName );
  1956. if (!SUCCEEDED(hr))
  1957. {
  1958. TRACE_CRIT("%!FUNC! WARNING: couldn't get bind name for 0x%p, ignoring",
  1959. (PVOID) pncc);
  1960. continue;
  1961. }
  1962. do // while FALSE -- just to allow breaking out
  1963. {
  1964. UINT Len = wcslen(szName);
  1965. if (Len != MY_GUID_LENGTH)
  1966. {
  1967. TRACE_CRIT("%!FUNC! WARNING: GUID %ws has unexpected length %ul",
  1968. szName, Len);
  1969. break;
  1970. }
  1971. DWORD characteristics = 0;
  1972. hr = pncc->GetCharacteristics( &characteristics );
  1973. if(!SUCCEEDED(hr))
  1974. {
  1975. TRACE_CRIT("%!FUNC! WARNING: couldn't get characteristics for %ws, ignoring",
  1976. szName);
  1977. break;
  1978. }
  1979. if(characteristics & NCF_PHYSICAL)
  1980. {
  1981. ULONG devstat = 0;
  1982. // This is a physical network card.
  1983. // we are only interested in such devices
  1984. // check if the nic is enabled, we are only
  1985. // interested in enabled nics.
  1986. //
  1987. hr = pncc->GetDeviceStatus( &devstat );
  1988. if(!SUCCEEDED(hr))
  1989. {
  1990. TRACE_CRIT(
  1991. "%!FUNC! WARNING: couldn't get dev status for %ws, ignoring",
  1992. szName
  1993. );
  1994. break;
  1995. }
  1996. // if any of the nics has any of the problem codes
  1997. // then it cannot be used.
  1998. if( devstat != CM_PROB_NOT_CONFIGURED
  1999. &&
  2000. devstat != CM_PROB_FAILED_START
  2001. &&
  2002. devstat != CM_PROB_NORMAL_CONFLICT
  2003. &&
  2004. devstat != CM_PROB_NEED_RESTART
  2005. &&
  2006. devstat != CM_PROB_REINSTALL
  2007. &&
  2008. devstat != CM_PROB_WILL_BE_REMOVED
  2009. &&
  2010. devstat != CM_PROB_DISABLED
  2011. &&
  2012. devstat != CM_PROB_FAILED_INSTALL
  2013. &&
  2014. devstat != CM_PROB_FAILED_ADD
  2015. )
  2016. {
  2017. //
  2018. // No problem with this nic and also
  2019. // physical device
  2020. // thus we want it.
  2021. //
  2022. if (pINlbBinding != NULL)
  2023. {
  2024. BOOL fBound = FALSE;
  2025. hr = pINlbBinding->IsBoundTo(pncc);
  2026. if( !SUCCEEDED( hr ) )
  2027. {
  2028. TRACE_CRIT("IsBoundTo method failed for Nic %ws", szName);
  2029. goto end;
  2030. }
  2031. if( hr == S_OK )
  2032. {
  2033. TRACE_VERB("BOUND: %ws\n", szName);
  2034. NumNlbBoundNics++;
  2035. fBound = TRUE;
  2036. }
  2037. else if (hr == S_FALSE )
  2038. {
  2039. TRACE_VERB("NOT BOUND: %ws\n", szName);
  2040. fBound = FALSE;
  2041. }
  2042. }
  2043. // We allocate a little node to keep this string
  2044. // temporarily and add it to our list of nodes.
  2045. //
  2046. pNicNode = new MYNICNODE;
  2047. if (pNicNode == NULL)
  2048. {
  2049. Status = WBEM_E_OUT_OF_MEMORY;
  2050. goto end;
  2051. }
  2052. ZeroMemory(pNicNode, sizeof(*pNicNode));
  2053. pNicNode->szNicGuid = szName;
  2054. szName = NULL; // so we don't delete inside the lopp.
  2055. pNicNode->pNext = pNicNodeList;
  2056. pNicNodeList = pNicNode;
  2057. NumNics++;
  2058. }
  2059. else
  2060. {
  2061. // There is a problem...
  2062. TRACE_CRIT(
  2063. "%!FUNC! WARNING: Skipping %ws because DeviceStatus=0x%08lx",
  2064. szName, devstat
  2065. );
  2066. break;
  2067. }
  2068. }
  2069. else
  2070. {
  2071. TRACE_VERB("%!FUNC! Ignoring non-physical device %ws", szName);
  2072. }
  2073. } while (FALSE);
  2074. if (szName != NULL)
  2075. {
  2076. CoTaskMemFree( szName );
  2077. }
  2078. pncc->Release();
  2079. pncc=NULL;
  2080. }
  2081. if (pINlbBinding!=NULL)
  2082. {
  2083. pINlbBinding->Release();
  2084. pINlbBinding = NULL;
  2085. }
  2086. if (NumNics==0)
  2087. {
  2088. Status = WBEM_NO_ERROR;
  2089. goto end;
  2090. }
  2091. //
  2092. // Now let's allocate space for all the nic strings and:w
  2093. // copy them over..
  2094. //
  2095. #define MY_GUID_LENGTH 38
  2096. pszNics = CfgUtilsAllocateStringArray(NumNics, MY_GUID_LENGTH);
  2097. if (pszNics == NULL)
  2098. {
  2099. Status = WBEM_E_OUT_OF_MEMORY;
  2100. goto end;
  2101. }
  2102. pNicNode= pNicNodeList;
  2103. for (UINT u=0; u<NumNics; u++, pNicNode=pNicNode->pNext)
  2104. {
  2105. ASSERT(pNicNode != NULL); // because we just counted NumNics of em.
  2106. UINT Len = wcslen(pNicNode->szNicGuid);
  2107. if (Len != MY_GUID_LENGTH)
  2108. {
  2109. //
  2110. // We should never get here beause we checked the length earlier.
  2111. //
  2112. TRACE_CRIT("%!FUNC! ERROR: GUID %ws has unexpected length %ul",
  2113. pNicNode->szNicGuid, Len);
  2114. ASSERT(FALSE);
  2115. Status = WBEM_E_CRITICAL_ERROR;
  2116. goto end;
  2117. }
  2118. CopyMemory(
  2119. pszNics[u],
  2120. pNicNode->szNicGuid,
  2121. (MY_GUID_LENGTH+1)*sizeof(WCHAR));
  2122. ASSERT(pszNics[u][MY_GUID_LENGTH]==0);
  2123. }
  2124. Status = WBEM_NO_ERROR;
  2125. end:
  2126. //
  2127. // Now release the temporarly allocated memory.
  2128. //
  2129. pNicNode= pNicNodeList;
  2130. while (pNicNode!=NULL)
  2131. {
  2132. MYNICNODE *pTmp = pNicNode->pNext;
  2133. CoTaskMemFree(pNicNode->szNicGuid);
  2134. pNicNode->szNicGuid = NULL;
  2135. delete pNicNode;
  2136. pNicNode = pTmp;
  2137. }
  2138. if (FAILED(Status))
  2139. {
  2140. TRACE_CRIT("%!FUNC! fails with status 0x%08lx", (UINT) Status);
  2141. NumNics = 0;
  2142. if (pszNics!=NULL)
  2143. {
  2144. delete pszNics;
  2145. pszNics = NULL;
  2146. }
  2147. }
  2148. else
  2149. {
  2150. if (pNumBoundToNlb != NULL)
  2151. {
  2152. *pNumBoundToNlb = NumNlbBoundNics;
  2153. }
  2154. *ppszNics = pszNics;
  2155. *pNumNics = NumNics;
  2156. }
  2157. if (pencc != NULL)
  2158. {
  2159. pencc->Release();
  2160. }
  2161. return Status;
  2162. }
  2163. WBEMSTATUS
  2164. MyNetCfg::GetBindingIF(
  2165. IN LPCWSTR szComponent,
  2166. OUT INetCfgComponentBindings **ppIBinding
  2167. )
  2168. {
  2169. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2170. INetCfgComponent *pncc = NULL;
  2171. INetCfgComponentBindings *pnccb = NULL;
  2172. HRESULT hr;
  2173. if (m_pINetCfg == NULL)
  2174. {
  2175. //
  2176. // This means we're not initialized
  2177. //
  2178. ASSERT(FALSE);
  2179. goto end;
  2180. }
  2181. hr = m_pINetCfg->FindComponent(szComponent, &pncc);
  2182. if (FAILED(hr))
  2183. {
  2184. TRACE_CRIT("Error checking if component %ws does not exist\n", szComponent);
  2185. pncc = NULL;
  2186. goto end;
  2187. }
  2188. else if (hr == S_FALSE)
  2189. {
  2190. Status = WBEM_E_NOT_FOUND;
  2191. TRACE_CRIT("Component %ws does not exist\n", szComponent);
  2192. goto end;
  2193. }
  2194. hr = pncc->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb );
  2195. if( !SUCCEEDED( hr ) )
  2196. {
  2197. TRACE_CRIT("INetCfgComponent::QueryInterface failed ");
  2198. pnccb = NULL;
  2199. goto end;
  2200. }
  2201. Status = WBEM_NO_ERROR;
  2202. end:
  2203. if (pncc)
  2204. {
  2205. pncc->Release();
  2206. pncc=NULL;
  2207. }
  2208. *ppIBinding = pnccb;
  2209. return Status;
  2210. }
  2211. WBEMSTATUS
  2212. set_string_parameter(
  2213. IN IWbemClassObjectPtr spObj,
  2214. IN LPCWSTR szParameterName,
  2215. IN LPCWSTR szValue
  2216. )
  2217. {
  2218. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2219. HRESULT hr;
  2220. {
  2221. _bstr_t bstrName = szParameterName;
  2222. _variant_t v_value = (LPWSTR) szValue; // Allocates.
  2223. hr = spObj->Put(
  2224. bstrName, // Parameter Name
  2225. 0, // Must be 0
  2226. &v_value,
  2227. 0 // Must be 0
  2228. );
  2229. v_value.Clear();
  2230. if (FAILED(hr))
  2231. {
  2232. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  2233. goto end;
  2234. }
  2235. Status = WBEM_NO_ERROR;
  2236. //
  2237. // I think bstrName releases the internally allocated string
  2238. // on exiting this block.
  2239. //
  2240. }
  2241. end:
  2242. return Status;
  2243. }
  2244. WBEMSTATUS
  2245. set_multi_string_parameter(
  2246. IN IWbemClassObjectPtr spObj,
  2247. IN LPCWSTR szParameterName,
  2248. IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
  2249. IN UINT NumItems,
  2250. IN LPCWSTR pStringValue
  2251. )
  2252. {
  2253. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2254. SAFEARRAY *pSA = NULL;
  2255. HRESULT hr;
  2256. LONG Index = 0;
  2257. //
  2258. // Create safe array for the parameter values
  2259. //
  2260. pSA = SafeArrayCreateVector(
  2261. VT_BSTR,
  2262. 0, // lower bound
  2263. NumItems // size of the fixed-sized vector.
  2264. );
  2265. if (pSA == NULL)
  2266. {
  2267. TRACE_CRIT("Could not create safe array");
  2268. Status = WBEM_E_OUT_OF_MEMORY;
  2269. goto end;
  2270. }
  2271. //
  2272. // Place the strings into the safe array
  2273. //
  2274. {
  2275. for (Index = 0; Index<NumItems; Index++)
  2276. {
  2277. LPCWSTR sz = pStringValue + Index*MaxStringLen;
  2278. //
  2279. // SafeArrayPutElement expects the string passed in to
  2280. // be of type BSTR, which is of type wchar *, except, that
  2281. // the first 2 wchars contains length and other(?)
  2282. // information. This is why you can't simply pass in sz.
  2283. //
  2284. // So to get this we initalize an object of type _bstr_t
  2285. // based on sz. On initializaton, bstrValue allocates memory
  2286. // and copies the string.
  2287. //
  2288. _bstr_t bstrValue = sz;
  2289. wchar_t *pwchar = (wchar_t *) bstrValue; // returns internal pointer.
  2290. // bpStr[Index] = sz; // may work as well.
  2291. //
  2292. // SafeArrayPutElement internally allocates space for pwchar and
  2293. // copies over the string.
  2294. // So pSA doesn't contain a direct reference to pwchar.
  2295. //
  2296. hr = SafeArrayPutElement(pSA, &Index, pwchar);
  2297. if (FAILED(hr))
  2298. {
  2299. TRACE_CRIT("Unable to put element %wsz", sz);
  2300. (VOID) SafeArrayUnaccessData(pSA);
  2301. goto end;
  2302. }
  2303. //
  2304. // I think that bstrValue's contents are deallocated on exit of
  2305. // this block.
  2306. //
  2307. }
  2308. }
  2309. #if DBG
  2310. //
  2311. // Just check ...
  2312. //
  2313. {
  2314. BSTR *pbStr=NULL;
  2315. hr = SafeArrayAccessData(pSA, ( void **) &pbStr);
  2316. if (FAILED(hr))
  2317. {
  2318. TRACE_CRIT("Could not access data of safe array");
  2319. goto end;
  2320. }
  2321. for (UINT u = 0; u<NumItems; u++)
  2322. {
  2323. LPCWSTR sz = pbStr[u];
  2324. if (_wcsicmp(sz, (pStringValue + u*MaxStringLen)))
  2325. {
  2326. TRACE_CRIT("!!!MISMATCH!!!!");
  2327. }
  2328. else
  2329. {
  2330. TRACE_CRIT("!!!MATCH!!!!");
  2331. }
  2332. }
  2333. (VOID) SafeArrayUnaccessData(pSA);
  2334. pbStr=NULL;
  2335. }
  2336. #endif // DBG
  2337. //
  2338. // Put the parameter.
  2339. //
  2340. {
  2341. VARIANT V;
  2342. _bstr_t bstrName = szParameterName;
  2343. VariantInit(&V);
  2344. V.vt = VT_ARRAY | VT_BSTR;
  2345. V.parray = pSA;
  2346. _variant_t v_value;
  2347. v_value.Attach(V); // Takes owhership of V. V now becomes empty.
  2348. ASSERT(V.vt == VT_EMPTY);
  2349. pSA = NULL; // should be no need to delete this explicitly now.
  2350. // v_value.Clear() should delete it, I think.
  2351. hr = spObj->Put(
  2352. bstrName, // Parameter Name
  2353. 0, // Must be 0
  2354. &v_value,
  2355. 0 // Must be 0
  2356. );
  2357. v_value.Clear();
  2358. if (FAILED(hr))
  2359. {
  2360. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  2361. goto end;
  2362. }
  2363. Status = WBEM_NO_ERROR;
  2364. }
  2365. //
  2366. // ?Destroy the data?
  2367. //
  2368. if (FAILED(Status))
  2369. {
  2370. if (pSA!=NULL)
  2371. {
  2372. SafeArrayDestroy(pSA);
  2373. pSA = NULL;
  2374. }
  2375. }
  2376. end:
  2377. return Status;
  2378. }
  2379. WBEMSTATUS
  2380. MyNetCfg::UpdateBindingState(
  2381. IN LPCWSTR szNic,
  2382. IN LPCWSTR szComponent,
  2383. IN UPDATE_OP Op,
  2384. OUT BOOL *pfBound
  2385. )
  2386. {
  2387. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2388. INetCfgComponent *pINic = NULL;
  2389. INetCfgComponentBindings *pIBinding=NULL;
  2390. BOOL fBound = FALSE;
  2391. HRESULT hr;
  2392. //
  2393. // Get instance to the NIC
  2394. //
  2395. Status = GetNicIF(szNic, &pINic);
  2396. if (FAILED(Status))
  2397. {
  2398. pINic = NULL;
  2399. goto end;
  2400. }
  2401. //
  2402. // Get instance of the nlb component
  2403. //
  2404. Status = GetBindingIF(szComponent, &pIBinding);
  2405. if (FAILED(Status))
  2406. {
  2407. pIBinding = NULL;
  2408. goto end;
  2409. }
  2410. //
  2411. // Check if nlb is bound to the nlb component.
  2412. //
  2413. hr = pIBinding->IsBoundTo(pINic);
  2414. if( !SUCCEEDED( hr ) )
  2415. {
  2416. TRACE_CRIT("IsBoundTo method failed for Nic %ws", szNic);
  2417. goto end;
  2418. }
  2419. if( hr == S_OK )
  2420. {
  2421. fBound = TRUE;
  2422. }
  2423. else if (hr == S_FALSE )
  2424. {
  2425. fBound = FALSE;
  2426. }
  2427. if ( (Op == MyNetCfg::NOOP)
  2428. || (Op == MyNetCfg::BIND && fBound)
  2429. || (Op == MyNetCfg::UNBIND && !fBound))
  2430. {
  2431. Status = WBEM_NO_ERROR;
  2432. goto end;
  2433. }
  2434. if (Op == MyNetCfg::BIND)
  2435. {
  2436. hr = pIBinding->BindTo( pINic );
  2437. }
  2438. else if (Op == MyNetCfg::UNBIND)
  2439. {
  2440. hr = pIBinding->UnbindFrom( pINic );
  2441. }
  2442. else
  2443. {
  2444. ASSERT(FALSE);
  2445. goto end;
  2446. }
  2447. if (FAILED(hr))
  2448. {
  2449. TRACE_CRIT("Error 0x%08lx %ws %ws on %ws",
  2450. (UINT) hr,
  2451. ((Op==MyNetCfg::BIND) ? L"binding" : L"unbinding"),
  2452. szComponent,
  2453. szNic
  2454. );
  2455. goto end;
  2456. }
  2457. //
  2458. // apply the binding change made.
  2459. //
  2460. hr = m_pINetCfg->Apply();
  2461. if( !SUCCEEDED( hr ) )
  2462. {
  2463. TRACE_CRIT("INetCfg::Apply failed with 0x%08lx", (UINT) hr);
  2464. goto end;
  2465. }
  2466. //
  2467. // We're done. Our state should now be toggled.
  2468. //
  2469. fBound = !fBound;
  2470. Status = WBEM_NO_ERROR;
  2471. end:
  2472. if (pINic!=NULL)
  2473. {
  2474. pINic->Release();
  2475. pINic = NULL;
  2476. }
  2477. if (pIBinding!=NULL)
  2478. {
  2479. pIBinding->Release();
  2480. pIBinding = NULL;
  2481. }
  2482. *pfBound = fBound;
  2483. return Status;
  2484. }
  2485. WBEMSTATUS
  2486. CfgUtilControlCluster(
  2487. IN LPCWSTR szNic,
  2488. IN LONG ioctl
  2489. )
  2490. {
  2491. HRESULT hr;
  2492. GUID Guid;
  2493. WBEMSTATUS Status;
  2494. if (!g_CfgUtils.IsInitalized())
  2495. {
  2496. TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic);
  2497. Status = WBEM_E_INITIALIZATION_FAILURE;
  2498. goto end;
  2499. }
  2500. hr = CLSIDFromString((LPWSTR)szNic, &Guid);
  2501. if (FAILED(hr))
  2502. {
  2503. TRACE_CRIT(
  2504. "CWlbsControl::Initialize failed at CLSIDFromString %ws",
  2505. szNic
  2506. );
  2507. Status = WBEM_E_INVALID_PARAMETER;
  2508. goto end;
  2509. }
  2510. TRACE_INFO("Going to stop cluster on NIC %ws...", szNic);
  2511. DWORD dwRet = g_CfgUtils.m_pWlbsControl->LocalClusterControl(
  2512. Guid,
  2513. ioctl
  2514. );
  2515. TRACE_INFO("Stop cluster returned with wlbs error 0x%08lx", dwRet);
  2516. Status = WBEM_NO_ERROR;
  2517. switch(dwRet)
  2518. {
  2519. case WLBS_ALREADY: break;
  2520. case WLBS_CONVERGED: break;
  2521. case WLBS_CONVERGING: break;
  2522. case WLBS_DEFAULT: break;
  2523. case WLBS_DRAIN_STOP: break;
  2524. case WLBS_DRAINING: break;
  2525. case WLBS_OK: break;
  2526. case WLBS_STOPPED: break;
  2527. case WLBS_SUSPENDED: break;
  2528. case WLBS_BAD_PARAMS: Status = WBEM_E_INVALID_PARAMETER; break;
  2529. default: Status = WBEM_E_CRITICAL_ERROR; break;
  2530. }
  2531. end:
  2532. return Status;
  2533. }
  2534. //
  2535. // Initializes pParams using default values.
  2536. //
  2537. VOID
  2538. CfgUtilInitializeParams(
  2539. OUT WLBS_REG_PARAMS *pParams
  2540. )
  2541. {
  2542. //
  2543. // We don't expect WlbsSetDefaults to fail (it should have been
  2544. // defined returning VOID.
  2545. //
  2546. DWORD dwRet;
  2547. dwRet = WlbsSetDefaults(pParams);
  2548. if (dwRet != WLBS_OK)
  2549. {
  2550. ZeroMemory(pParams, sizeof(*pParams));
  2551. TRACE_CRIT("Internal error: WlbsSetDefaults failed");
  2552. ASSERT(FALSE);
  2553. }
  2554. }
  2555. WBEMSTATUS
  2556. CfgUtilSafeArrayFromStrings(
  2557. IN LPCWSTR *pStrings,
  2558. IN UINT NumStrings,
  2559. OUT SAFEARRAY **ppSA
  2560. )
  2561. /*
  2562. Allocates and returns a SAFEARRAY of strings -- strings are copies of
  2563. the passed in values.
  2564. Call SafeArrayDestroy when done with the array.
  2565. */
  2566. {
  2567. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2568. SAFEARRAY *pSA = NULL;
  2569. HRESULT hr;
  2570. LONG Index = 0;
  2571. *ppSA = NULL;
  2572. //
  2573. // Create safe array for the parameter values
  2574. //
  2575. pSA = SafeArrayCreateVector(
  2576. VT_BSTR,
  2577. 0, // lower bound
  2578. NumStrings // size of the fixed-sized vector.
  2579. );
  2580. if (pSA == NULL)
  2581. {
  2582. TRACE_CRIT("Could not create safe array");
  2583. Status = WBEM_E_OUT_OF_MEMORY;
  2584. goto end;
  2585. }
  2586. //
  2587. // Place the strings into the safe array
  2588. //
  2589. {
  2590. for (Index = 0; Index<NumStrings; Index++)
  2591. {
  2592. LPCWSTR sz = pStrings[Index];
  2593. //
  2594. // SafeArrayPutElement expects the string passed in to
  2595. // be of type BSTR, which is of type wchar *, except, that
  2596. // the first 2 wchars contains length and other(?)
  2597. // information. This is why you can't simply pass in sz.
  2598. //
  2599. // So to get this we initalize an object of type _bstr_t
  2600. // based on sz. On initializaton, bstrValue allocates memory
  2601. // and copies the string.
  2602. //
  2603. _bstr_t bstrValue = sz;
  2604. wchar_t *pwchar = (wchar_t *) bstrValue; // returns internal pointer.
  2605. // bpStr[Index] = sz; // may work as well.
  2606. //
  2607. // SafeArrayPutElement internally allocates space for pwchar and
  2608. // copies over the string.
  2609. // So pSA doesn't contain a direct reference to pwchar.
  2610. //
  2611. hr = SafeArrayPutElement(pSA, &Index, pwchar);
  2612. if (FAILED(hr))
  2613. {
  2614. TRACE_CRIT("Unable to put element %wsz", sz);
  2615. (VOID) SafeArrayUnaccessData(pSA);
  2616. goto end;
  2617. }
  2618. //
  2619. // I think that bstrValue's contents are deallocated on exit of
  2620. // this block.
  2621. //
  2622. }
  2623. }
  2624. Status = WBEM_NO_ERROR;
  2625. end:
  2626. if (FAILED(Status))
  2627. {
  2628. if (pSA!=NULL)
  2629. {
  2630. SafeArrayDestroy(pSA);
  2631. pSA = NULL;
  2632. }
  2633. }
  2634. *ppSA = pSA;
  2635. return Status;
  2636. }
  2637. WBEMSTATUS
  2638. CfgUtilStringsFromSafeArray(
  2639. IN SAFEARRAY *pSA,
  2640. OUT LPWSTR **ppStrings,
  2641. OUT UINT *pNumStrings
  2642. )
  2643. /*
  2644. Extracts copies of the strings in the passed-in safe array.
  2645. Free *pStrings using the delete operator when done.
  2646. NOTE: Do NOT delete the individual strings -- they are
  2647. stored in the memory allocated for pStrings.
  2648. */
  2649. {
  2650. WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
  2651. LPWSTR *pStrings = NULL;
  2652. LPCWSTR csz;
  2653. LPWSTR sz;
  2654. UINT NumStrings = 0;
  2655. UINT u;
  2656. HRESULT hr;
  2657. BSTR *pbStr =NULL;
  2658. UINT TotalSize =0;
  2659. LONG UBound = 0;
  2660. *ppStrings = NULL;
  2661. *pNumStrings = 0;
  2662. hr = SafeArrayGetUBound(pSA, 1, &UBound);
  2663. if (FAILED(hr))
  2664. {
  2665. TRACE_CRIT("Could not get upper bound of safe array");
  2666. goto end;
  2667. }
  2668. NumStrings = (UINT) (UBound+1); // Convert from UpperBound to NumStrings.
  2669. if (NumStrings == 0)
  2670. {
  2671. // nothing in array -- we're done.
  2672. Status = WBEM_NO_ERROR;
  2673. goto end;
  2674. }
  2675. hr = SafeArrayAccessData(pSA, ( void **) &pbStr);
  2676. if (FAILED(hr))
  2677. {
  2678. TRACE_CRIT("Could not access data of safe array");
  2679. goto end;
  2680. }
  2681. //
  2682. // Calculate space for the array of pointers to strings...
  2683. //
  2684. TotalSize = NumStrings*sizeof(LPWSTR);
  2685. //
  2686. // Calculate space for the strings themselves...
  2687. //
  2688. for (u=0; u<NumStrings; u++)
  2689. {
  2690. csz = pbStr[u];
  2691. TotalSize += (wcslen(csz)+1)*sizeof(WCHAR);
  2692. }
  2693. //
  2694. // Allocate space for *both* the array of pointers and the strings
  2695. // in one shot -- we're doing a new of type LPWSTR[] for the whole
  2696. // lot, so need to specify the size in units of LPWSTR (with an
  2697. // additional +1 in case there's roundoff.
  2698. //
  2699. pStrings = new LPWSTR[(TotalSize/sizeof(LPWSTR))+1];
  2700. if (pStrings == NULL)
  2701. {
  2702. Status = WBEM_E_OUT_OF_MEMORY;
  2703. (VOID) SafeArrayUnaccessData(pSA);
  2704. goto end;
  2705. }
  2706. //
  2707. // Make sz point to the start of the place where we'll be placing
  2708. // the string data.
  2709. //
  2710. sz = (LPWSTR) (pStrings+NumStrings);
  2711. for (u=0; u<NumStrings; u++)
  2712. {
  2713. csz = pbStr[u];
  2714. UINT len = wcslen(csz)+1;
  2715. CopyMemory(sz, csz, len*sizeof(WCHAR));
  2716. pStrings[u] = sz;
  2717. sz+=len;
  2718. }
  2719. (VOID) SafeArrayUnaccessData(pSA);
  2720. Status = WBEM_NO_ERROR;
  2721. end:
  2722. pbStr=NULL;
  2723. if (FAILED(Status))
  2724. {
  2725. if (pStrings!=NULL)
  2726. {
  2727. delete pStrings;
  2728. pStrings = NULL;
  2729. }
  2730. NumStrings = 0;
  2731. }
  2732. *ppStrings = pStrings;
  2733. *pNumStrings = NumStrings;
  2734. return Status;
  2735. }
  2736. WBEMSTATUS
  2737. CfgUtilGetWmiObjectInstance(
  2738. IN IWbemServicesPtr spWbemServiceIF,
  2739. IN LPCWSTR szClassName,
  2740. IN LPCWSTR szPropertyName,
  2741. IN LPCWSTR szPropertyValue,
  2742. OUT IWbemClassObjectPtr &sprefObj // smart pointer
  2743. )
  2744. {
  2745. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  2746. HRESULT hr;
  2747. //
  2748. // TODO: consider using IWbemServices::ExecQuery
  2749. //
  2750. IEnumWbemClassObjectPtr spEnum=NULL; // smart pointer
  2751. IWbemClassObjectPtr spObj = NULL; // smart pointer.
  2752. _bstr_t bstrClassName = szClassName;
  2753. //
  2754. // get all instances of object
  2755. //
  2756. hr = spWbemServiceIF->CreateInstanceEnum(
  2757. bstrClassName,
  2758. WBEM_FLAG_RETURN_IMMEDIATELY,
  2759. NULL,
  2760. &spEnum
  2761. );
  2762. if (FAILED(hr))
  2763. {
  2764. TRACE_CRIT("IWbemServices::CreateInstanceEnum failure\n" );
  2765. spEnum = NULL;
  2766. goto end;
  2767. }
  2768. //
  2769. // Look for the object with the matching property.
  2770. //
  2771. do
  2772. {
  2773. ULONG count = 1;
  2774. hr = spEnum->Next(
  2775. INFINITE,
  2776. 1,
  2777. &spObj,
  2778. &count
  2779. );
  2780. //
  2781. // Note -- Next() returns S_OK if number asked == number returned.
  2782. // and S_FALSE if number asked < than number requested.
  2783. // Since we're asking for only ...
  2784. //
  2785. if (hr == S_OK)
  2786. {
  2787. LPWSTR szEnumValue = NULL;
  2788. Status = get_string_parameter(
  2789. spObj,
  2790. szPropertyName,
  2791. &szEnumValue // Delete when done.
  2792. );
  2793. if (FAILED(Status))
  2794. {
  2795. //
  2796. // Ignore this failure here.
  2797. //
  2798. }
  2799. else if (szEnumValue!=NULL)
  2800. {
  2801. BOOL fFound = FALSE;
  2802. if (!_wcsicmp(szEnumValue, szPropertyValue))
  2803. {
  2804. fFound = TRUE;
  2805. }
  2806. delete szEnumValue;
  2807. if (fFound)
  2808. {
  2809. break; // BREAK BREAK BREAK BREAK
  2810. }
  2811. }
  2812. }
  2813. else
  2814. {
  2815. TRACE_INFO(
  2816. "====0x%p->Next() returns Error 0x%lx; count=0x%lu", (PVOID) spObj,
  2817. (UINT) hr, count);
  2818. }
  2819. //
  2820. // Since I don't fully trust smart pointers, I'm specifically
  2821. // setting spObj to NULL here...
  2822. //
  2823. spObj = NULL; // smart pointer
  2824. } while (hr == S_OK);
  2825. if (spObj == NULL)
  2826. {
  2827. //
  2828. // We couldn't find a NIC which matches the one asked for...
  2829. //
  2830. Status = WBEM_E_NOT_FOUND;
  2831. goto end;
  2832. }
  2833. end:
  2834. if (FAILED(Status))
  2835. {
  2836. sprefObj = NULL;
  2837. }
  2838. else
  2839. {
  2840. sprefObj = spObj; // smart pointer.
  2841. }
  2842. return Status;
  2843. }
  2844. WBEMSTATUS
  2845. CfgUtilGetWmiRelPath(
  2846. IN IWbemClassObjectPtr spObj,
  2847. OUT LPWSTR * pszRelPath // free using delete
  2848. )
  2849. {
  2850. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2851. LPWSTR pRelPath = NULL;
  2852. //
  2853. // Extract the relative path, needed for ExecMethod.
  2854. //
  2855. Status = get_string_parameter(
  2856. spObj,
  2857. L"__RELPATH", // szParameterName
  2858. &pRelPath // Delete when done.
  2859. );
  2860. if (FAILED(Status))
  2861. {
  2862. TRACE_CRIT("Couldn't get rel path");
  2863. pRelPath = NULL;
  2864. goto end;
  2865. }
  2866. else
  2867. {
  2868. if (pRelPath==NULL)
  2869. {
  2870. ASSERT(FALSE); // we don't expect this!
  2871. goto end;
  2872. }
  2873. TRACE_CRIT("GOT RELATIVE PATH %ws", pRelPath);
  2874. }
  2875. end:
  2876. *pszRelPath = pRelPath;
  2877. return Status;
  2878. }
  2879. WBEMSTATUS
  2880. CfgUtilGetWmiInputInstanceAndRelPath(
  2881. IN IWbemServicesPtr spWbemServiceIF,
  2882. IN LPCWSTR szClassName,
  2883. IN LPCWSTR szPropertyName, // NULL: return Class rel path
  2884. IN LPCWSTR szPropertyValue,
  2885. IN LPCWSTR szMethodName,
  2886. OUT IWbemClassObjectPtr &spWbemInputInstance, // smart pointer
  2887. OUT LPWSTR * pszRelPath // free using delete
  2888. )
  2889. {
  2890. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  2891. IWbemClassObjectPtr spClassObj = NULL; // smart pointer
  2892. HRESULT hr;
  2893. LPWSTR pRelPath = NULL;
  2894. TRACE_INFO(L"-> %!FUNC!(PropertyValue=%ws)", szPropertyValue);
  2895. //
  2896. // Get CLASS object
  2897. //
  2898. {
  2899. hr = spWbemServiceIF->GetObject(
  2900. _bstr_t(szClassName),
  2901. 0,
  2902. NULL,
  2903. &spClassObj,
  2904. NULL
  2905. );
  2906. if (FAILED(hr))
  2907. {
  2908. TRACE_CRIT("Couldn't get nic class object pointer");
  2909. Status = (WBEMSTATUS)hr;
  2910. goto end;
  2911. }
  2912. }
  2913. //
  2914. // Get WMI path to specific object
  2915. //
  2916. if (szPropertyName == NULL)
  2917. {
  2918. // Get WMI path to the class
  2919. Status = CfgUtilGetWmiRelPath(
  2920. spClassObj,
  2921. &pRelPath
  2922. );
  2923. if (FAILED(Status))
  2924. {
  2925. goto end;
  2926. }
  2927. }
  2928. else
  2929. {
  2930. IWbemClassObjectPtr spObj = NULL; // smart pointer
  2931. pRelPath = NULL;
  2932. Status = CfgUtilGetWmiObjectInstance(
  2933. spWbemServiceIF,
  2934. szClassName,
  2935. szPropertyName,
  2936. szPropertyValue,
  2937. spObj // smart pointer, passed by ref
  2938. );
  2939. if (FAILED(Status))
  2940. {
  2941. ASSERT(spObj == NULL);
  2942. goto end;
  2943. }
  2944. Status = CfgUtilGetWmiRelPath(
  2945. spObj,
  2946. &pRelPath
  2947. );
  2948. spObj = NULL; // smart pointer
  2949. if (FAILED(Status))
  2950. {
  2951. goto end;
  2952. }
  2953. }
  2954. //
  2955. // Get the input parameters to the call to the method
  2956. //
  2957. {
  2958. IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
  2959. // check if any input parameters specified.
  2960. hr = spClassObj->GetMethod(
  2961. szMethodName,
  2962. 0,
  2963. &spWbemInput,
  2964. NULL
  2965. );
  2966. if(FAILED(hr))
  2967. {
  2968. TRACE_CRIT("IWbemClassObject::GetMethod failure");
  2969. Status = (WBEMSTATUS) hr;
  2970. goto end;
  2971. }
  2972. if (spWbemInput != NULL)
  2973. {
  2974. hr = spWbemInput->SpawnInstance( 0, &spWbemInputInstance );
  2975. if( FAILED( hr) )
  2976. {
  2977. TRACE_CRIT("IWbemClassObject::SpawnInstance failure. Unable to spawn instance." );
  2978. Status = (WBEMSTATUS) hr;
  2979. goto end;
  2980. }
  2981. }
  2982. else
  2983. {
  2984. //
  2985. // This method has no input arguments!
  2986. //
  2987. spWbemInputInstance = NULL;
  2988. }
  2989. }
  2990. Status = WBEM_NO_ERROR;
  2991. end:
  2992. if (FAILED(Status))
  2993. {
  2994. if (pRelPath != NULL)
  2995. {
  2996. delete pRelPath;
  2997. pRelPath = NULL;
  2998. }
  2999. }
  3000. *pszRelPath = pRelPath;
  3001. TRACE_INFO(L"<- %!FUNC!(Obj=%ws) returns 0x%08lx", szPropertyValue, (UINT) Status);
  3002. return Status;
  3003. }
  3004. WBEMSTATUS
  3005. CfgUtilGetWmiStringParam(
  3006. IN IWbemClassObjectPtr spObj,
  3007. IN LPCWSTR szParameterName,
  3008. OUT LPWSTR *ppStringValue
  3009. )
  3010. {
  3011. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  3012. WCHAR *pStringValue = NULL;
  3013. try
  3014. {
  3015. _variant_t v_value;
  3016. CIMTYPE v_type;
  3017. HRESULT hr;
  3018. hr = spObj->Get(
  3019. _bstr_t(szParameterName), // Name
  3020. 0, // Reserved, must be 0
  3021. &v_value, // Place to store value
  3022. &v_type, // Type of value
  3023. NULL // Flavor (unused)
  3024. );
  3025. if (FAILED(hr))
  3026. {
  3027. // Couldn't read the Setting ID field!
  3028. //
  3029. TRACE_CRIT(
  3030. "get_str_parm:Couldn't retrieve %ws from 0x%p. Hr=0x%08lx",
  3031. szParameterName,
  3032. (PVOID) spObj,
  3033. hr
  3034. );
  3035. goto end;
  3036. }
  3037. else if (v_type == VT_NULL)
  3038. {
  3039. pStringValue = NULL;
  3040. Status = WBEM_NO_ERROR;
  3041. goto end;
  3042. }
  3043. else
  3044. {
  3045. if (v_type != VT_BSTR)
  3046. {
  3047. TRACE_CRIT(
  3048. "get_str_parm: Parm value not of string type %ws from 0x%p",
  3049. szParameterName,
  3050. (PVOID) spObj
  3051. );
  3052. Status = WBEM_E_INVALID_PARAMETER;
  3053. }
  3054. else
  3055. {
  3056. _bstr_t bstrNicGuid(v_value);
  3057. LPCWSTR sz = bstrNicGuid; // Pointer to internal buffer.
  3058. if (sz==NULL)
  3059. {
  3060. // hmm.. null value
  3061. pStringValue = NULL;
  3062. Status = WBEM_NO_ERROR;
  3063. }
  3064. else
  3065. {
  3066. UINT len = wcslen(sz);
  3067. pStringValue = new WCHAR[len+1];
  3068. if (pStringValue == NULL)
  3069. {
  3070. TRACE_CRIT("get_str_parm: Alloc failure!");
  3071. Status = WBEM_E_OUT_OF_MEMORY;
  3072. }
  3073. else
  3074. {
  3075. CopyMemory(pStringValue, sz, (len+1)*sizeof(WCHAR));
  3076. Status = WBEM_NO_ERROR;
  3077. }
  3078. }
  3079. TRACE_VERB(
  3080. "get_str_parm: String parm %ws of 0x%p is %ws",
  3081. szParameterName,
  3082. (PVOID) spObj,
  3083. (sz==NULL) ? L"<null>" : sz
  3084. );
  3085. }
  3086. v_value.Clear(); // Must be cleared after each call to Get.
  3087. }
  3088. }
  3089. catch( _com_error e )
  3090. {
  3091. TRACE_INFO(L"%!FUNC! -- com exception");
  3092. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  3093. }
  3094. end:
  3095. if (!FAILED(Status) && pStringValue == NULL)
  3096. {
  3097. //
  3098. // We convert a NULL value to an empty, not NULL string.
  3099. //
  3100. pStringValue = new WCHAR[1];
  3101. if (pStringValue == NULL)
  3102. {
  3103. Status = WBEM_E_OUT_OF_MEMORY;
  3104. }
  3105. else
  3106. {
  3107. *pStringValue = 0;
  3108. Status = WBEM_NO_ERROR;
  3109. }
  3110. }
  3111. *ppStringValue = pStringValue;
  3112. return Status;
  3113. }
  3114. WBEMSTATUS
  3115. CfgUtilSetWmiStringParam(
  3116. IN IWbemClassObjectPtr spObj,
  3117. IN LPCWSTR szParameterName,
  3118. IN LPCWSTR szValue
  3119. )
  3120. {
  3121. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  3122. try
  3123. {
  3124. HRESULT hr;
  3125. _bstr_t bstrName = szParameterName;
  3126. _variant_t v_value = (LPWSTR) szValue; // Allocates.
  3127. hr = spObj->Put(
  3128. bstrName, // Parameter Name
  3129. 0, // Must be 0
  3130. &v_value,
  3131. 0 // Must be 0
  3132. );
  3133. v_value.Clear();
  3134. if (FAILED(hr))
  3135. {
  3136. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  3137. goto end;
  3138. }
  3139. Status = WBEM_NO_ERROR;
  3140. //
  3141. // I think bstrName releases the internally allocated string
  3142. // on exiting this block.
  3143. //
  3144. }
  3145. catch( _com_error e )
  3146. {
  3147. TRACE_INFO(L"%!FUNC! -- com exception");
  3148. Status = WBEM_E_INVALID_PARAMETER;
  3149. }
  3150. end:
  3151. return Status;
  3152. }
  3153. WBEMSTATUS
  3154. CfgUtilGetWmiStringArrayParam(
  3155. IN IWbemClassObjectPtr spObj,
  3156. IN LPCWSTR szParameterName,
  3157. OUT LPWSTR **ppStrings,
  3158. OUT UINT *pNumStrings
  3159. )
  3160. {
  3161. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  3162. try
  3163. {
  3164. _variant_t v_value;
  3165. CIMTYPE v_type;
  3166. HRESULT hr;
  3167. LONG count = 0;
  3168. *ppStrings = NULL;
  3169. *pNumStrings = 0;
  3170. hr = spObj->Get(
  3171. _bstr_t(szParameterName),
  3172. 0, // Reserved, must be 0
  3173. &v_value, // Place to store value
  3174. &v_type, // Type of value
  3175. NULL // Flavor (unused)
  3176. );
  3177. if (FAILED(hr))
  3178. {
  3179. // Couldn't read the requested parameter.
  3180. //
  3181. TRACE_CRIT(
  3182. "get_multi_str_parm:Couldn't retrieve %ws from 0x%p",
  3183. szParameterName,
  3184. (PVOID) spObj
  3185. );
  3186. Status = WBEM_E_INVALID_PARAMETER;
  3187. goto end;
  3188. }
  3189. if (v_type != (VT_ARRAY | VT_BSTR))
  3190. {
  3191. if (v_type == VT_NULL)
  3192. {
  3193. //
  3194. // We convert a NULL value to zero strings
  3195. //
  3196. Status = WBEM_NO_ERROR;
  3197. goto end;
  3198. }
  3199. TRACE_CRIT("vt is not of type string!");
  3200. goto end;
  3201. }
  3202. else
  3203. {
  3204. VARIANT ipsV = v_value.Detach();
  3205. SAFEARRAY *pSA = ipsV.parray;
  3206. Status = CfgUtilStringsFromSafeArray(
  3207. pSA,
  3208. ppStrings,
  3209. pNumStrings
  3210. );
  3211. VariantClear( &ipsV );
  3212. }
  3213. }
  3214. catch( _com_error e )
  3215. {
  3216. TRACE_INFO(L"%!FUNC! -- com exception");
  3217. Status = WBEM_E_NOT_FOUND;
  3218. }
  3219. end:
  3220. return Status;
  3221. }
  3222. WBEMSTATUS
  3223. CfgUtilSetWmiStringArrayParam(
  3224. IN IWbemClassObjectPtr spObj,
  3225. IN LPCWSTR szParameterName,
  3226. IN LPCWSTR *ppStrings,
  3227. IN UINT NumStrings
  3228. )
  3229. {
  3230. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  3231. SAFEARRAY *pSA = NULL;
  3232. try
  3233. {
  3234. HRESULT hr;
  3235. LONG Index = 0;
  3236. Status = CfgUtilSafeArrayFromStrings(
  3237. ppStrings,
  3238. NumStrings,
  3239. &pSA
  3240. );
  3241. if (FAILED(Status))
  3242. {
  3243. pSA = NULL;
  3244. goto end;
  3245. }
  3246. //
  3247. // Put the parameter.
  3248. //
  3249. {
  3250. VARIANT V;
  3251. _bstr_t bstrName = szParameterName;
  3252. VariantInit(&V);
  3253. V.vt = VT_ARRAY | VT_BSTR;
  3254. V.parray = pSA;
  3255. _variant_t v_value;
  3256. v_value.Attach(V); // Takes owhership of V. V now becomes empty.
  3257. ASSERT(V.vt == VT_EMPTY);
  3258. pSA = NULL; // should be no need to delete this explicitly now.
  3259. // v_value.Clear() should delete it, I think.
  3260. hr = spObj->Put(
  3261. bstrName, // Parameter Name
  3262. 0, // Must be 0
  3263. &v_value,
  3264. 0 // Must be 0
  3265. );
  3266. v_value.Clear();
  3267. if (FAILED(hr))
  3268. {
  3269. Status = (WBEMSTATUS) hr;
  3270. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  3271. goto end;
  3272. }
  3273. Status = WBEM_NO_ERROR;
  3274. }
  3275. }
  3276. catch( _com_error e )
  3277. {
  3278. TRACE_INFO(L"%!FUNC! -- com exception");
  3279. Status = WBEM_E_INVALID_PARAMETER;
  3280. }
  3281. end:
  3282. if (pSA!=NULL)
  3283. {
  3284. SafeArrayDestroy(pSA);
  3285. pSA = NULL;
  3286. }
  3287. return Status;
  3288. }
  3289. WBEMSTATUS
  3290. CfgUtilGetWmiDWORDParam(
  3291. IN IWbemClassObjectPtr spObj,
  3292. IN LPCWSTR szParameterName,
  3293. OUT DWORD *pValue
  3294. )
  3295. {
  3296. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  3297. DWORD Value=0;
  3298. try
  3299. {
  3300. _variant_t v_value;
  3301. CIMTYPE v_type;
  3302. HRESULT hr;
  3303. hr = spObj->Get(
  3304. _bstr_t(szParameterName), // Name
  3305. 0, // Reserved, must be 0
  3306. &v_value, // Place to store value
  3307. &v_type, // Type of value
  3308. NULL // Flavor (unused)
  3309. );
  3310. if (FAILED(hr))
  3311. {
  3312. // Couldn't read the parameter
  3313. //
  3314. TRACE_CRIT(
  3315. "GetDWORDParm:Couldn't retrieve %ws from 0x%p",
  3316. szParameterName,
  3317. (PVOID) spObj
  3318. );
  3319. goto end;
  3320. }
  3321. else
  3322. {
  3323. Value = (DWORD) (long) v_value;
  3324. v_value.Clear(); // Must be cleared after each call to Get.
  3325. Status = WBEM_NO_ERROR;
  3326. }
  3327. }
  3328. catch( _com_error e )
  3329. {
  3330. TRACE_INFO(L"%!FUNC! -- com exception");
  3331. Status = WBEM_E_NOT_FOUND;
  3332. }
  3333. end:
  3334. *pValue = Value;
  3335. return Status;
  3336. }
  3337. WBEMSTATUS
  3338. CfgUtilSetWmiDWORDParam(
  3339. IN IWbemClassObjectPtr spObj,
  3340. IN LPCWSTR szParameterName,
  3341. IN DWORD Value
  3342. )
  3343. {
  3344. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  3345. try
  3346. {
  3347. HRESULT hr;
  3348. _bstr_t bstrName = szParameterName;
  3349. _variant_t v_value = (long) Value;
  3350. hr = spObj->Put(
  3351. bstrName, // Parameter Name
  3352. 0, // Must be 0
  3353. &v_value,
  3354. 0 // Must be 0
  3355. );
  3356. v_value.Clear();
  3357. if (FAILED(hr))
  3358. {
  3359. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  3360. goto end;
  3361. }
  3362. Status = WBEM_NO_ERROR;
  3363. }
  3364. catch( _com_error e )
  3365. {
  3366. TRACE_INFO(L"%!FUNC! -- com exception");
  3367. Status = WBEM_E_INVALID_PARAMETER;
  3368. }
  3369. end:
  3370. return Status;
  3371. }
  3372. WBEMSTATUS
  3373. CfgUtilGetWmiBoolParam(
  3374. IN IWbemClassObjectPtr spObj,
  3375. IN LPCWSTR szParameterName,
  3376. OUT BOOL *pValue
  3377. )
  3378. {
  3379. WBEMSTATUS Status = WBEM_E_NOT_FOUND;
  3380. BOOL Value=0;
  3381. try
  3382. {
  3383. _variant_t v_value;
  3384. CIMTYPE v_type;
  3385. HRESULT hr;
  3386. hr = spObj->Get(
  3387. _bstr_t(szParameterName), // Name
  3388. 0, // Reserved, must be 0
  3389. &v_value, // Place to store value
  3390. &v_type, // Type of value
  3391. NULL // Flavor (unused)
  3392. );
  3393. if (FAILED(hr))
  3394. {
  3395. // Couldn't read the parameter
  3396. //
  3397. TRACE_CRIT(
  3398. "GetDWORDParm:Couldn't retrieve %ws from 0x%p",
  3399. szParameterName,
  3400. (PVOID) spObj
  3401. );
  3402. goto end;
  3403. }
  3404. else
  3405. {
  3406. Value = ((bool) v_value)!=0;
  3407. v_value.Clear(); // Must be cleared after each call to Get.
  3408. Status = WBEM_NO_ERROR;
  3409. }
  3410. }
  3411. catch( _com_error e )
  3412. {
  3413. TRACE_INFO(L"%!FUNC! -- com exception");
  3414. Status = WBEM_E_NOT_FOUND;
  3415. }
  3416. end:
  3417. *pValue = Value;
  3418. return Status;
  3419. }
  3420. WBEMSTATUS
  3421. CfgUtilSetWmiBoolParam(
  3422. IN IWbemClassObjectPtr spObj,
  3423. IN LPCWSTR szParameterName,
  3424. IN BOOL Value
  3425. )
  3426. {
  3427. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  3428. try
  3429. {
  3430. HRESULT hr;
  3431. _bstr_t bstrName = szParameterName;
  3432. _variant_t v_value = (long) Value;
  3433. hr = spObj->Put(
  3434. bstrName, // Parameter Name
  3435. 0, // Must be 0
  3436. &v_value,
  3437. 0 // Must be 0
  3438. );
  3439. v_value.Clear();
  3440. if (FAILED(hr))
  3441. {
  3442. TRACE_CRIT("Unable to put parameter %ws", szParameterName);
  3443. goto end;
  3444. }
  3445. Status = WBEM_NO_ERROR;
  3446. }
  3447. catch( _com_error e )
  3448. {
  3449. TRACE_INFO(L"%!FUNC! -- com exception");
  3450. Status = WBEM_E_INVALID_PARAMETER;
  3451. }
  3452. end:
  3453. return Status;
  3454. }
  3455. WBEMSTATUS
  3456. CfgUtilConnectToServer(
  3457. IN LPCWSTR szNetworkResource, // \\machinename\root\microsoftnlb \root\...
  3458. IN LPCWSTR szUser,
  3459. IN LPCWSTR szPassword,
  3460. IN LPCWSTR szAuthority,
  3461. OUT IWbemServices **ppWbemService // deref when done.
  3462. )
  3463. {
  3464. HRESULT hr = WBEM_E_CRITICAL_ERROR;
  3465. IWbemLocatorPtr spLocator=NULL; // Smart pointer
  3466. IWbemServices *pService=NULL;
  3467. try
  3468. {
  3469. _bstr_t serverPath(szNetworkResource);
  3470. *ppWbemService = NULL;
  3471. hr = CoCreateInstance(CLSID_WbemLocator, 0,
  3472. CLSCTX_INPROC_SERVER,
  3473. IID_IWbemLocator,
  3474. (LPVOID *) &spLocator);
  3475. if (FAILED(hr))
  3476. {
  3477. TRACE_CRIT(L"CoCreateInstance IWebmLocator failed 0x%08lx ", (UINT)hr);
  3478. goto end;
  3479. }
  3480. for (int timesToRetry=0; timesToRetry<10; timesToRetry++)
  3481. {
  3482. hr = spLocator->ConnectServer(
  3483. serverPath,
  3484. // (szUser!=NULL) ? (_bstr_t(szUser)) : NULL,
  3485. _bstr_t(szUser),
  3486. // (szPassword==NULL) ? NULL : _bstr_t(szPassword),
  3487. _bstr_t(szPassword),
  3488. NULL, // Locale
  3489. 0, // Security flags
  3490. //(szAuthority==NULL) ? NULL : _bstr_t(szAuthority),
  3491. _bstr_t(szAuthority),
  3492. NULL,
  3493. &pService
  3494. );
  3495. if( !FAILED( hr) )
  3496. {
  3497. break;
  3498. }
  3499. //
  3500. // these have been found to be special cases where retrying may
  3501. // help. The errors below are not in any header file, and I searched
  3502. // the index2a sources for these constants -- no hits.
  3503. // TODO: file bug against WMI.
  3504. //
  3505. if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) )
  3506. {
  3507. TRACE_CRIT(L"connectserver recoverable failure, retrying.");
  3508. Sleep(500);
  3509. }
  3510. }
  3511. if (FAILED(hr))
  3512. {
  3513. TRACE_CRIT(L"Error 0x%08lx connecting to server", (UINT) hr);
  3514. goto end;
  3515. }
  3516. else
  3517. {
  3518. TRACE_INFO(L"Successfully connected to server %s", serverPath);
  3519. }
  3520. // Set the proxy so that impersonation of the client occurs.
  3521. //
  3522. hr = CoSetProxyBlanket(
  3523. pService,
  3524. RPC_C_AUTHN_WINNT,
  3525. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
  3526. COLE_DEFAULT_PRINCIPAL, // NULL,
  3527. RPC_C_AUTHN_LEVEL_DEFAULT,
  3528. RPC_C_IMP_LEVEL_IMPERSONATE,
  3529. COLE_DEFAULT_AUTHINFO, // NULL,
  3530. EOAC_DEFAULT // EOAC_NONE
  3531. );
  3532. if (FAILED(hr))
  3533. {
  3534. TRACE_CRIT(L"Error 0x%08lx setting proxy blanket", (UINT) hr);
  3535. goto end;
  3536. }
  3537. hr = WBEM_NO_ERROR;
  3538. }
  3539. catch( _com_error e )
  3540. {
  3541. TRACE_INFO(L"%!FUNC! -- com exception");
  3542. hr = WBEM_E_INVALID_PARAMETER;
  3543. }
  3544. end:
  3545. spLocator = NULL; // smart pointer.
  3546. if (FAILED(hr))
  3547. {
  3548. if (pService != NULL)
  3549. {
  3550. pService->Release();
  3551. pService=NULL;
  3552. }
  3553. }
  3554. *ppWbemService = pService;
  3555. return (WBEMSTATUS) hr;
  3556. }
  3557. WBEMSTATUS
  3558. CfgUtilsGetNlbCompatibleNics(
  3559. OUT LPWSTR **ppszNics,
  3560. OUT UINT *pNumNics,
  3561. OUT UINT *pNumBoundToNlb // OPTIONAL
  3562. )
  3563. {
  3564. WBEMSTATUS Status = WBEM_NO_ERROR;
  3565. BOOL fNetCfgInitialized = FALSE;
  3566. MyNetCfg NetCfg;
  3567. BOOL fBound = FALSE;
  3568. //
  3569. // Get and initialize interface to netcfg
  3570. //
  3571. Status = NetCfg.Initialize(FALSE); // TRUE == get write lock.
  3572. if (FAILED(Status))
  3573. {
  3574. goto end;
  3575. }
  3576. fNetCfgInitialized = TRUE;
  3577. //
  3578. //
  3579. //
  3580. Status = NetCfg.GetNlbCompatibleNics(
  3581. ppszNics,
  3582. pNumNics,
  3583. pNumBoundToNlb // OPTIONAL
  3584. );
  3585. end:
  3586. if (fNetCfgInitialized)
  3587. {
  3588. NetCfg.Deinitialize();
  3589. }
  3590. return Status;
  3591. }
  3592. WBEMSTATUS
  3593. CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj(
  3594. IN IWbemClassObjectPtr spObj, // smart pointer
  3595. OUT IWbemClassObjectPtr &spAdapterObj // smart pointer, by reference
  3596. )
  3597. /*
  3598. We need to return the "Win32_NetworkAdapter" object associated with
  3599. the "Win32_NetworkAdapterConfiguration" object.
  3600. We use the "Win32_NetworkAdapterSetting" object for this.
  3601. */
  3602. {
  3603. spAdapterObj = spObj;
  3604. return WBEM_NO_ERROR;
  3605. }
  3606. #if 0
  3607. HRESULT
  3608. Test(
  3609. IWbemClassObject * pNetworkAdapterIn)
  3610. //
  3611. // FROM: nt\base\cluster\mgmt\cluscfg\server\cenumcluscfgipaddresses.cpp
  3612. //
  3613. {
  3614. #define ARRAYSIZE(_arr) (sizeof(_arr)/sizeof(_arr[0]))
  3615. #define TraceSysAllocString(_str) (NULL)
  3616. #define TraceSysFreeString( bstrQuery ) (0)
  3617. #define THR(_exp) S_OK
  3618. #define STHR(_exp) S_OK
  3619. #define STATUS_REPORT_STRING(_a, _b, _c, _d, _e) (0)
  3620. #define STATUS_REPORT( _a, _b, _c, _d) (0)
  3621. #define Assert ASSERT
  3622. #define HRETURN( hr ) return hr
  3623. HRESULT hr = S_OK;
  3624. BSTR bstrQuery = NULL;
  3625. BSTR bstrWQL = NULL;
  3626. VARIANT var;
  3627. WCHAR sz[ 256 ];
  3628. IEnumWbemClassObject * pConfigurations = NULL;
  3629. ULONG ulReturned;
  3630. IWbemClassObject * pConfiguration = NULL;
  3631. int cFound = 0;
  3632. BSTR bstrAdapterName = NULL;
  3633. int idx;
  3634. VariantInit( &var );
  3635. bstrWQL = TraceSysAllocString( L"WQL" );
  3636. if ( bstrWQL == NULL )
  3637. {
  3638. goto OutOfMemory;
  3639. } // if:
  3640. hr = THR( HrGetWMIProperty( pNetworkAdapterIn, L"DeviceID", VT_BSTR, &var ) );
  3641. if ( FAILED( hr ) )
  3642. {
  3643. goto Cleanup;
  3644. } // if:
  3645. _snwprintf( sz, ARRAYSIZE( sz ), L"Associators of {Win32_NetworkAdapter.DeviceID='%s'} where AssocClass=Win32_NetworkAdapterSetting", var.bstrVal );
  3646. bstrQuery = TraceSysAllocString( sz );
  3647. if ( bstrQuery == NULL )
  3648. {
  3649. goto OutOfMemory;
  3650. } // if:
  3651. VariantClear( &var );
  3652. hr = THR( HrGetWMIProperty( pNetworkAdapterIn, L"NetConnectionID", VT_BSTR, &var ) );
  3653. if ( FAILED( hr ) )
  3654. {
  3655. goto Cleanup;
  3656. } // if:
  3657. bstrAdapterName = TraceSysAllocString( var.bstrVal );
  3658. if ( bstrAdapterName == NULL )
  3659. {
  3660. goto OutOfMemory;
  3661. } // if:
  3662. hr = THR( m_pIWbemServices->ExecQuery( bstrWQL, bstrQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pConfigurations ) );
  3663. if ( FAILED( hr ) )
  3664. {
  3665. STATUS_REPORT_STRING(
  3666. TASKID_Major_Find_Devices,
  3667. TASKID_Minor_WMI_NetworkAdapterSetting_Qry_Failed,
  3668. IDS_ERROR_WMI_NETWORKADAPTERSETTINGS_QRY_FAILED,
  3669. bstrAdapterName,
  3670. hr
  3671. );
  3672. goto Cleanup;
  3673. } // if:
  3674. for ( idx = 0; ; idx++ )
  3675. {
  3676. hr = pConfigurations->Next( WBEM_INFINITE, 1, &pConfiguration, &ulReturned );
  3677. if ( ( hr == S_OK ) && ( ulReturned == 1 ) )
  3678. {
  3679. //
  3680. // KB: 25-AUG-2000 GalenB
  3681. //
  3682. // WMI only supports one configuration per adapter!
  3683. //
  3684. Assert( idx < 1 );
  3685. VariantClear( &var );
  3686. hr = THR( HrGetWMIProperty( pConfiguration, L"IPEnabled", VT_BOOL, &var ) );
  3687. if ( FAILED( hr ) )
  3688. {
  3689. goto Cleanup;
  3690. } // if:
  3691. //
  3692. // If this configuration is not for TCP/IP then skip it.
  3693. //
  3694. if ( ( var.vt != VT_BOOL ) || ( var.boolVal != VARIANT_TRUE ) )
  3695. {
  3696. hr = S_FALSE;
  3697. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Non_Tcp_Config, IDS_WARNING__NON_TCP_CONFIG, bstrAdapterName, hr );
  3698. continue;
  3699. } // if:
  3700. hr = STHR( HrSaveIPAddresses( bstrAdapterName, pConfiguration ) );
  3701. if ( FAILED( hr ) )
  3702. {
  3703. goto Cleanup;
  3704. } // if:
  3705. //
  3706. // KB: 24-AUG-2000 GalenB
  3707. //
  3708. // If any configuration returns S_FALSE then we skip.
  3709. //
  3710. if ( hr == S_FALSE )
  3711. {
  3712. pConfiguration->Release();
  3713. pConfiguration = NULL;
  3714. continue;
  3715. } // if:
  3716. cFound++;
  3717. pConfiguration->Release();
  3718. pConfiguration = NULL;
  3719. } // if:
  3720. else if ( ( hr == S_FALSE ) && ( ulReturned == 0 ) )
  3721. {
  3722. hr = S_OK;
  3723. break;
  3724. } // else if:
  3725. else
  3726. {
  3727. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WQL_Qry_Next_Failed, IDS_ERROR_WQL_QRY_NEXT_FAILED, bstrQuery, hr );
  3728. goto Cleanup;
  3729. } // else:
  3730. } // for:
  3731. //
  3732. // If we didn't find any valid configurations then we should return S_FALSE
  3733. // to tell the caller to ingore that adpater.
  3734. //
  3735. if ( cFound == 0 )
  3736. {
  3737. hr = S_FALSE;
  3738. STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_No_Valid_TCP_Configs, IDS_WARNING_NO_VALID_TCP_CONFIGS, bstrAdapterName, hr );
  3739. } // if:
  3740. goto Cleanup;
  3741. OutOfMemory:
  3742. hr = THR( E_OUTOFMEMORY );
  3743. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetAdapterConfiguration, IDS_ERROR_OUTOFMEMORY, hr );
  3744. Cleanup:
  3745. VariantClear( &var );
  3746. TraceSysFreeString( bstrQuery );
  3747. TraceSysFreeString( bstrWQL );
  3748. TraceSysFreeString( bstrAdapterName );
  3749. if ( pConfiguration != NULL )
  3750. {
  3751. pConfiguration->Release();
  3752. } // if:
  3753. if ( pConfigurations != NULL )
  3754. {
  3755. pConfigurations->Release();
  3756. } // if:
  3757. HRETURN( hr );
  3758. } //*** CEnumClusCfgIPAddresses::HrGetAdapterConfiguration
  3759. #endif // 0