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.

1014 lines
23 KiB

  1. #include <afxext.h>
  2. #include <netcfgx.h>
  3. #include <devguid.h>
  4. #include <cfg.h>
  5. #include "resource.h"
  6. #include "Application.h"
  7. #include "Document.h"
  8. #include "MainForm.h"
  9. #include "LeftView.h"
  10. #include "AboutDialog.h"
  11. #include "disclaimer.h"
  12. #include "MUsingCom.h"
  13. #include "resourcestring.h"
  14. Application theApplication;
  15. MUsingCom usingCom;
  16. BOOL CanRunNLB(void);
  17. BEGIN_MESSAGE_MAP( Application, CWinApp )
  18. ON_COMMAND( ID_APP_ABOUT, OnAppAbout )
  19. END_MESSAGE_MAP()
  20. #define EVENT_NAME _T("NLB Cluster Manager")
  21. #define szNLBMGRREG_BASE_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NLB"
  22. #define szNLBMGRREG_DISABLE_DISCLAIMER L"DisableNlbMgrDisclaimer"
  23. HKEY
  24. NlbMgrRegCreateKey(
  25. LPCWSTR szSubKey // Optional
  26. );
  27. UINT
  28. NlbMgrRegReadUINT(
  29. HKEY hKey,
  30. LPCWSTR szName,
  31. UINT Default
  32. );
  33. VOID
  34. NlbMgrRegWriteUINT(
  35. HKEY hKey,
  36. LPCWSTR szName,
  37. UINT Value
  38. );
  39. BOOL NoAdminNics(void);
  40. BOOL
  41. Application::InitInstance()
  42. {
  43. /*
  44. The following event is created to detect the existence of an instance of the NLB Manager.
  45. If an instance exists, GetLastError will return ERROR_ALREADY_EXISTS. Then, we make that
  46. instance to be the current window
  47. Note : We do NOT save the handle returned by the CreateEvent call and hence do NOT close
  48. it when we quit.
  49. */
  50. if (CreateEvent(NULL, FALSE, TRUE, EVENT_NAME) == NULL)
  51. {
  52. return FALSE;
  53. }
  54. if (GetLastError() == ERROR_ALREADY_EXISTS)
  55. {
  56. CString str;
  57. HWND hWnd;
  58. if (str.LoadString(IDR_MAINFRAME) == 0)
  59. return FALSE;
  60. // Find the existing NLB Manager window
  61. if (!(hWnd = FindWindow(NULL, (LPCTSTR)str)))
  62. return FALSE;
  63. // If the existing NLB Manager window is Minimized, call ShowWindow to restore it, else
  64. // call SetForegroundWindow to bring it to the foreground
  65. if (IsIconic(hWnd))
  66. ShowWindow(hWnd, SW_RESTORE);
  67. else
  68. SetForegroundWindow(hWnd);
  69. return FALSE;
  70. }
  71. CSingleDocTemplate* pSingleDocumentTemplate =
  72. new CSingleDocTemplate( IDR_MAINFRAME,
  73. RUNTIME_CLASS( Document ),
  74. RUNTIME_CLASS( MainForm ),
  75. RUNTIME_CLASS( LeftView) );
  76. AddDocTemplate( pSingleDocumentTemplate );
  77. CCommandLineInfo commandLineInfo;
  78. if( !ProcessShellCommand( commandLineInfo ) )
  79. return FALSE;
  80. if (!CanRunNLB())
  81. {
  82. return FALSE;
  83. }
  84. return TRUE;
  85. }
  86. void
  87. Application::OnAppAbout()
  88. {
  89. AboutDialog aboutDlg;
  90. aboutDlg.DoModal();
  91. }
  92. void
  93. ShowDisclaimer(void)
  94. /*
  95. We check the registry if we need to put up the disclaimer dialog.
  96. If we do we put it up and then afterwards check if the "don't show
  97. me" checkbox is checked. If it has, we save this fact in the registry.
  98. */
  99. {
  100. HKEY hKey;
  101. hKey = NlbMgrRegCreateKey(NULL);
  102. if (hKey != NULL)
  103. {
  104. UINT uDisableDisclaimer;
  105. uDisableDisclaimer = NlbMgrRegReadUINT(
  106. hKey,
  107. szNLBMGRREG_DISABLE_DISCLAIMER,
  108. 0 // default value.
  109. );
  110. if (!uDisableDisclaimer)
  111. {
  112. DisclaimerDialog Dlg;
  113. Dlg.DoModal();
  114. if (Dlg.dontRemindMe)
  115. {
  116. NlbMgrRegWriteUINT(
  117. hKey,
  118. szNLBMGRREG_DISABLE_DISCLAIMER,
  119. 1
  120. );
  121. }
  122. }
  123. RegCloseKey(hKey);
  124. hKey = NULL;
  125. }
  126. }
  127. BOOL CanRunNLB(void)
  128. /*
  129. Checks if NLB can run on the current machine. The main check is to make sure that there is atleast one active NIC without NLB bound.
  130. */
  131. {
  132. if (NoAdminNics())
  133. {
  134. ::MessageBox(
  135. NULL,
  136. GETRESOURCEIDSTRING( IDS_CANTRUN_NONICS_TEXT), // Contents
  137. GETRESOURCEIDSTRING( IDS_CANTRUN_NONICS_CAPTION), // caption
  138. MB_ICONSTOP | MB_OK );
  139. }
  140. else
  141. {
  142. ::ShowDisclaimer();
  143. }
  144. return TRUE;
  145. }
  146. UINT
  147. NlbMgrRegReadUINT(
  148. HKEY hKey,
  149. LPCWSTR szName,
  150. UINT Default
  151. )
  152. {
  153. LONG lRet;
  154. DWORD dwType;
  155. DWORD dwData;
  156. DWORD dwRet;
  157. dwData = sizeof(dwRet);
  158. lRet = RegQueryValueEx(
  159. hKey, // handle to key to query
  160. szName,
  161. NULL, // reserved
  162. &dwType, // address of buffer for value type
  163. (LPBYTE) &dwRet, // address of data buffer
  164. &dwData // address of data buffer size
  165. );
  166. if ( lRet != ERROR_SUCCESS
  167. || dwType != REG_DWORD
  168. || dwData != sizeof(dwData))
  169. {
  170. dwRet = (DWORD) Default;
  171. }
  172. return (UINT) dwRet;
  173. }
  174. VOID
  175. NlbMgrRegWriteUINT(
  176. HKEY hKey,
  177. LPCWSTR szName,
  178. UINT Value
  179. )
  180. {
  181. LONG lRet;
  182. lRet = RegSetValueEx(
  183. hKey, // handle to key to set value for
  184. szName,
  185. 0, // reserved
  186. REG_DWORD, // flag for value type
  187. (BYTE*) &Value,// address of value data
  188. sizeof(Value) // size of value data
  189. );
  190. if (lRet !=ERROR_SUCCESS)
  191. {
  192. // trace error
  193. }
  194. }
  195. HKEY
  196. NlbMgrRegCreateKey(
  197. LPCWSTR szSubKey
  198. )
  199. {
  200. WCHAR szKey[256];
  201. DWORD dwOptions = 0;
  202. HKEY hKey = NULL;
  203. wcscpy(szKey, szNLBMGRREG_BASE_KEY);
  204. if (szSubKey != NULL)
  205. {
  206. if (wcslen(szSubKey)>128)
  207. {
  208. // too long.
  209. goto end;
  210. }
  211. wcscat(szKey, L"\\");
  212. wcscat(szKey, szSubKey);
  213. }
  214. DWORD dwDisposition;
  215. LONG lRet;
  216. lRet = RegCreateKeyEx(
  217. HKEY_LOCAL_MACHINE, // handle to an open key
  218. szKey, // address of subkey name
  219. 0, // reserved
  220. L"class", // address of class string
  221. 0, // special options flag
  222. KEY_ALL_ACCESS, // desired security access
  223. NULL, // address of key security structure
  224. &hKey, // address of buffer for opened handle
  225. &dwDisposition // address of disposition value buffer
  226. );
  227. if (lRet != ERROR_SUCCESS)
  228. {
  229. hKey = NULL;
  230. }
  231. end:
  232. return hKey;
  233. }
  234. //
  235. // This class manages NetCfg interfaces
  236. //
  237. class AppMyNetCfg
  238. {
  239. public:
  240. AppMyNetCfg(VOID)
  241. {
  242. m_pINetCfg = NULL;
  243. m_pLock = NULL;
  244. }
  245. ~AppMyNetCfg()
  246. {
  247. ASSERT(m_pINetCfg==NULL);
  248. ASSERT(m_pLock==NULL);
  249. }
  250. WBEMSTATUS
  251. Initialize(
  252. BOOL fWriteLock
  253. );
  254. VOID
  255. Deinitialize(
  256. VOID
  257. );
  258. WBEMSTATUS
  259. GetNlbCompatibleNics(
  260. OUT LPWSTR **ppszNics,
  261. OUT UINT *pNumNics,
  262. OUT UINT *pNumBoundToNlb // OPTIONAL
  263. );
  264. WBEMSTATUS
  265. GetBindingIF(
  266. IN LPCWSTR szComponent,
  267. OUT INetCfgComponentBindings **ppIBinding
  268. );
  269. private:
  270. INetCfg *m_pINetCfg;
  271. INetCfgLock *m_pLock;
  272. }; // Class AppMyNetCfg
  273. WBEMSTATUS
  274. AppMyNetCfg::Initialize(
  275. BOOL fWriteLock
  276. )
  277. {
  278. HRESULT hr;
  279. INetCfg *pnc = NULL;
  280. INetCfgLock *pncl = NULL;
  281. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  282. BOOL fLocked = FALSE;
  283. BOOL fInitialized=FALSE;
  284. if (m_pINetCfg != NULL || m_pLock != NULL)
  285. {
  286. ASSERT(FALSE);
  287. goto end;
  288. }
  289. hr = CoCreateInstance( CLSID_CNetCfg,
  290. NULL,
  291. CLSCTX_SERVER,
  292. IID_INetCfg,
  293. (void **) &pnc);
  294. if( !SUCCEEDED( hr ) )
  295. {
  296. // failure to create instance.
  297. //TRACE_CRIT("ERROR: could not get interface to Net Config");
  298. goto end;
  299. }
  300. //
  301. // If require, get the write lock
  302. //
  303. if (fWriteLock)
  304. {
  305. WCHAR *szLockedBy = NULL;
  306. hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl );
  307. if( !SUCCEEDED( hr ) )
  308. {
  309. //TRACE_CRIT("ERROR: could not get interface to NetCfg Lock");
  310. goto end;
  311. }
  312. hr = pncl->AcquireWriteLock( 1, // One Second
  313. L"NLBManager",
  314. &szLockedBy);
  315. if( hr != S_OK )
  316. {
  317. //TRACE_CRIT("Could not get write lock. Lock held by %ws",
  318. // (szLockedBy!=NULL) ? szLockedBy : L"<null>");
  319. goto end;
  320. }
  321. }
  322. // Initializes network configuration by loading into
  323. // memory all basic networking information
  324. //
  325. hr = pnc->Initialize( NULL );
  326. if( !SUCCEEDED( hr ) )
  327. {
  328. // failure to Initialize
  329. //TRACE_CRIT("INetCfg::Initialize failure ");
  330. goto end;
  331. }
  332. Status = WBEM_NO_ERROR;
  333. end:
  334. if (FAILED(Status))
  335. {
  336. if (pncl!=NULL)
  337. {
  338. if (fLocked)
  339. {
  340. pncl->ReleaseWriteLock();
  341. }
  342. pncl->Release();
  343. pncl=NULL;
  344. }
  345. if( pnc != NULL)
  346. {
  347. if (fInitialized)
  348. {
  349. pnc->Uninitialize();
  350. }
  351. pnc->Release();
  352. pnc= NULL;
  353. }
  354. }
  355. else
  356. {
  357. m_pINetCfg = pnc;
  358. m_pLock = pncl;
  359. }
  360. return Status;
  361. }
  362. VOID
  363. AppMyNetCfg::Deinitialize(
  364. VOID
  365. )
  366. {
  367. if (m_pLock!=NULL)
  368. {
  369. m_pLock->ReleaseWriteLock();
  370. m_pLock->Release();
  371. m_pLock=NULL;
  372. }
  373. if( m_pINetCfg != NULL)
  374. {
  375. m_pINetCfg->Uninitialize();
  376. m_pINetCfg->Release();
  377. m_pINetCfg= NULL;
  378. }
  379. }
  380. LPWSTR *
  381. CfgUtilsAllocateStringArray(
  382. UINT NumStrings,
  383. UINT MaxStringLen // excluding ending NULL
  384. )
  385. /*
  386. Allocate a single chunk of memory using the new LPWSTR[] operator.
  387. The first NumStrings LPWSTR values of this operator contain an array
  388. of pointers to WCHAR strings. Each of these strings
  389. is of size (MaxStringLen+1) WCHARS.
  390. The rest of the memory contains the strings themselve.
  391. Return NULL if NumStrings==0 or on allocation failure.
  392. Each of the strings are initialized to be empty strings (first char is 0).
  393. */
  394. {
  395. LPWSTR *pStrings = NULL;
  396. UINT TotalSize = 0;
  397. if (NumStrings == 0)
  398. {
  399. goto end;
  400. }
  401. //
  402. // Note - even if MaxStringLen is 0 we will allocate space for NumStrings
  403. // pointers and NumStrings empty (first char is 0) strings.
  404. //
  405. //
  406. // Calculate space for the array of pointers to strings...
  407. //
  408. TotalSize = NumStrings*sizeof(LPWSTR);
  409. //
  410. // Calculate space for the strings themselves...
  411. // Remember to add +1 for each ending 0 character.
  412. //
  413. TotalSize += NumStrings*(MaxStringLen+1)*sizeof(WCHAR);
  414. //
  415. // Allocate space for *both* the array of pointers and the strings
  416. // in one shot -- we're doing a new of type LPWSTR[] for the whole
  417. // lot, so need to specify the size in units of LPWSTR (with an
  418. // additional +1 in case there's roundoff.
  419. //
  420. pStrings = new LPWSTR[(TotalSize/sizeof(LPWSTR))+1];
  421. if (pStrings == NULL)
  422. {
  423. goto end;
  424. }
  425. //
  426. // Make sz point to the start of the place where we'll be placing
  427. // the string data.
  428. //
  429. LPWSTR sz = (LPWSTR) (pStrings+NumStrings);
  430. for (UINT u=0; u<NumStrings; u++)
  431. {
  432. *sz=NULL;
  433. pStrings[u] = sz;
  434. sz+=(MaxStringLen+1); // +1 for ending NULL
  435. }
  436. end:
  437. return pStrings;
  438. }
  439. WBEMSTATUS
  440. AppMyNetCfg::GetNlbCompatibleNics(
  441. OUT LPWSTR **ppszNics,
  442. OUT UINT *pNumNics,
  443. OUT UINT *pNumBoundToNlb // OPTIONAL
  444. )
  445. /*
  446. Returns an array of pointers to string-version of GUIDS
  447. that represent the set of alive and healthy NICS that are
  448. suitable for NLB to bind to -- basically alive ethernet NICs.
  449. Delete ppNics using the delete WCHAR[] operator. Do not
  450. delete the individual strings.
  451. */
  452. {
  453. #define MY_GUID_LENGTH 38
  454. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  455. HRESULT hr;
  456. IEnumNetCfgComponent* pencc = NULL;
  457. INetCfgComponent *pncc = NULL;
  458. ULONG countToFetch = 1;
  459. ULONG countFetched;
  460. DWORD characteristics;
  461. UINT NumNics = 0;
  462. LPWSTR *pszNics = NULL;
  463. INetCfgComponentBindings *pINlbBinding=NULL;
  464. UINT NumNlbBoundNics = 0;
  465. typedef struct _MYNICNODE MYNICNODE;
  466. typedef struct _MYNICNODE
  467. {
  468. LPWSTR szNicGuid;
  469. MYNICNODE *pNext;
  470. } MYNICNODE;
  471. MYNICNODE *pNicNodeList = NULL;
  472. MYNICNODE *pNicNode = NULL;
  473. *ppszNics = NULL;
  474. *pNumNics = 0;
  475. if (pNumBoundToNlb != NULL)
  476. {
  477. *pNumBoundToNlb = 0;
  478. }
  479. if (m_pINetCfg == NULL)
  480. {
  481. //
  482. // This means we're not initialized
  483. //
  484. ASSERT(FALSE);
  485. goto end;
  486. }
  487. hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc );
  488. if( !SUCCEEDED( hr ) )
  489. {
  490. // failure to Enumerate net components
  491. //TRACE_CRIT("%!FUNC! Could not enum netcfg adapters");
  492. pencc = NULL;
  493. goto end;
  494. }
  495. //
  496. // Check if nlb is bound to the nlb component.
  497. //
  498. //
  499. // If we need to count of NLB-bound nics, get instance of the nlb component
  500. //
  501. if (pNumBoundToNlb != NULL)
  502. {
  503. Status = GetBindingIF(L"ms_wlbs", &pINlbBinding);
  504. if (FAILED(Status))
  505. {
  506. //TRACE_CRIT("%!FUNC! WARNING: NLB doesn't appear to be installed on this machine");
  507. pINlbBinding = NULL;
  508. }
  509. }
  510. while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK )
  511. {
  512. LPWSTR szName = NULL;
  513. hr = pncc->GetBindName( &szName );
  514. if (!SUCCEEDED(hr))
  515. {
  516. //TRACE_CRIT("%!FUNC! WARNING: couldn't get bind name for 0x%p, ignoring",
  517. // (PVOID) pncc);
  518. continue;
  519. }
  520. do // while FALSE -- just to allow breaking out
  521. {
  522. UINT Len = wcslen(szName);
  523. if (Len != MY_GUID_LENGTH)
  524. {
  525. //TRACE_CRIT("%!FUNC! WARNING: GUID %ws has unexpected length %ul",
  526. // szName, Len);
  527. break;
  528. }
  529. DWORD characteristics = 0;
  530. hr = pncc->GetCharacteristics( &characteristics );
  531. if(!SUCCEEDED(hr))
  532. {
  533. //TRACE_CRIT("%!FUNC! WARNING: couldn't get characteristics for %ws, ignoring",
  534. // szName);
  535. break;
  536. }
  537. if(characteristics & NCF_PHYSICAL)
  538. {
  539. ULONG devstat = 0;
  540. // This is a physical network card.
  541. // we are only interested in such devices
  542. // check if the nic is enabled, we are only
  543. // interested in enabled nics.
  544. //
  545. hr = pncc->GetDeviceStatus( &devstat );
  546. if(!SUCCEEDED(hr))
  547. {
  548. //TRACE_CRIT(
  549. // "%!FUNC! WARNING: couldn't get dev status for %ws, ignoring",
  550. // szName
  551. // );
  552. break;
  553. }
  554. // if any of the nics has any of the problem codes
  555. // then it cannot be used.
  556. if( devstat != CM_PROB_NOT_CONFIGURED
  557. &&
  558. devstat != CM_PROB_FAILED_START
  559. &&
  560. devstat != CM_PROB_NORMAL_CONFLICT
  561. &&
  562. devstat != CM_PROB_NEED_RESTART
  563. &&
  564. devstat != CM_PROB_REINSTALL
  565. &&
  566. devstat != CM_PROB_WILL_BE_REMOVED
  567. &&
  568. devstat != CM_PROB_DISABLED
  569. &&
  570. devstat != CM_PROB_FAILED_INSTALL
  571. &&
  572. devstat != CM_PROB_FAILED_ADD
  573. )
  574. {
  575. //
  576. // No problem with this nic and also
  577. // physical device
  578. // thus we want it.
  579. //
  580. if (pINlbBinding != NULL)
  581. {
  582. BOOL fBound = FALSE;
  583. hr = pINlbBinding->IsBoundTo(pncc);
  584. if( !SUCCEEDED( hr ) )
  585. {
  586. //TRACE_CRIT("IsBoundTo method failed for Nic %ws", szName);
  587. goto end;
  588. }
  589. if( hr == S_OK )
  590. {
  591. //TRACE_VERB("BOUND: %ws\n", szName);
  592. NumNlbBoundNics++;
  593. fBound = TRUE;
  594. }
  595. else if (hr == S_FALSE )
  596. {
  597. //TRACE_VERB("NOT BOUND: %ws\n", szName);
  598. fBound = FALSE;
  599. }
  600. }
  601. // We allocate a little node to keep this string
  602. // temporarily and add it to our list of nodes.
  603. //
  604. pNicNode = new MYNICNODE;
  605. if (pNicNode == NULL)
  606. {
  607. Status = WBEM_E_OUT_OF_MEMORY;
  608. goto end;
  609. }
  610. ZeroMemory(pNicNode, sizeof(*pNicNode));
  611. pNicNode->szNicGuid = szName;
  612. szName = NULL; // so we don't delete inside the lopp.
  613. pNicNode->pNext = pNicNodeList;
  614. pNicNodeList = pNicNode;
  615. NumNics++;
  616. }
  617. else
  618. {
  619. // There is a problem...
  620. //TRACE_CRIT(
  621. // "%!FUNC! WARNING: Skipping %ws because DeviceStatus=0x%08lx",
  622. // szName, devstat
  623. // );
  624. break;
  625. }
  626. }
  627. else
  628. {
  629. //TRACE_VERB("%!FUNC! Ignoring non-physical device %ws", szName);
  630. }
  631. } while (FALSE);
  632. if (szName != NULL)
  633. {
  634. CoTaskMemFree( szName );
  635. }
  636. pncc->Release();
  637. pncc=NULL;
  638. }
  639. if (pINlbBinding!=NULL)
  640. {
  641. pINlbBinding->Release();
  642. pINlbBinding = NULL;
  643. }
  644. if (NumNics==0)
  645. {
  646. Status = WBEM_NO_ERROR;
  647. goto end;
  648. }
  649. //
  650. // Now let's allocate space for all the nic strings and:w
  651. // copy them over..
  652. //
  653. #define MY_GUID_LENGTH 38
  654. pszNics = CfgUtilsAllocateStringArray(NumNics, MY_GUID_LENGTH);
  655. if (pszNics == NULL)
  656. {
  657. Status = WBEM_E_OUT_OF_MEMORY;
  658. goto end;
  659. }
  660. pNicNode= pNicNodeList;
  661. for (UINT u=0; u<NumNics; u++, pNicNode=pNicNode->pNext)
  662. {
  663. ASSERT(pNicNode != NULL); // because we just counted NumNics of em.
  664. UINT Len = wcslen(pNicNode->szNicGuid);
  665. if (Len != MY_GUID_LENGTH)
  666. {
  667. //
  668. // We should never get here beause we checked the length earlier.
  669. //
  670. //TRACE_CRIT("%!FUNC! ERROR: GUID %ws has unexpected length %ul",
  671. // pNicNode->szNicGuid, Len);
  672. ASSERT(FALSE);
  673. Status = WBEM_E_CRITICAL_ERROR;
  674. goto end;
  675. }
  676. CopyMemory(
  677. pszNics[u],
  678. pNicNode->szNicGuid,
  679. (MY_GUID_LENGTH+1)*sizeof(WCHAR));
  680. ASSERT(pszNics[u][MY_GUID_LENGTH]==0);
  681. }
  682. Status = WBEM_NO_ERROR;
  683. end:
  684. //
  685. // Now release the temporarly allocated memory.
  686. //
  687. pNicNode= pNicNodeList;
  688. while (pNicNode!=NULL)
  689. {
  690. MYNICNODE *pTmp = pNicNode->pNext;
  691. CoTaskMemFree(pNicNode->szNicGuid);
  692. pNicNode->szNicGuid = NULL;
  693. delete pNicNode;
  694. pNicNode = pTmp;
  695. }
  696. if (FAILED(Status))
  697. {
  698. // TRACE_CRIT("%!FUNC! fails with status 0x%08lx", (UINT) Status);
  699. NumNics = 0;
  700. if (pszNics!=NULL)
  701. {
  702. delete pszNics;
  703. pszNics = NULL;
  704. }
  705. }
  706. else
  707. {
  708. if (pNumBoundToNlb != NULL)
  709. {
  710. *pNumBoundToNlb = NumNlbBoundNics;
  711. }
  712. *ppszNics = pszNics;
  713. *pNumNics = NumNics;
  714. }
  715. if (pencc != NULL)
  716. {
  717. pencc->Release();
  718. }
  719. return Status;
  720. }
  721. WBEMSTATUS
  722. AppMyNetCfg::GetBindingIF(
  723. IN LPCWSTR szComponent,
  724. OUT INetCfgComponentBindings **ppIBinding
  725. )
  726. {
  727. WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
  728. INetCfgComponent *pncc = NULL;
  729. INetCfgComponentBindings *pnccb = NULL;
  730. HRESULT hr;
  731. if (m_pINetCfg == NULL)
  732. {
  733. //
  734. // This means we're not initialized
  735. //
  736. ASSERT(FALSE);
  737. goto end;
  738. }
  739. hr = m_pINetCfg->FindComponent(szComponent, &pncc);
  740. if (FAILED(hr))
  741. {
  742. // TRACE_CRIT("Error checking if component %ws does not exist\n", szComponent);
  743. pncc = NULL;
  744. goto end;
  745. }
  746. else if (hr == S_FALSE)
  747. {
  748. Status = WBEM_E_NOT_FOUND;
  749. // TRACE_CRIT("Component %ws does not exist\n", szComponent);
  750. goto end;
  751. }
  752. hr = pncc->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb );
  753. if( !SUCCEEDED( hr ) )
  754. {
  755. // TRACE_CRIT("INetCfgComponent::QueryInterface failed ");
  756. pnccb = NULL;
  757. goto end;
  758. }
  759. Status = WBEM_NO_ERROR;
  760. end:
  761. if (pncc)
  762. {
  763. pncc->Release();
  764. pncc=NULL;
  765. }
  766. *ppIBinding = pnccb;
  767. return Status;
  768. }
  769. WBEMSTATUS
  770. CfgUtilsGetNlbCompatibleNics(
  771. OUT LPWSTR **ppszNics,
  772. OUT UINT *pNumNics,
  773. OUT UINT *pNumBoundToNlb // OPTIONAL
  774. )
  775. {
  776. WBEMSTATUS Status = WBEM_NO_ERROR;
  777. BOOL fNetCfgInitialized = FALSE;
  778. AppMyNetCfg NetCfg;
  779. BOOL fBound = FALSE;
  780. //
  781. // Get and initialize interface to netcfg
  782. //
  783. Status = NetCfg.Initialize(FALSE); // TRUE == get write lock.
  784. if (FAILED(Status))
  785. {
  786. goto end;
  787. }
  788. fNetCfgInitialized = TRUE;
  789. //
  790. //
  791. //
  792. Status = NetCfg.GetNlbCompatibleNics(
  793. ppszNics,
  794. pNumNics,
  795. pNumBoundToNlb // OPTIONAL
  796. );
  797. end:
  798. if (fNetCfgInitialized)
  799. {
  800. NetCfg.Deinitialize();
  801. }
  802. return Status;
  803. }
  804. BOOL NoAdminNics(void)
  805. /*
  806. Return TRUE IFF all NICs on this machine are bound to NLB.
  807. */
  808. {
  809. LPWSTR *pszNics = NULL;
  810. OUT UINT NumNics = 0;
  811. OUT UINT NumBoundToNlb = 0;
  812. WBEMSTATUS Status = WBEM_NO_ERROR;
  813. BOOL fNetCfgInitialized = FALSE;
  814. AppMyNetCfg NetCfg;
  815. BOOL fRet = FALSE;
  816. //
  817. // Get and initialize interface to netcfg
  818. //
  819. Status = NetCfg.Initialize(FALSE); // TRUE == get write lock.
  820. if (FAILED(Status))
  821. {
  822. goto end;
  823. }
  824. fNetCfgInitialized = TRUE;
  825. //
  826. // Get the total list of enabled nics and the list of nics
  827. // bound to NLB. If there are non-zero enabled nics and all are
  828. // bound to NLB, we return TRUE.
  829. //
  830. Status = NetCfg.GetNlbCompatibleNics(
  831. &pszNics,
  832. &NumNics,
  833. &NumBoundToNlb
  834. );
  835. if (!FAILED(Status))
  836. {
  837. fRet = NumNics && (NumNics == NumBoundToNlb);
  838. if (NumNics)
  839. {
  840. delete pszNics;
  841. pszNics = NULL;
  842. }
  843. }
  844. end:
  845. if (fNetCfgInitialized)
  846. {
  847. NetCfg.Deinitialize();
  848. }
  849. return fRet;
  850. }