// Copyright (c) Microsoft. All rights reserved. // // This is unpublished source code of Microsoft. // The copyright notice above does not evidence any // actual or intended publication of such source code. // OneLiner : Implementation of NICCard // DevUnit : wlbstest // Author : Murtaza Hakim // History: // -------- // // Revised by : mhakim // Date : 02-16-01 // Reason : Added code to find friendly name of nic. // include files #include "NICCard.h" #include #include #include using namespace std; // constructor NICCard::NICCard( IdentifierType type, wstring id ) : pnc( NULL ), nameType( type ), nicName( id ), status( NICCard_SUCCESS ) { HRESULT hr; // initialize com. hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED ); if( !SUCCEEDED( hr ) ) { // failure to initialize com cout << "CoInitializeEx failure " << endl; // status = COM_FAILURE; // return; } // get INetCfg com interface. hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_SERVER, IID_INetCfg, (void **) &pnc ); if( !SUCCEEDED( hr ) ) { // failure to create instance. cout << "CoCreateInstance failure" << endl; status = COM_FAILURE; return; } } // destructor NICCard::~NICCard() { // release resources. HRESULT hr; if( pnc ) { hr = pnc->Release(); pnc = 0; } // uninitialize. CoUninitialize(); } //+---------------------------------------------------------------------------- // // Function: NICCard::isBoundTo // // Description: whether a component is bound to the adapter // // Arguments: wstring component - component id, e.g. "ms_wlbs" // // Returns: NICCard::NICCard_Error - // // History: Murtaza intitial code // fengsun Created Header 12/21/00 // //+---------------------------------------------------------------------------- NICCard::NICCard_Error NICCard::isBoundTo( wstring component ) { HRESULT hr; NICCard_Error err; INetCfgComponent *pnccNic = NULL; INetCfgComponent *pnccComponent = NULL; INetCfgComponentBindings *pnccb = NULL; // check creation status. // if not success something went wrong during construction // and this object cannot be used. // if( status != NICCard_SUCCESS ) { err = status; goto cleanup; } // Initializes network configuration by loading into // memory all basic networking information // hr = pnc->Initialize( NULL ); if( !SUCCEEDED( hr ) ) { // failure to Initialize cout << "INetCfg::Initialize failure " << endl; err = COM_FAILURE; goto cleanup; } // check if physical nic object of nameType, and nicName exists. // err = findNIC( nameType, nicName, &pnccNic ); if( err != NICCard_SUCCESS ) { // nic specified does not exist. wprintf(L"nic specified as %s does not exist\n", nicName.c_str() ); // err value set by findNic goto cleanup; } if (FAILED(hr = pnc->FindComponent(component.c_str(), &pnccComponent))) { // not protocol, service or client. No such component exists. wprintf(L"component specified as %s does not exist\n", component.c_str() ); err = NO_SUCH_COMPONENT; goto cleanup; } // check if binding exists. // hr = pnccComponent->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::QueryInterface failed " << endl; err = COM_FAILURE; goto cleanup; } hr = pnccb->IsBoundTo( pnccNic ); if( hr == S_OK ) { err = BOUND; } else if( hr == S_FALSE ) { err = UNBOUND; } else { err = COM_FAILURE; } goto cleanup; // free up com resources. cleanup: if( pnccb ) { pnccb->Release(); pnccb = 0; } if( pnccComponent ) { pnccComponent->Release(); pnccComponent = 0; } if( pnccNic ) { pnccNic->Release(); pnccNic = 0; } pnc->Uninitialize(); return err; } //+---------------------------------------------------------------------------- // // Function: NICCard::bind // // Description: bind a component to the adapter // // Arguments: wstring component - component id, e.g. "ms_wlbs" // // Returns: NICCard::NICCard_Error - // // History: Murtaza intitial code // fengsun Created Header 12/21/00 // //+---------------------------------------------------------------------------- NICCard::NICCard_Error NICCard::bind( wstring component ) { NICCard_Error err; err = isBoundTo( component ); if( err == UNBOUND ) { return toggleState( component ); } else if( err == BOUND ) { return NICCard_SUCCESS; } else { return err; } } //+---------------------------------------------------------------------------- // // Function: NICCard::unbind // // Description: unbind a component to the adapter // // Arguments: wstring component - component id, e.g. "ms_wlbs" // // Returns: NICCard::NICCard_Error - // // History: Murtaza intitial code // fengsun Created Header 12/21/00 // //+---------------------------------------------------------------------------- NICCard::NICCard_Error NICCard::unbind( wstring component ) { NICCard_Error err; err = isBoundTo( component ); if( err == BOUND ) { return toggleState( component ); } else if( err == UNBOUND ) { return NICCard_SUCCESS; } else { return err; } } // private // returns true if found, else false. NICCard::NICCard_Error NICCard::findNIC( IdentifierType type, wstring nicName, INetCfgComponent** ppnccNic ) { HRESULT hr; IEnumNetCfgComponent* pencc; INetCfgComponent* pncc; ULONG countToFetch = 1; ULONG countFetched; DWORD characteristics; wstring name; LPWSTR pName; hr = pnc->EnumComponents( &GUID_DEVCLASS_NET, &pencc ); if( !SUCCEEDED( hr ) ) { // failure to Enumerate net components cout << "INetCfg::EnumComponents failure " << endl; return COM_FAILURE; } while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK ) { // here we have been given guid. if( type == guid ) { hr = pncc->GetBindName( &pName ); } else { hr = pncc->GetDisplayName( &pName ); } name = pName; CoTaskMemFree( pName ); if( name == nicName ) { *ppnccNic = pncc; if( pencc ) { pencc->Release(); pencc = 0; } return NICCard_SUCCESS; } pncc->Release(); } if( pencc ) { pencc->Release(); pencc = 0; } *ppnccNic = NULL; return NO_SUCH_NIC; } //+---------------------------------------------------------------------------- // // Function: NICCard::toggleState // // Description: toggle a component binding state to the adapter // // Arguments: wstring component - component id, e.g. "ms_wlbs" // // Returns: NICCard::NICCard_Error - // // History: Murtaza intitial code // fengsun Created Header 12/21/00 // //+---------------------------------------------------------------------------- NICCard::NICCard_Error NICCard::toggleState( wstring component ) { HRESULT hr; NICCard_Error err; INetCfgComponent *pnccNic = NULL; INetCfgComponent *pnccComponent = NULL; INetCfgComponentBindings *pnccb = NULL; INetCfgLock *pncl = NULL; LPWSTR presentLockHolder = new wchar_t[1000]; // check creation status. // if not success something went wrong during construction // and this object cannot be used. // if( status != NICCard_SUCCESS ) { err = status; goto cleanup; } // as this operation can make modifications we require a lock. // thus get lock. // hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl ); if( !SUCCEEDED( hr ) ) { cout << "INetCfg QueryInterface for IID_INetCfgLock failed " << endl; err = COM_FAILURE; goto cleanup; } hr = pncl->AcquireWriteLock( TIME_TO_WAIT, L"NLBManager", &presentLockHolder ); if( hr != S_OK ) { cout << "INetCfgLock::AcquireWriteLock failure is " << hr << endl; err = COM_FAILURE; goto cleanup; } // Initializes network configuration by loading into // memory all basic networking information // hr = pnc->Initialize( NULL ); if( !SUCCEEDED( hr ) ) { // failure to Initialize cout << "INetCfg::Initialize failed with " << hr << endl; err = COM_FAILURE; goto cleanup; } // check if physical nic object of nameType, and nicName exists. // err = findNIC( nameType, nicName, &pnccNic ); if( err != NICCard_SUCCESS ) { // nic specified does not exist. wprintf(L"nic specified as %s does not exist\n", nicName.c_str() ); goto cleanup; } if (FAILED(hr = pnc->FindComponent(component.c_str(), &pnccComponent))) { // not protocol, service or client. No such component exists. wprintf(L"component specified as %s does not exist\n", component.c_str() ); err = NO_SUCH_COMPONENT; goto cleanup; } // check if binding exists. // hr = pnccComponent->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::QueryInterface failed " << endl; err = COM_FAILURE; goto cleanup; } hr = pnccb->IsBoundTo( pnccNic ); if( hr == S_OK ) { hr = pnccb->UnbindFrom( pnccNic ); if( !SUCCEEDED( hr ) ) { if( hr == NETCFG_E_NO_WRITE_LOCK ) cout << "Unable to obtain write lock. Please verify properties page not already open" << endl; else cout << "INetCfgBindings::UnbindFrom failed with " << hr << endl; err = COM_FAILURE; } else { // apply the binding change made. hr = pnc->Apply(); if( !SUCCEEDED( hr ) ) { cout << "INetCfg::Apply failed with " << hr << endl; err = COM_FAILURE; } else { err = NICCard_SUCCESS; } } } else if( hr == S_FALSE ) { hr = pnccb->BindTo( pnccNic ); if( !SUCCEEDED( hr ) ) { if( hr == NETCFG_E_NO_WRITE_LOCK ) cout << "Unable to obtain write lock. Please verify properties page not already open" << endl; else cout << "INetCfgBindings::BindTo failed with " << hr << endl; err = COM_FAILURE; } else { // apply the binding change made. hr = pnc->Apply(); if( !SUCCEEDED( hr ) ) { cout << "INetCfg::Apply failed with " << hr << endl; err = COM_FAILURE; } else { err = NICCard_SUCCESS; } } } else { cout << "INetCfgComponentBindings::IsBoundTo failed with " << hr << endl; err = COM_FAILURE; } goto cleanup; // free up com resources. cleanup: if( pnccb ) { pnccb->Release(); pnccb = 0; } if( pnccComponent ) { pnccComponent->Release(); pnccComponent = 0; } if( pnccNic ) { pnccNic->Release(); pnccNic = 0; } if( pnc ) pnc->Uninitialize(); if( pncl ) { pncl->ReleaseWriteLock(); pncl->Release(); pncl = 0; } delete [] presentLockHolder; return err; } // getNics // NICCard::NICCard_Error NICCard::getNics( vector* nicList ) { HRESULT hr; INetCfg *pncStatic = 0; IEnumNetCfgComponent *pencc = 0; INetCfgComponent *pncc = 0; wstring name; LPWSTR pName; NICCard_Error err; ULONG countToFetch = 1; ULONG countFetched; ULONG status; Info info; DWORD characteristics = 0; // initialize com. hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED ); if( !SUCCEEDED( hr ) ) { // failure to initialize com cout << "CoInitializeEx failure " << endl; // err = COM_FAILURE; // goto cleanup; } // get INetCfg com interface. hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_SERVER, IID_INetCfg, (void **) &pncStatic ); if( !SUCCEEDED( hr ) ) { // failure to create instance. cout << "CoCreateInstance failure" << endl; err = COM_FAILURE; goto cleanup; } // Initializes network configuration by loading into // memory all basic networking information // hr = pncStatic->Initialize( NULL ); if( !SUCCEEDED( hr ) ) { // failure to Initialize cout << "INetCfg::Initialize failure " << endl; err = COM_FAILURE; goto cleanup; } hr = pncStatic->EnumComponents( &GUID_DEVCLASS_NET, &pencc ); if( !SUCCEEDED( hr ) ) { // failure to Enumerate net components cout << "INetCfg::EnumComponents failure " << endl; err = COM_FAILURE; goto cleanup; } while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK ) { hr = pncc->GetBindName( &pName ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::GetBindName failure " << endl; err = COM_FAILURE; goto cleanup; } info.guid = pName; CoTaskMemFree( pName ); hr = pncc->GetDisplayName( &pName ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::GetDisplayName failure " << endl; err = COM_FAILURE; goto cleanup; } info.fullName = pName; CoTaskMemFree( pName ); hr = pncc->GetCharacteristics( &characteristics ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::GetCharacteristics failure " << endl; err = COM_FAILURE; goto cleanup; } GetFriendlyNICName( info.guid, info.friendlyName ); if( characteristics & NCF_PHYSICAL ) { // this is a physical network card. // we are only interested in such devices // check if the nic is enabled, we are only // interested in enabled nics. // hr = pncc->GetDeviceStatus( &status ); if( !SUCCEEDED( hr ) ) { cout << "INetCfgComponent::GetDeviceStatus failure " << endl; err = COM_FAILURE; goto cleanup; } // if any of the nics has any of the problem codes // then it cannot be used. if( status != CM_PROB_NOT_CONFIGURED && status != CM_PROB_FAILED_START && status != CM_PROB_NORMAL_CONFLICT && status != CM_PROB_NEED_RESTART && status != CM_PROB_REINSTALL && status != CM_PROB_WILL_BE_REMOVED && status != CM_PROB_DISABLED && status != CM_PROB_FAILED_INSTALL && status != CM_PROB_FAILED_ADD ) { // no problem with this nic and also // physical device // thus we want it. nicList->push_back( info ); } } if( pncc ) { pncc->Release(); pncc = 0; } characteristics = 0; countToFetch = 1; } err = NICCard_SUCCESS; cleanup: if( pncStatic ) { pncStatic->Uninitialize(); pncStatic->Release(); pncStatic = 0; } if( pencc ) { pencc->Release(); pencc = 0; } if( pncc ) { pncc->Release(); pncc = 0; } return err; } NICCard::NICCard_Error NICCard::isNetCfgAvailable() { NICCard_Error err; HRESULT hr; INetCfgLock *pncl = NULL; LPWSTR presentLockHolder = new wchar_t[1000]; hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl ); if( !SUCCEEDED( hr ) ) { cout << "INetCfg QueryInterface for IID_INetCfgLock failed " << endl; err = COM_FAILURE; goto cleanup; } hr = pncl->AcquireWriteLock( TIME_TO_WAIT, L"NLBManager", &presentLockHolder ); if( hr != S_OK ) { cout << "INetCfgLock::AcquireWriteLock failure is " << hr << endl; err = COM_FAILURE; goto cleanup; } err = NICCard_SUCCESS; cleanup: if( pncl ) { pncl->ReleaseWriteLock(); pncl->Release(); pncl = 0; } delete [] presentLockHolder; return err; } // code to find friendly name of nic. // this code is modified for wstring, but // otherwise is courtesy of hengz. // int NICCard::GetFriendlyNICName(const wstring& guid, wstring& name ) { // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network HKEY hregkey=NULL, hkOpenKey=NULL, hkQueryKey=NULL; DWORD dwDataBuffer=200; DWORD dwValueType=REG_SZ; wchar_t data[200], path[200], adapters[200]; wchar_t *pHost=NULL; int num=0, ret; FILETIME time; //make connection to the machine's registry if ((ret=RegConnectRegistry(pHost, HKEY_LOCAL_MACHINE, &hregkey)) != ERROR_SUCCESS) { // TRACE( MTrace::SEVERE_ERROR, L"(RegConnectRegistry) failure" ); return (-1); } //look for the GUID if( (ret=RegOpenKeyEx(hregkey, L"SYSTEM\\CurrentControlSet\\Control\\Network", 0, KEY_READ, &hkOpenKey)) != ERROR_SUCCESS ) { RegCloseKey(hregkey); // TRACE( MTrace::SEVERE_ERROR, L"(RegOpenKeyEx) failed to open HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network" ); return (-1); } while (1) { adapters[0]=L'\0'; dwDataBuffer=200; if( ((ret=RegEnumKeyEx(hkOpenKey, num, adapters, &dwDataBuffer, NULL,NULL,NULL, &time)) != ERROR_SUCCESS) && (ret!=ERROR_MORE_DATA) ) { if (ret==ERROR_NO_MORE_ITEMS) { // TRACE(MTrace::SEVERE_ERROR,L"(RegEnumKeyEx): failed to find network adapters in HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network"); } else { // TRACE(MTrace::SEVERE_ERROR,L"(RegEnumKeyEx): fail to enum HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network" ); } RegCloseKey(hkOpenKey); RegCloseKey(hregkey); return (-1); } //open the items one by one swprintf(path, L"SYSTEM\\CurrentControlSet\\Control\\Network\\%s", adapters); if( (ret=RegOpenKeyEx(hregkey, path, 0, KEY_READ, &hkQueryKey)) != ERROR_SUCCESS ) { num++; continue; } dwDataBuffer=200; data[0]=L'\0'; if((ret=RegQueryValueEx(hkQueryKey, L"", 0, &dwValueType, (LPBYTE)data, &dwDataBuffer)) != ERROR_SUCCESS) { num++; continue; } RegCloseKey(hkQueryKey); num++; if (wcscmp(L"Network Adapters", data)==0) break; } RegCloseKey(hkOpenKey); //found the guid now //look for friendly nic name swprintf(path, L"SYSTEM\\CurrentControlSet\\Control\\Network\\%s\\%s\\Connection", adapters, guid.c_str() ); if( (ret=RegOpenKeyEx(hregkey, path, 0, KEY_READ, &hkOpenKey)) != ERROR_SUCCESS ) { RegCloseKey(hregkey); // TRACE(MTrace::SEVERE_ERROR, L"(RegOpenKeyEx) fail to open " + wstring( path ) ); return (-1); } dwDataBuffer=200; data[0]=L'\0'; if((ret=RegQueryValueEx(hkOpenKey, L"Name", 0, &dwValueType, (LPBYTE)data, &dwDataBuffer)) != ERROR_SUCCESS) { // TRACE(MTrace::SEVERE_ERROR, L"(RegQueryValueEx) fail to query name " + wstring (path ) ); RegCloseKey(hkOpenKey); RegCloseKey(hregkey); return (-1); } RegCloseKey(hkOpenKey); RegCloseKey(hregkey); name = data; return 0; }