|
|
//***************************************************************************
//
// CFGUTILS.CPP
//
// Module: WMI Framework Instance provider
//
// Purpose: Low-level utilities to configure NICs -- bind/unbind,
// get/set IP address lists, and get/set NLB cluster params.
//
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
//
// History:
//
// 04/05/01 JosephJ Created
//
//***************************************************************************
#include "private.h"
#include <netcfgx.h>
#include <devguid.h>
#include <cfg.h>
#include "..\..\..\inc\wlbsiocl.h"
#include "..\..\..\api\control.h"
#include "cfgutils.tmh"
//
// This magic has the side effect defining "smart pointers"
// IWbemServicesPtr
// IWbemLocatorPtr
// IWbemClassObjectPtr
// IEnumWbemClassObjectPtr
// IWbemCallResultPtr
// IWbemStatusCodeTextPtr
//
// These types automatically call the COM Release function when the
// objects go out of scope.
//
_COM_SMARTPTR_TYPEDEF(IWbemServices, __uuidof(IWbemServices)); _COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator)); _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject)); _COM_SMARTPTR_TYPEDEF(IWbemCallResult, __uuidof(IWbemCallResult)); _COM_SMARTPTR_TYPEDEF(IWbemStatusCodeText, __uuidof(IWbemStatusCodeText));
WBEMSTATUS CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj( IN IWbemClassObjectPtr spObj, // smart pointer
OUT IWbemClassObjectPtr &spAdapterObj // smart pointer, by reference
);
WBEMSTATUS get_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT LPWSTR *ppStringValue );
WBEMSTATUS get_nic_instance( IN IWbemServicesPtr spWbemServiceIF, IN LPCWSTR szNicGuid, OUT IWbemClassObjectPtr &sprefObj );
WBEMSTATUS get_multi_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
OUT UINT *pNumItems, OUT LPCWSTR *ppStringValue );
WBEMSTATUS set_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN LPCWSTR szValue );
WBEMSTATUS set_multi_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
IN UINT NumItems, IN LPCWSTR pStringValue );
//
// This locally-defined class implements interfaces to WMI, NetConfig,
// and low-level NLB APIs.
//
class CfgUtils {
public: //
// Initialization function -- call before using any other functions
//
WBEMSTATUS Initialize( VOID );
//
// Deinitialization function -- call after using any other functions
//
VOID Deinitialize( VOID );
//
// Constructor and distructor.
//
CfgUtils(VOID) { //
// WARNING: We do a blanked zero memory initialization of our entire
// structure. Any other initialization should go into the
// Initialize() function.
//
ZeroMemory(this, sizeof(*this));
InitializeCriticalSection(&m_Crit); }
~CfgUtils() { DeleteCriticalSection(&m_Crit); }
//
// Check if we're initialized
//
BOOL IsInitalized(VOID) { return m_ComInitialized && m_WmiInitialized && m_NLBApisInitialized; }
IWbemStatusCodeTextPtr m_spWbemStatusIF; // Smart pointer
IWbemServicesPtr m_spWbemServiceIF; // Smart pointer
CWlbsControl *m_pWlbsControl;
WBEMSTATUS GetClusterFromGuid( IN LPCWSTR szGuid, OUT CWlbsCluster **pCluster );
private:
//
// A single lock serialzes all access.
// Use mfn_Lock and mfn_Unlock.
//
CRITICAL_SECTION m_Crit;
BOOL m_ComInitialized; BOOL m_WmiInitialized; BOOL m_NLBApisInitialized;
VOID mfn_Lock( VOID ) { EnterCriticalSection(&m_Crit); }
VOID mfn_Unlock( VOID ) { LeaveCriticalSection(&m_Crit); }
};
//
// This class manages NetCfg interfaces
//
class MyNetCfg {
public:
MyNetCfg(VOID) { m_pINetCfg = NULL; m_pLock = NULL; }
~MyNetCfg() { ASSERT(m_pINetCfg==NULL); ASSERT(m_pLock==NULL); }
WBEMSTATUS Initialize( BOOL fWriteLock );
VOID Deinitialize( VOID );
WBEMSTATUS GetNlbCompatibleNics( OUT LPWSTR **ppszNics, OUT UINT *pNumNics, OUT UINT *pNumBoundToNlb // OPTIONAL
);
WBEMSTATUS GetNicIF( IN LPCWSTR szNicGuid, OUT INetCfgComponent **ppINic );
WBEMSTATUS GetBindingIF( IN LPCWSTR szComponent, OUT INetCfgComponentBindings **ppIBinding );
typedef enum { NOOP, BIND, UNBIND
} UPDATE_OP;
WBEMSTATUS UpdateBindingState( IN LPCWSTR szNic, IN LPCWSTR szComponent, IN UPDATE_OP Op, OUT BOOL *pfBound );
private:
INetCfg *m_pINetCfg; INetCfgLock *m_pLock;
}; // Class MyNetCfg
//
// We keep a single global instance of this class around currently...
//
CfgUtils g_CfgUtils;
WBEMSTATUS CfgUtilInitialize(VOID) { return g_CfgUtils.Initialize(); }
VOID CfgUtilDeitialize(VOID) { return g_CfgUtils.Deinitialize(); }
WBEMSTATUS CfgUtils::Initialize( VOID ) { WBEMSTATUS Status = WBEM_E_INITIALIZATION_FAILURE; HRESULT hr; TRACE_INFO(L"-> CfgUtils::Initialize");
mfn_Lock();
//
// Initialize COM
//
{ HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED); if ( FAILED(hr) ) { TRACE_CRIT(L"CfgUtils: Failed to initialize COM library (hr=0x%08lx)", hr); goto end; } m_ComInitialized = TRUE; }
//
// WMI Initialization
//
{ IWbemLocatorPtr spWbemLocatorIF = NULL; // Smart pointer
//
// Get error text generator interface
//
SCODE sc = CoCreateInstance( CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID *) &m_spWbemStatusIF ); if( sc != S_OK ) { ASSERT(m_spWbemStatusIF == NULL); // smart pointer
TRACE_CRIT(L"CfgUtils: CoCreateInstance IWbemStatusCodeText failure\n"); goto end; } TRACE_INFO(L"CfgUtils: m_spIWbemStatusIF=0x%p\n", (PVOID) m_spWbemStatusIF);
//
// Get "locator" interface
//
hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &spWbemLocatorIF ); if (FAILED(hr)) { ASSERT(spWbemLocatorIF == NULL); // smart pointer
TRACE_CRIT(L"CoCreateInstance IWebmLocator failed 0x%08lx", (UINT)hr); goto end; }
//
// Get interface to provider for NetworkAdapter class objects
// on the local machine
//
_bstr_t serverPath = L"root\\cimv2"; hr = spWbemLocatorIF->ConnectServer( serverPath, NULL, // strUser,
NULL, // strPassword,
NULL, 0, NULL, NULL, &m_spWbemServiceIF ); if (FAILED(hr)) { ASSERT(m_spWbemServiceIF == NULL); // smart pointer
TRACE_CRIT(L"ConnectServer to cimv2 failed 0x%08lx", (UINT)hr); goto end; } TRACE_INFO(L"CfgUtils: m_spIWbemServiceIF=0x%p\n", (PVOID) m_spWbemServiceIF);
hr = CoSetProxyBlanket( m_spWbemServiceIF, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
COLE_DEFAULT_PRINCIPAL, // NULL,
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, COLE_DEFAULT_AUTHINFO, // NULL,
EOAC_DEFAULT // EOAC_NONE
); if (FAILED(hr)) { TRACE_INFO(L"Error 0x%08lx setting proxy blanket", (UINT) hr); goto end; }
//
// Release locator interface.
//
// <NO need to do this explicitly, because this is a smart pointer>
//
spWbemLocatorIF = NULL; m_WmiInitialized = TRUE; }
//
// Netconfig Initialization
//
{ // Nothing to do here...
}
//
// WLBS API Initialization
//
{ CWlbsControl *pWlbsControl = NULL; pWlbsControl = new CWlbsControl;
if (pWlbsControl == NULL) { TRACE_CRIT("Could not initialize wlbs control!"); goto end; } DWORD dwRet = pWlbsControl->Initialize();
if (dwRet == WLBS_INIT_ERROR) { TRACE_CRIT("Error initializing WLBS Control!"); delete pWlbsControl; pWlbsControl = NULL; goto end; } else { TRACE_INFO("WlbsControl (0x%p) Initialize returns 0x%08lx", (PVOID) pWlbsControl, dwRet); }
m_pWlbsControl = pWlbsControl; m_NLBApisInitialized = TRUE;
}
Status = WBEM_NO_ERROR;
end:
mfn_Unlock();
if (FAILED(Status)) { TRACE_CRIT("CfgUtil -- FAILING INITIALIZATION! Status=0x%08lx", (UINT) Status); CfgUtils::Deinitialize(); }
TRACE_INFO(L"<- CfgUtils::Initialize(Status=0x%08lx)", (UINT) Status);
return Status; }
VOID CfgUtils::Deinitialize( VOID ) //
// NOTE: can be called in the context of a failed initialization.
//
{ TRACE_INFO(L"-> CfgUtils::Deinitialize");
mfn_Lock();
//
// De-initialize WLBS API
//
if (m_NLBApisInitialized) { delete m_pWlbsControl; m_pWlbsControl = NULL; m_NLBApisInitialized = FALSE; }
//
// Deinitialize Netconfig
//
//
// Deinitialize WMI
//
{ //
// Release interface to NetworkAdapter provider
//
if (m_spWbemStatusIF!= NULL) { // Smart pointer.
m_spWbemStatusIF= NULL; }
if (m_spWbemServiceIF!= NULL) { // Smart pointer.
m_spWbemServiceIF= NULL; }
m_WmiInitialized = FALSE; }
//
// Deinitialize COM.
//
if (m_ComInitialized) { TRACE_CRIT(L"CfgUtils: Deinitializing COM"); CoUninitialize(); m_ComInitialized = FALSE; }
mfn_Unlock();
TRACE_INFO(L"<- CfgUtils::Deinitialize"); }
WBEMSTATUS CfgUtils::GetClusterFromGuid( IN LPCWSTR szGuid, OUT CWlbsCluster **ppCluster ) { GUID Guid; WBEMSTATUS Status = WBEM_NO_ERROR; CWlbsCluster *pCluster = NULL; GUID AdapterGuid; HRESULT hr;
hr = CLSIDFromString((LPWSTR)szGuid, &Guid); if (FAILED(hr)) { TRACE_CRIT( "CWlbsControl::Initialize failed at CLSIDFromString %ws", szGuid ); Status = WBEM_E_INVALID_PARAMETER; goto end; }
mfn_Lock(); // TODO: This is not really that effective because we still
// refer to pCluster outside this function.
g_CfgUtils.m_pWlbsControl->ReInitialize(); pCluster = m_pWlbsControl->GetClusterFromAdapter(Guid); mfn_Unlock();
if (pCluster == NULL) { TRACE_CRIT("ERROR: Couldn't find cluster with Nic GUID %ws", szGuid); Status = WBEM_E_NOT_FOUND; goto end; }
Status = WBEM_NO_ERROR;
end:
*ppCluster = pCluster;
return Status; }
//
// Gets the list of statically-bound IP addresses for the NIC.
// Sets *pNumIpAddresses to 0 if DHCP
//
WBEMSTATUS CfgUtilGetIpAddressesAndFriendlyName( IN LPCWSTR szNic, OUT UINT *pNumIpAddresses, OUT NLB_IP_ADDRESS_INFO **ppIpInfo, // Free using c++ delete operator.
OUT LPWSTR *pszFriendlyName // Optional, Free using c++ delete
) { WBEMSTATUS Status = WBEM_NO_ERROR; IWbemClassObjectPtr spObj = NULL; // smart pointer
HRESULT hr; LPCWSTR pAddrs = NULL; LPCWSTR pSubnets = NULL; UINT AddrCount = 0; NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
*pNumIpAddresses = NULL; *ppIpInfo = NULL; if (pszFriendlyName!=NULL) { *pszFriendlyName = NULL; }
//
// If not initialized, fail...
//
if (!g_CfgUtils.IsInitalized()) { TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic); Status = WBEM_E_INITIALIZATION_FAILURE; goto end; }
//
// Get WMI instance to specific NIC
//
Status = get_nic_instance( g_CfgUtils.m_spWbemServiceIF, szNic, spObj // pass by reference
); if (FAILED(Status)) { ASSERT(spObj == NULL); goto end; }
//
// Extract IP addresses and subnets.
//
{ //
// This gets the ip addresses in a 2D WCHAR array -- inner dimension
// is WLBS_MAX_CLI_IP_ADDR.
//
Status = get_multi_string_parameter( spObj, L"IPAddress", // szParameterName,
WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
&AddrCount, &pAddrs );
if (FAILED(Status)) { pAddrs = NULL; goto end; } else { TRACE_INFO("GOT %lu IP ADDRESSES!", AddrCount); }
UINT SubnetCount; Status = get_multi_string_parameter( spObj, L"IPSubnet", // szParameterName,
WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
&SubnetCount, &pSubnets );
if (FAILED(Status)) { pSubnets = NULL; goto end; } else if (SubnetCount != AddrCount) { TRACE_CRIT("FAILING SubnetCount!=AddressCount!"); goto end; } }
//
// Convert IP addresses to our internal form.
//
if (AddrCount != 0) { pIpInfo = new NLB_IP_ADDRESS_INFO[AddrCount]; if (pIpInfo == NULL) { TRACE_CRIT("get_multi_str_parm: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; goto end; } ZeroMemory(pIpInfo, AddrCount*sizeof(*pIpInfo)); for (UINT u=0;u<AddrCount; u++) { //
// We extrace each IP address and it's corresponding subnet mask
// from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
// structure.
//
LPCWSTR pIp = pAddrs+u*WLBS_MAX_CL_IP_ADDR; LPCWSTR pSub = pSubnets+u*WLBS_MAX_CL_NET_MASK; TRACE_INFO("IPaddress: %ws; SubnetMask:%ws", pIp, pSub); UINT len = wcslen(pIp); UINT len1 = wcslen(pSub); if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK)) { CopyMemory(pIpInfo[u].IpAddress, pIp, (len+1)*sizeof(WCHAR)); CopyMemory(pIpInfo[u].SubnetMask, pSub, (len1+1)*sizeof(WCHAR)); } else { //
// This would be an implementation error in get_multi_string_...
//
ASSERT(FALSE); Status = WBEM_E_CRITICAL_ERROR; goto end; } } }
//
// If requested, get friendly name.
// We don't fail if there's an error, just return the empty "" string.
//
if (pszFriendlyName != NULL) { IWbemClassObjectPtr spAdapterObj = NULL; // smart pointer
LPWSTR szFriendlyName = NULL; WBEMSTATUS TmpStatus;
do { TmpStatus = CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj( spObj, spAdapterObj // passed by ref
);
if (FAILED(TmpStatus)) { break; }
TmpStatus = CfgUtilGetWmiStringParam( spAdapterObj, L"NetConnectionID", &szFriendlyName ); if (FAILED(TmpStatus)) { TRACE_CRIT("%!FUNC! Get NetConnectionID failed error=0x%08lx\n", (UINT) TmpStatus);
}
} while (FALSE);
if (szFriendlyName == NULL) { //
// Try to put an empty string.
//
szFriendlyName = new WCHAR[1]; if (szFriendlyName == NULL) { Status = WBEM_E_OUT_OF_MEMORY; TRACE_CRIT("%!FUNC! Alloc failure!"); goto end; } *szFriendlyName = 0; // Empty string
}
*pszFriendlyName = szFriendlyName; szFriendlyName = NULL; }
end:
if (pAddrs != NULL) { delete pAddrs; } if (pSubnets != NULL) { delete pSubnets; }
if (FAILED(Status)) { if (pIpInfo != NULL) { delete pIpInfo; pIpInfo = NULL; } AddrCount = 0; }
*pNumIpAddresses = AddrCount; *ppIpInfo = pIpInfo; spObj = NULL; // smart pointer
TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
return Status; }
#if OBSOLETE
//
// Sets the list of statically-bound IP addresses for the NIC.
// if NumIpAddresses is 0, the NIC is configured for DHCP.
//
WBEMSTATUS CfgUtilSetStaticIpAddressesOld( IN LPCWSTR szNic, IN UINT NumIpAddresses, IN NLB_IP_ADDRESS_INFO *pIpInfo ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemClassObjectPtr spNicClassObj = NULL; // smart pointer
IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
HRESULT hr; WCHAR *rgIpAddresses = NULL; WCHAR *rgIpSubnets = NULL; LPWSTR pRelPath = NULL;
TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
//
// If not initialized, fail...
//
if (!g_CfgUtils.IsInitalized()) { TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic); Status = WBEM_E_INITIALIZATION_FAILURE; goto end; }
if (NumIpAddresses != 0) { //
// Convert IP addresses from our internal form into 2D arrays.
//
rgIpAddresses = new WCHAR[NumIpAddresses * WLBS_MAX_CL_IP_ADDR]; rgIpSubnets = new WCHAR[NumIpAddresses * WLBS_MAX_CL_NET_MASK]; if (rgIpAddresses == NULL || rgIpSubnets == NULL) { TRACE_CRIT("SetStaticIpAddresses: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; goto end; }
for (UINT u=0;u<NumIpAddresses; u++) { //
// We extrace each IP address and it's corresponding subnet mask
// from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
// structure.
//
LPWSTR pIpDest = rgIpAddresses+u*WLBS_MAX_CL_IP_ADDR; LPWSTR pSubDest = rgIpSubnets+u*WLBS_MAX_CL_NET_MASK; LPCWSTR pIpSrc = pIpInfo[u].IpAddress; LPCWSTR pSubSrc = pIpInfo[u].SubnetMask; UINT len = wcslen(pIpSrc); UINT len1 = wcslen(pSubSrc); if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK)) { CopyMemory(pIpDest, pIpSrc, (len+1)*sizeof(WCHAR)); CopyMemory(pSubDest, pSubSrc, (len1+1)*sizeof(WCHAR)); } else { //
// This would be an implementation error in get_multi_string_...
//
ASSERT(FALSE); goto end; } } }
//
// Get WMI path to specific NIC
//
{ IWbemClassObjectPtr spNicObj = NULL; // smart pointer
pRelPath = NULL; Status = get_nic_instance( g_CfgUtils.m_spWbemServiceIF, szNic, spNicObj // pass by reference
); if (FAILED(Status)) { ASSERT(spObj == NULL); goto end; }
//
// Extract the relative path, needed for ExecMethod.
//
Status = get_string_parameter( spNicObj, L"__RELPATH", // szParameterName
&pRelPath // Delete when done.
); if (FAILED(Status)) { TRACE_CRIT("Couldn't get rel path"); pRelPath = NULL; goto end; } else { if (pRelPath==NULL) { ASSERT(FALSE); // we don't expect this!
goto end; } TRACE_CRIT("GOT RELATIVE PATH for %ws: %ws", szNic, pRelPath); } }
//
// Get NIC CLASS object
//
{ hr = g_CfgUtils.m_spWbemServiceIF->GetObject( _bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &spNicClassObj, NULL );
if (FAILED(hr)) { TRACE_CRIT("Couldn't get nic class object pointer"); goto end; } }
//
// Set up input parameters to the call to Enable static.
//
{ IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
// check if any input parameters specified.
hr = spNicClassObj->GetMethod( L"EnableStatic", 0, &spWbemInput, NULL ); if( FAILED( hr) ) { TRACE_CRIT("IWbemClassObject::GetMethod failure"); goto end; } hr = spWbemInput->SpawnInstance( 0, &spWbemInputInstance ); if( FAILED( hr) ) { TRACE_CRIT("IWbemClassObject::SpawnInstance failure. Unable to spawn instance." ); goto end; } //
// This gets the ip addresses in a 2D WCHAR array -- inner dimension
// is WLBS_MAX_CLI_IP_ADDR.
//
Status = set_multi_string_parameter( spWbemInputInstance, L"IPAddress", // szParameterName,
WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
NumIpAddresses, rgIpAddresses );
if (FAILED(Status)) { goto end; } else { TRACE_INFO("SET %lu IP ADDRESSES!", NumIpAddresses); }
Status = set_multi_string_parameter( spWbemInputInstance, L"SubnetMask", // szParameterName,
WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
NumIpAddresses, rgIpSubnets );
if (FAILED(Status)) { goto end; } }
//
// execute method and get the output result
// WARNING: we try this a few times because the wmi call apperears to
// suffer from a recoverable error. TODO: Need to get to the bottom of
// this.
//
for (UINT NumTries=10; NumTries--;) { IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
_variant_t v_retVal;
TRACE_CRIT("Going to call EnableStatic");
hr = g_CfgUtils.m_spWbemServiceIF->ExecMethod( _bstr_t(pRelPath), L"EnableStatic", 0, NULL, spWbemInputInstance, &spWbemOutput, NULL ); TRACE_CRIT("EnableStatic returns"); if( FAILED( hr) ) { TRACE_CRIT("IWbemServices::ExecMethod failure 0x%08lx", (UINT) hr); goto end; }
hr = spWbemOutput->Get( L"ReturnValue", 0, &v_retVal, NULL, NULL ); if( FAILED( hr) ) { TRACE_CRIT("IWbemClassObject::Get failure"); goto end; }
LONG lRet = (LONG) v_retVal; v_retVal.Clear();
if (lRet == 0) { TRACE_INFO("EnableStatic returns SUCCESS!"); Status = WBEM_NO_ERROR; break; } else if (lRet == 0x51) // This appears to be a recoverable error
{ TRACE_INFO( "EnableStatic on NIC %ws returns recoverable FAILURE:0x%08lx!", szNic, lRet ); Sleep(1000); Status = WBEM_E_CRITICAL_ERROR; } else { TRACE_INFO( "EnableStatic on NIC %ws returns FAILURE:0x%08lx!", szNic, lRet ); Status = WBEM_E_CRITICAL_ERROR; } }
end:
if (rgIpAddresses != NULL) { delete rgIpAddresses; } if (rgIpSubnets != NULL) { delete rgIpSubnets; }
if (pRelPath != NULL) { delete pRelPath; }
spNicClassObj = NULL; // smart pointer
spWbemInputInstance = NULL;
TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
return Status; } #endif // OBSOLETE
//
// Sets the list of statically-bound IP addresses for the NIC.
// if NumIpAddresses is 0, the NIC is configured for DHCP.
//
WBEMSTATUS CfgUtilSetStaticIpAddresses( IN LPCWSTR szNic, IN UINT NumIpAddresses, IN NLB_IP_ADDRESS_INFO *pIpInfo ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
WCHAR *rgIpAddresses = NULL; WCHAR *rgIpSubnets = NULL; LPWSTR pRelPath = NULL;
TRACE_INFO(L"-> %!FUNC!(Nic=%ws)", szNic);
//
// If not initialized, fail...
//
if (!g_CfgUtils.IsInitalized()) { TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic); Status = WBEM_E_INITIALIZATION_FAILURE; goto end; }
if (NumIpAddresses != 0) { //
// Convert IP addresses from our internal form into 2D arrays.
//
rgIpAddresses = new WCHAR[NumIpAddresses * WLBS_MAX_CL_IP_ADDR]; rgIpSubnets = new WCHAR[NumIpAddresses * WLBS_MAX_CL_NET_MASK]; if (rgIpAddresses == NULL || rgIpSubnets == NULL) { TRACE_CRIT("SetStaticIpAddresses: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; goto end; }
for (UINT u=0;u<NumIpAddresses; u++) { //
// We extrace each IP address and it's corresponding subnet mask
// from the 2 2D arrays and insert it into a NLB_IP_ADDRESS_INFO
// structure.
//
LPWSTR pIpDest = rgIpAddresses+u*WLBS_MAX_CL_IP_ADDR; LPWSTR pSubDest = rgIpSubnets+u*WLBS_MAX_CL_NET_MASK; LPCWSTR pIpSrc = pIpInfo[u].IpAddress; LPCWSTR pSubSrc = pIpInfo[u].SubnetMask; UINT len = wcslen(pIpSrc); UINT len1 = wcslen(pSubSrc); if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK)) { CopyMemory(pIpDest, pIpSrc, (len+1)*sizeof(WCHAR)); CopyMemory(pSubDest, pSubSrc, (len1+1)*sizeof(WCHAR)); } else { //
// This would be an implementation error in get_multi_string_...
//
ASSERT(FALSE); goto end; } } }
//
// Get input instance and relpath...
//
Status = CfgUtilGetWmiInputInstanceAndRelPath( g_CfgUtils.m_spWbemServiceIF, L"Win32_NetworkAdapterConfiguration", // szClassName
L"SettingID", // szPropertyName
szNic, // szPropertyValue
L"EnableStatic", // szMethodName,
spWbemInputInstance, // smart pointer
&pRelPath // free using delete
);
if (FAILED(Status)) { goto end; }
//
// Set up input parameters to the call to Enable static.
//
{ //
// This gets the ip addresses in a 2D WCHAR array -- inner dimension
// is WLBS_MAX_CLI_IP_ADDR.
//
Status = set_multi_string_parameter( spWbemInputInstance, L"IPAddress", // szParameterName,
WLBS_MAX_CL_IP_ADDR, // MaxStringLen - in wchars, incl null
NumIpAddresses, rgIpAddresses );
if (FAILED(Status)) { goto end; } else { TRACE_INFO("SET %lu IP ADDRESSES!", NumIpAddresses); }
Status = set_multi_string_parameter( spWbemInputInstance, L"SubnetMask", // szParameterName,
WLBS_MAX_CL_NET_MASK, // MaxStringLen - in wchars, incl null
NumIpAddresses, rgIpSubnets );
if (FAILED(Status)) { goto end; } }
//
// execute method and get the output result
// WARNING: we try this a few times because the wmi call apperears to
// suffer from a recoverable error. TODO: Need to get to the bottom of
// this.
//
for (UINT NumTries=10; NumTries--;) { HRESULT hr; IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
_variant_t v_retVal;
TRACE_CRIT("Going to call EnableStatic");
hr = g_CfgUtils.m_spWbemServiceIF->ExecMethod( _bstr_t(pRelPath), L"EnableStatic", 0, NULL, spWbemInputInstance, &spWbemOutput, NULL ); TRACE_CRIT("EnableStatic returns"); if( FAILED( hr) ) { TRACE_CRIT("IWbemServices::ExecMethod failure 0x%08lx", (UINT) hr); goto end; }
hr = spWbemOutput->Get( L"ReturnValue", 0, &v_retVal, NULL, NULL ); if( FAILED( hr) ) { TRACE_CRIT("IWbemClassObject::Get failure"); goto end; }
LONG lRet = (LONG) v_retVal; v_retVal.Clear();
if (lRet == 0) { TRACE_INFO("EnableStatic returns SUCCESS!"); Status = WBEM_NO_ERROR; break; } else if (lRet == 0x51) // This appears to be a recoverable error
{ TRACE_INFO( "EnableStatic on NIC %ws returns recoverable FAILURE:0x%08lx!", szNic, lRet ); Sleep(1000); Status = WBEM_E_CRITICAL_ERROR; } else { TRACE_INFO( "EnableStatic on NIC %ws returns FAILURE:0x%08lx!", szNic, lRet ); Status = WBEM_E_CRITICAL_ERROR; } }
end:
if (rgIpAddresses != NULL) { delete rgIpAddresses; } if (rgIpSubnets != NULL) { delete rgIpSubnets; }
if (pRelPath != NULL) { delete pRelPath; }
spWbemInputInstance = NULL;
TRACE_INFO(L"<- %!FUNC!(Nic=%ws) returns 0x%08lx", szNic, (UINT) Status);
return Status; }
//
// Determines whether NLB is bound to the specified NIC.
//
WBEMSTATUS CfgUtilCheckIfNlbBound( IN LPCWSTR szNic, OUT BOOL *pfBound ) { WBEMSTATUS Status = WBEM_NO_ERROR; BOOL fNetCfgInitialized = FALSE; MyNetCfg NetCfg; BOOL fBound = FALSE;
//
// Get and initialize interface to netcfg
//
Status = NetCfg.Initialize(FALSE); // FALSE == don't get write lock.
if (FAILED(Status)) { goto end; } fNetCfgInitialized = TRUE;
//
//
//
Status = NetCfg.UpdateBindingState( szNic, L"ms_wlbs", MyNetCfg::NOOP, &fBound );
end:
if (fNetCfgInitialized) { NetCfg.Deinitialize(); }
*pfBound = fBound;
return Status; }
//
// Binds/unbinds NLB to the specified NIC.
//
WBEMSTATUS CfgUtilChangeNlbBindState( IN LPCWSTR szNic, IN BOOL fBind ) { WBEMSTATUS Status = WBEM_NO_ERROR; BOOL fNetCfgInitialized = FALSE; MyNetCfg NetCfg; BOOL fBound = FALSE;
//
// Get and initialize interface to netcfg
//
Status = NetCfg.Initialize(TRUE); // TRUE == get write lock.
if (FAILED(Status)) { goto end; } fNetCfgInitialized = TRUE;
//
//
//
Status = NetCfg.UpdateBindingState( szNic, L"ms_wlbs", fBind ? MyNetCfg::BIND : MyNetCfg::UNBIND, &fBound );
end:
if (fNetCfgInitialized) { NetCfg.Deinitialize(); }
return Status; }
//
// Gets the current NLB configuration for the specified NIC
//
WBEMSTATUS CfgUtilGetNlbConfig( IN LPCWSTR szNic, OUT WLBS_REG_PARAMS *pParams ) { GUID Guid; WBEMSTATUS Status = WBEM_NO_ERROR; CWlbsCluster *pCluster = NULL;
// g_CfgUtils.mfn_Lock(); // Because pCluster is not protected...
Status = g_CfgUtils.GetClusterFromGuid( szNic, &pCluster ); if (FAILED(Status)) { goto end; }
//
// Read the configuration.
//
DWORD dwRet = pCluster->ReadConfig(pParams); if (dwRet != WLBS_OK) { TRACE_CRIT("Could not read NLB configuration for %wsz", szNic); Status = WBEM_E_CRITICAL_ERROR; goto end; }
Status = WBEM_NO_ERROR;
end:
// g_CfgUtils.mfn_Unlock();
return Status; }
//
// Sets the current NLB configuration for the specified NIC. This
// includes notifying the driver if required.
//
WBEMSTATUS CfgUtilSetNlbConfig( IN LPCWSTR szNic, IN WLBS_REG_PARAMS *pParams ) { GUID Guid; WBEMSTATUS Status = WBEM_NO_ERROR; CWlbsCluster *pCluster = NULL; DWORD dwRet = 0;
// NOTE: we assume pCluster won't go away -- i.e. no one is trying
// to unbind in this process' context.
// someone else remove it say fron netconfig UI?
Status = g_CfgUtils.GetClusterFromGuid( szNic, &pCluster ); if (FAILED(Status)) { goto end; }
//
// Write the configuration.
//
dwRet = pCluster->WriteConfig(pParams); if (dwRet != WLBS_OK) { TRACE_CRIT("Could not write NLB configuration for %wsz. Err=0x%08lx", szNic, dwRet); Status = WBEM_E_CRITICAL_ERROR; goto end; }
//
// Commit the changes.
//
dwRet = pCluster->CommitChanges(g_CfgUtils.m_pWlbsControl); if (dwRet != WLBS_OK) { TRACE_CRIT("Could not commit changes to NLB configuration for %wsz. Err=0x%08lx", szNic, dwRet); Status = WBEM_E_CRITICAL_ERROR; goto end; }
Status = WBEM_NO_ERROR;
end:
return Status; }
WBEMSTATUS CfgUtilsAnalyzeNlbUpdate( IN WLBS_REG_PARAMS *pCurrentParams, OPTIONAL IN WLBS_REG_PARAMS *pNewParams, OUT BOOL *pfConnectivityChange ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; BOOL fConnectivityChange = FALSE;
//
// If not initialized, fail...
//
if (!g_CfgUtils.IsInitalized()) { TRACE_CRIT(L"%!FUNC! FAILING because uninitialized"); Status = WBEM_E_INITIALIZATION_FAILURE; goto end; }
if (pCurrentParams != NULL) { //
// If the structures have identical content, we return S_FALSE.
// We do this check before we call ValidateParm below, because
// ValidateParam has the side effect of filling out / modifying
// certain fields.
//
if (memcmp(pCurrentParams, pNewParams, sizeof(*pCurrentParams))==0) { Status = WBEM_S_FALSE; goto end; } }
//
// Validate pNewParams -- this may also modify pNewParams slightly, by
// re-formatting ip addresses into canonical format.
//
BOOL fRet = g_CfgUtils.m_pWlbsControl->ValidateParam(pNewParams); if (!fRet) { TRACE_CRIT(L"%!FUNC!FAILING because New params are invalid"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
Status = WBEM_NO_ERROR;
if (pCurrentParams == NULL) { //
// NLB was not previously bound.
//
fConnectivityChange = TRUE; goto end; }
//
// Change in multicast modes or mac address.
//
if ( (pCurrentParams->mcast_support != pNewParams->mcast_support) || _wcsicmp(pCurrentParams->cl_mac_addr, pNewParams->cl_mac_addr)!=0) { fConnectivityChange = TRUE; }
//
// Change in primary cluster ip or subnet mask
//
if ( _wcsicmp(pCurrentParams->cl_ip_addr,pNewParams->cl_ip_addr)!=0 || _wcsicmp(pCurrentParams->cl_net_mask,pNewParams->cl_net_mask)!=0) { fConnectivityChange = TRUE; }
end: *pfConnectivityChange = fConnectivityChange; return Status; }
WBEMSTATUS CfgUtilsValidateNicGuid( IN LPCWSTR szGuid ) //
//
{ //
// Sample GUID: {EBE09517-07B4-4E88-AAF1-E06F5540608B}
//
WBEMSTATUS Status = WBEM_E_INVALID_PARAMETER; UINT Length = wcslen(szGuid);
if (Length != NLB_GUID_LEN) { TRACE_CRIT("Length != %d", NLB_GUID_LEN); goto end; }
//
// Open tcpip's registry key and look for guid there -- if not found,
// we'll return WBEM_E_NOT_FOUND
//
{ WCHAR szKey[128]; // This is enough for the tcpip+guid key
wcscpy(szKey, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\" ); wcscat(szKey, szGuid); HKEY hKey = NULL; LONG lRet; lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // handle to an open key
szKey, // address of subkey name
0, // reserved
KEY_QUERY_VALUE, // desired security access
&hKey // address of buffer for opened handle
); if (lRet != ERROR_SUCCESS) { TRACE_CRIT("Guid %ws doesn't exist under tcpip", szGuid); Status = WBEM_E_NOT_FOUND; goto end; } RegCloseKey(hKey); }
Status = WBEM_NO_ERROR;
end:
return Status; }
WBEMSTATUS get_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT LPWSTR *ppStringValue ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; WCHAR *pStringValue = NULL; _variant_t v_value; CIMTYPE v_type; HRESULT hr;
hr = spObj->Get( _bstr_t(szParameterName), // Name
0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the Setting ID field!
//
TRACE_CRIT( "get_str_parm:Couldn't retrieve %ws from 0x%p", szParameterName, (PVOID) spObj ); goto end; } else { if (v_type != VT_BSTR) { TRACE_CRIT( "get_str_parm: Parm value not of string type %ws from 0x%p", szParameterName, (PVOID) spObj ); Status = WBEM_E_INVALID_PARAMETER; } else {
_bstr_t bstrNicGuid(v_value); LPCWSTR sz = bstrNicGuid; // Pointer to internal buffer.
if (sz==NULL) { // hmm.. null value
Status = WBEM_NO_ERROR; } else { UINT len = wcslen(sz); pStringValue = new WCHAR[len+1]; if (pStringValue == NULL) { TRACE_CRIT("get_str_parm: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; } else { CopyMemory(pStringValue, sz, (len+1)*sizeof(WCHAR)); Status = WBEM_NO_ERROR; } }
TRACE_VERB( "get_str_parm: String parm %ws of 0x%p is %ws", szParameterName, (PVOID) spObj, (sz==NULL) ? L"<null>" : sz ); }
v_value.Clear(); // Must be cleared after each call to Get.
}
end: *ppStringValue = pStringValue;
return Status;
}
WBEMSTATUS get_nic_instance( IN IWbemServicesPtr spWbemServiceIF, IN LPCWSTR szNicGuid, OUT IWbemClassObjectPtr &sprefObj ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; IWbemClassObjectPtr spObj = NULL; // smart pointer.
Status = CfgUtilGetWmiObjectInstance( spWbemServiceIF, L"Win32_NetworkAdapterConfiguration", // szClassName
L"SettingID", // szParameterName
szNicGuid, // ParameterValue
spObj // smart pointer, passed by ref
); if (FAILED(Status)) { ASSERT(spObj == NULL); goto end; }
end:
if (FAILED(Status)) { sprefObj = NULL; } else { sprefObj = spObj; // smart pointer.
}
return Status; }
WBEMSTATUS get_multi_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
OUT UINT *pNumItems, OUT LPCWSTR *ppStringValue ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; WCHAR *pStringValue = NULL; _variant_t v_value; CIMTYPE v_type; HRESULT hr; LONG count = 0;
*ppStringValue = NULL; *pNumItems = 0;
hr = spObj->Get( _bstr_t(szParameterName), 0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the requested parameter.
//
TRACE_CRIT( "get_multi_str_parm:Couldn't retrieve %ws from 0x%p", szParameterName, (PVOID) spObj ); goto end; }
{ VARIANT ipsV = v_value.Detach();
do // while false
{ BSTR* pbstr; if (ipsV.vt == VT_NULL) { //
// NULL string -- this is ok
//
count = 0; } else { count = ipsV.parray->rgsabound[0].cElements; }
if (count==0) { Status = WBEM_NO_ERROR; break; } pStringValue = new WCHAR[count*MaxStringLen]; if (pStringValue == NULL) { TRACE_CRIT("get_multi_str_parm: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; break; } ZeroMemory(pStringValue, sizeof(WCHAR)*count*MaxStringLen); hr = SafeArrayAccessData(ipsV.parray, ( void **) &pbstr); if(FAILED(hr)) { Status = WBEM_E_INVALID_PARAMETER; // TODO: pick better error
break; } Status = WBEM_NO_ERROR; for( LONG x = 0; x < count; x++ ) { LPCWSTR sz = pbstr[x]; // Pointer to internal buffer.
if (sz==NULL) { // hmm.. null value
continue; } else { UINT len = wcslen(sz); if ((len+1) > MaxStringLen) { TRACE_CRIT("get_str_parm: string size too long!"); Status = WBEM_E_INVALID_PARAMETER; break; } else { WCHAR *pDest = pStringValue+x*MaxStringLen; CopyMemory(pDest, sz, (len+1)*sizeof(WCHAR)); } } } (VOID) SafeArrayUnaccessData( ipsV.parray ); } while (FALSE);
VariantClear( &ipsV ); }
if (FAILED(Status)) { if (pStringValue!=NULL) { delete pStringValue; *pStringValue = NULL; } } else { *ppStringValue = pStringValue; *pNumItems = count; }
end:
return Status; }
WBEMSTATUS MyNetCfg::Initialize( BOOL fWriteLock ) { HRESULT hr; INetCfg *pnc = NULL; INetCfgLock *pncl = NULL; WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; BOOL fLocked = FALSE; BOOL fInitialized=FALSE; if (m_pINetCfg != NULL || m_pLock != NULL) { ASSERT(FALSE); goto end; }
hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_SERVER, IID_INetCfg, (void **) &pnc);
if( !SUCCEEDED( hr ) ) { // failure to create instance.
TRACE_CRIT("ERROR: could not get interface to Net Config"); goto end; }
//
// If require, get the write lock
//
if (fWriteLock) { WCHAR *szLockedBy = NULL; hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl ); if( !SUCCEEDED( hr ) ) { TRACE_CRIT("ERROR: could not get interface to NetCfg Lock"); goto end; }
hr = pncl->AcquireWriteLock( 1, // One Second
L"NLBManager", &szLockedBy); if( hr != S_OK ) { TRACE_CRIT("Could not get write lock. Lock held by %ws", (szLockedBy!=NULL) ? szLockedBy : L"<null>"); goto end; } }
// Initializes network configuration by loading into
// memory all basic networking information
//
hr = pnc->Initialize( NULL ); if( !SUCCEEDED( hr ) ) { // failure to Initialize
TRACE_CRIT("INetCfg::Initialize failure "); goto end; }
Status = WBEM_NO_ERROR; end:
if (FAILED(Status)) { if (pncl!=NULL) { if (fLocked) { pncl->ReleaseWriteLock(); } pncl->Release(); pncl=NULL; } if( pnc != NULL) { if (fInitialized) { pnc->Uninitialize(); } pnc->Release(); pnc= NULL; } } else { m_pINetCfg = pnc; m_pLock = pncl; }
return Status; }
VOID MyNetCfg::Deinitialize( VOID ) { if (m_pLock!=NULL) { m_pLock->ReleaseWriteLock(); m_pLock->Release(); m_pLock=NULL; } if( m_pINetCfg != NULL) { m_pINetCfg->Uninitialize(); m_pINetCfg->Release(); m_pINetCfg= NULL; } }
WBEMSTATUS MyNetCfg::GetNicIF( IN LPCWSTR szNicGuid, OUT INetCfgComponent **ppINic ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; INetCfgComponent *pncc = NULL; HRESULT hr; IEnumNetCfgComponent* pencc = NULL; ULONG countToFetch = 1; ULONG countFetched; DWORD characteristics;
if (m_pINetCfg == NULL) { //
// This means we're not initialized
//
ASSERT(FALSE); goto end; }
hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc ); if( !SUCCEEDED( hr ) ) { // failure to Enumerate net components
TRACE_CRIT("Could not enum netcfg adapters"); pencc = NULL; goto end; }
while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK ) { LPWSTR szName = NULL;
hr = pncc->GetBindName( &szName ); if (!SUCCEEDED(hr)) { TRACE_CRIT("WARNING: couldn't get bind name for 0x%p, ignoring", (PVOID) pncc); continue; } if(!_wcsicmp(szName, szNicGuid)) { //
// Got this one!
//
CoTaskMemFree( szName ); break; } CoTaskMemFree( szName ); pncc->Release(); pncc=NULL; }
if (pncc == NULL) { TRACE_CRIT("Could not find NIC %ws", szNicGuid); Status = WBEM_E_NOT_FOUND; } else { Status = WBEM_NO_ERROR; }
end:
if (pencc != NULL) { pencc->Release(); }
*ppINic = pncc;
return Status; }
LPWSTR * CfgUtilsAllocateStringArray( UINT NumStrings, UINT MaxStringLen // excluding ending NULL
) /*
Allocate a single chunk of memory using the new LPWSTR[] operator. The first NumStrings LPWSTR values of this operator contain an array of pointers to WCHAR strings. Each of these strings is of size (MaxStringLen+1) WCHARS. The rest of the memory contains the strings themselve.
Return NULL if NumStrings==0 or on allocation failure.
Each of the strings are initialized to be empty strings (first char is 0). */ { LPWSTR *pStrings = NULL; UINT TotalSize = 0;
if (NumStrings == 0) { goto end; }
//
// Note - even if MaxStringLen is 0 we will allocate space for NumStrings
// pointers and NumStrings empty (first char is 0) strings.
//
//
// Calculate space for the array of pointers to strings...
//
TotalSize = NumStrings*sizeof(LPWSTR);
//
// Calculate space for the strings themselves...
// Remember to add +1 for each ending 0 character.
//
TotalSize += NumStrings*(MaxStringLen+1)*sizeof(WCHAR);
//
// Allocate space for *both* the array of pointers and the strings
// in one shot -- we're doing a new of type LPWSTR[] for the whole
// lot, so need to specify the size in units of LPWSTR (with an
// additional +1 in case there's roundoff.
//
pStrings = new LPWSTR[(TotalSize/sizeof(LPWSTR))+1]; if (pStrings == NULL) { goto end; }
//
// Make sz point to the start of the place where we'll be placing
// the string data.
//
LPWSTR sz = (LPWSTR) (pStrings+NumStrings); for (UINT u=0; u<NumStrings; u++) { *sz=NULL; pStrings[u] = sz; sz+=(MaxStringLen+1); // +1 for ending NULL
}
end:
return pStrings;
}
WBEMSTATUS MyNetCfg::GetNlbCompatibleNics( OUT LPWSTR **ppszNics, OUT UINT *pNumNics, OUT UINT *pNumBoundToNlb // OPTIONAL
) /*
Returns an array of pointers to string-version of GUIDS that represent the set of alive and healthy NICS that are suitable for NLB to bind to -- basically alive ethernet NICs.
Delete ppNics using the delete WCHAR[] operator. Do not delete the individual strings. */ { #define MY_GUID_LENGTH 38
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; HRESULT hr; IEnumNetCfgComponent* pencc = NULL; INetCfgComponent *pncc = NULL; ULONG countToFetch = 1; ULONG countFetched; DWORD characteristics; UINT NumNics = 0; LPWSTR *pszNics = NULL; INetCfgComponentBindings *pINlbBinding=NULL; UINT NumNlbBoundNics = 0;
typedef struct _MYNICNODE MYNICNODE;
typedef struct _MYNICNODE { LPWSTR szNicGuid; MYNICNODE *pNext; } MYNICNODE;
MYNICNODE *pNicNodeList = NULL; MYNICNODE *pNicNode = NULL;
*ppszNics = NULL; *pNumNics = 0;
if (pNumBoundToNlb != NULL) { *pNumBoundToNlb = 0; }
if (m_pINetCfg == NULL) { //
// This means we're not initialized
//
ASSERT(FALSE); goto end; }
hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc ); if( !SUCCEEDED( hr ) ) { // failure to Enumerate net components
TRACE_CRIT("%!FUNC! Could not enum netcfg adapters"); pencc = NULL; goto end; }
//
// Check if nlb is bound to the nlb component.
//
//
// If we need to count of NLB-bound nics, get instance of the nlb component
//
if (pNumBoundToNlb != NULL) { Status = GetBindingIF(L"ms_wlbs", &pINlbBinding); if (FAILED(Status)) { TRACE_CRIT("%!FUNC! WARNING: NLB doesn't appear to be installed on this machine"); pINlbBinding = NULL; } }
while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK ) { LPWSTR szName = NULL;
hr = pncc->GetBindName( &szName ); if (!SUCCEEDED(hr)) { TRACE_CRIT("%!FUNC! WARNING: couldn't get bind name for 0x%p, ignoring", (PVOID) pncc); continue; }
do // while FALSE -- just to allow breaking out
{
UINT Len = wcslen(szName); if (Len != MY_GUID_LENGTH) { TRACE_CRIT("%!FUNC! WARNING: GUID %ws has unexpected length %ul", szName, Len); break; } DWORD characteristics = 0; hr = pncc->GetCharacteristics( &characteristics ); if(!SUCCEEDED(hr)) { TRACE_CRIT("%!FUNC! WARNING: couldn't get characteristics for %ws, ignoring", szName); break; } if(characteristics & NCF_PHYSICAL) { ULONG devstat = 0; // 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( &devstat ); if(!SUCCEEDED(hr)) { TRACE_CRIT( "%!FUNC! WARNING: couldn't get dev status for %ws, ignoring", szName ); break; } // if any of the nics has any of the problem codes
// then it cannot be used.
if( devstat != CM_PROB_NOT_CONFIGURED && devstat != CM_PROB_FAILED_START && devstat != CM_PROB_NORMAL_CONFLICT && devstat != CM_PROB_NEED_RESTART && devstat != CM_PROB_REINSTALL && devstat != CM_PROB_WILL_BE_REMOVED && devstat != CM_PROB_DISABLED && devstat != CM_PROB_FAILED_INSTALL && devstat != CM_PROB_FAILED_ADD ) { //
// No problem with this nic and also
// physical device
// thus we want it.
//
if (pINlbBinding != NULL) { BOOL fBound = FALSE;
hr = pINlbBinding->IsBoundTo(pncc);
if( !SUCCEEDED( hr ) ) { TRACE_CRIT("IsBoundTo method failed for Nic %ws", szName); goto end; } if( hr == S_OK ) { TRACE_VERB("BOUND: %ws\n", szName); NumNlbBoundNics++; fBound = TRUE; } else if (hr == S_FALSE ) { TRACE_VERB("NOT BOUND: %ws\n", szName); fBound = FALSE; } }
// We allocate a little node to keep this string
// temporarily and add it to our list of nodes.
//
pNicNode = new MYNICNODE; if (pNicNode == NULL) { Status = WBEM_E_OUT_OF_MEMORY; goto end; } ZeroMemory(pNicNode, sizeof(*pNicNode)); pNicNode->szNicGuid = szName; szName = NULL; // so we don't delete inside the lopp.
pNicNode->pNext = pNicNodeList; pNicNodeList = pNicNode; NumNics++; } else { // There is a problem...
TRACE_CRIT( "%!FUNC! WARNING: Skipping %ws because DeviceStatus=0x%08lx", szName, devstat ); break; } } else { TRACE_VERB("%!FUNC! Ignoring non-physical device %ws", szName); }
} while (FALSE);
if (szName != NULL) { CoTaskMemFree( szName ); } pncc->Release(); pncc=NULL; }
if (pINlbBinding!=NULL) { pINlbBinding->Release(); pINlbBinding = NULL; }
if (NumNics==0) { Status = WBEM_NO_ERROR; goto end; } //
// Now let's allocate space for all the nic strings and:w
// copy them over..
//
#define MY_GUID_LENGTH 38
pszNics = CfgUtilsAllocateStringArray(NumNics, MY_GUID_LENGTH); if (pszNics == NULL) { Status = WBEM_E_OUT_OF_MEMORY; goto end; }
pNicNode= pNicNodeList; for (UINT u=0; u<NumNics; u++, pNicNode=pNicNode->pNext) { ASSERT(pNicNode != NULL); // because we just counted NumNics of em.
UINT Len = wcslen(pNicNode->szNicGuid); if (Len != MY_GUID_LENGTH) { //
// We should never get here beause we checked the length earlier.
//
TRACE_CRIT("%!FUNC! ERROR: GUID %ws has unexpected length %ul", pNicNode->szNicGuid, Len); ASSERT(FALSE); Status = WBEM_E_CRITICAL_ERROR; goto end; } CopyMemory( pszNics[u], pNicNode->szNicGuid, (MY_GUID_LENGTH+1)*sizeof(WCHAR)); ASSERT(pszNics[u][MY_GUID_LENGTH]==0); }
Status = WBEM_NO_ERROR;
end:
//
// Now release the temporarly allocated memory.
//
pNicNode= pNicNodeList; while (pNicNode!=NULL) { MYNICNODE *pTmp = pNicNode->pNext; CoTaskMemFree(pNicNode->szNicGuid); pNicNode->szNicGuid = NULL; delete pNicNode; pNicNode = pTmp; }
if (FAILED(Status)) { TRACE_CRIT("%!FUNC! fails with status 0x%08lx", (UINT) Status); NumNics = 0; if (pszNics!=NULL) { delete pszNics; pszNics = NULL; } } else { if (pNumBoundToNlb != NULL) { *pNumBoundToNlb = NumNlbBoundNics; } *ppszNics = pszNics; *pNumNics = NumNics; }
if (pencc != NULL) { pencc->Release(); }
return Status; }
WBEMSTATUS MyNetCfg::GetBindingIF( IN LPCWSTR szComponent, OUT INetCfgComponentBindings **ppIBinding ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; INetCfgComponent *pncc = NULL; INetCfgComponentBindings *pnccb = NULL; HRESULT hr;
if (m_pINetCfg == NULL) { //
// This means we're not initialized
//
ASSERT(FALSE); goto end; }
hr = m_pINetCfg->FindComponent(szComponent, &pncc);
if (FAILED(hr)) { TRACE_CRIT("Error checking if component %ws does not exist\n", szComponent); pncc = NULL; goto end; } else if (hr == S_FALSE) { Status = WBEM_E_NOT_FOUND; TRACE_CRIT("Component %ws does not exist\n", szComponent); goto end; } hr = pncc->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb ); if( !SUCCEEDED( hr ) ) { TRACE_CRIT("INetCfgComponent::QueryInterface failed "); pnccb = NULL; goto end; }
Status = WBEM_NO_ERROR;
end:
if (pncc) { pncc->Release(); pncc=NULL; }
*ppIBinding = pnccb;
return Status;
}
WBEMSTATUS set_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN LPCWSTR szValue ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; HRESULT hr;
{ _bstr_t bstrName = szParameterName; _variant_t v_value = (LPWSTR) szValue; // Allocates.
hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
); v_value.Clear(); if (FAILED(hr)) { TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR;
//
// I think bstrName releases the internally allocated string
// on exiting this block.
//
}
end:
return Status; }
WBEMSTATUS set_multi_string_parameter( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN UINT MaxStringLen, // in wchars, INCLUDING space for trailing zeros.
IN UINT NumItems, IN LPCWSTR pStringValue ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; SAFEARRAY *pSA = NULL; HRESULT hr; LONG Index = 0;
//
// Create safe array for the parameter values
//
pSA = SafeArrayCreateVector( VT_BSTR, 0, // lower bound
NumItems // size of the fixed-sized vector.
); if (pSA == NULL) { TRACE_CRIT("Could not create safe array"); Status = WBEM_E_OUT_OF_MEMORY; goto end; }
//
// Place the strings into the safe array
//
{ for (Index = 0; Index<NumItems; Index++) { LPCWSTR sz = pStringValue + Index*MaxStringLen;
//
// SafeArrayPutElement expects the string passed in to
// be of type BSTR, which is of type wchar *, except, that
// the first 2 wchars contains length and other(?)
// information. This is why you can't simply pass in sz.
//
// So to get this we initalize an object of type _bstr_t
// based on sz. On initializaton, bstrValue allocates memory
// and copies the string.
//
_bstr_t bstrValue = sz; wchar_t *pwchar = (wchar_t *) bstrValue; // returns internal pointer.
// bpStr[Index] = sz; // may work as well.
//
// SafeArrayPutElement internally allocates space for pwchar and
// copies over the string.
// So pSA doesn't contain a direct reference to pwchar.
//
hr = SafeArrayPutElement(pSA, &Index, pwchar); if (FAILED(hr)) { TRACE_CRIT("Unable to put element %wsz", sz); (VOID) SafeArrayUnaccessData(pSA); goto end; }
//
// I think that bstrValue's contents are deallocated on exit of
// this block.
//
} } #if DBG
//
// Just check ...
//
{ BSTR *pbStr=NULL; hr = SafeArrayAccessData(pSA, ( void **) &pbStr); if (FAILED(hr)) { TRACE_CRIT("Could not access data of safe array"); goto end; } for (UINT u = 0; u<NumItems; u++) { LPCWSTR sz = pbStr[u]; if (_wcsicmp(sz, (pStringValue + u*MaxStringLen))) { TRACE_CRIT("!!!MISMATCH!!!!"); } else { TRACE_CRIT("!!!MATCH!!!!"); } } (VOID) SafeArrayUnaccessData(pSA); pbStr=NULL; } #endif // DBG
//
// Put the parameter.
//
{ VARIANT V; _bstr_t bstrName = szParameterName;
VariantInit(&V); V.vt = VT_ARRAY | VT_BSTR; V.parray = pSA; _variant_t v_value; v_value.Attach(V); // Takes owhership of V. V now becomes empty.
ASSERT(V.vt == VT_EMPTY); pSA = NULL; // should be no need to delete this explicitly now.
// v_value.Clear() should delete it, I think.
hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
);
v_value.Clear(); if (FAILED(hr)) { TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR; }
//
// ?Destroy the data?
//
if (FAILED(Status)) { if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; } }
end:
return Status; }
WBEMSTATUS MyNetCfg::UpdateBindingState( IN LPCWSTR szNic, IN LPCWSTR szComponent, IN UPDATE_OP Op, OUT BOOL *pfBound ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; INetCfgComponent *pINic = NULL; INetCfgComponentBindings *pIBinding=NULL; BOOL fBound = FALSE; HRESULT hr;
//
// Get instance to the NIC
//
Status = GetNicIF(szNic, &pINic); if (FAILED(Status)) { pINic = NULL; goto end; }
//
// Get instance of the nlb component
//
Status = GetBindingIF(szComponent, &pIBinding); if (FAILED(Status)) { pIBinding = NULL; goto end; }
//
// Check if nlb is bound to the nlb component.
//
hr = pIBinding->IsBoundTo(pINic); if( !SUCCEEDED( hr ) ) { TRACE_CRIT("IsBoundTo method failed for Nic %ws", szNic); goto end; }
if( hr == S_OK ) { fBound = TRUE; } else if (hr == S_FALSE ) { fBound = FALSE; }
if ( (Op == MyNetCfg::NOOP) || (Op == MyNetCfg::BIND && fBound) || (Op == MyNetCfg::UNBIND && !fBound)) { Status = WBEM_NO_ERROR; goto end; }
if (Op == MyNetCfg::BIND) { hr = pIBinding->BindTo( pINic ); } else if (Op == MyNetCfg::UNBIND) { hr = pIBinding->UnbindFrom( pINic ); } else { ASSERT(FALSE); goto end; }
if (FAILED(hr)) { TRACE_CRIT("Error 0x%08lx %ws %ws on %ws", (UINT) hr, ((Op==MyNetCfg::BIND) ? L"binding" : L"unbinding"), szComponent, szNic ); goto end; }
//
// apply the binding change made.
//
hr = m_pINetCfg->Apply(); if( !SUCCEEDED( hr ) ) { TRACE_CRIT("INetCfg::Apply failed with 0x%08lx", (UINT) hr); goto end; }
//
// We're done. Our state should now be toggled.
//
fBound = !fBound;
Status = WBEM_NO_ERROR;
end:
if (pINic!=NULL) { pINic->Release(); pINic = NULL; }
if (pIBinding!=NULL) { pIBinding->Release(); pIBinding = NULL; }
*pfBound = fBound;
return Status; }
WBEMSTATUS CfgUtilControlCluster( IN LPCWSTR szNic, IN LONG ioctl ) { HRESULT hr; GUID Guid; WBEMSTATUS Status;
if (!g_CfgUtils.IsInitalized()) { TRACE_CRIT(L"%!FUNC!(Nic=%ws) FAILING because uninitialized", szNic); Status = WBEM_E_INITIALIZATION_FAILURE; goto end; }
hr = CLSIDFromString((LPWSTR)szNic, &Guid); if (FAILED(hr)) { TRACE_CRIT( "CWlbsControl::Initialize failed at CLSIDFromString %ws", szNic ); Status = WBEM_E_INVALID_PARAMETER; goto end; } TRACE_INFO("Going to stop cluster on NIC %ws...", szNic); DWORD dwRet = g_CfgUtils.m_pWlbsControl->LocalClusterControl( Guid, ioctl ); TRACE_INFO("Stop cluster returned with wlbs error 0x%08lx", dwRet);
Status = WBEM_NO_ERROR;
switch(dwRet) { case WLBS_ALREADY: break; case WLBS_CONVERGED: break; case WLBS_CONVERGING: break; case WLBS_DEFAULT: break; case WLBS_DRAIN_STOP: break; case WLBS_DRAINING: break; case WLBS_OK: break; case WLBS_STOPPED: break; case WLBS_SUSPENDED: break; case WLBS_BAD_PARAMS: Status = WBEM_E_INVALID_PARAMETER; break; default: Status = WBEM_E_CRITICAL_ERROR; break; }
end:
return Status; }
//
// Initializes pParams using default values.
//
VOID CfgUtilInitializeParams( OUT WLBS_REG_PARAMS *pParams ) { //
// We don't expect WlbsSetDefaults to fail (it should have been
// defined returning VOID.
//
DWORD dwRet;
dwRet = WlbsSetDefaults(pParams);
if (dwRet != WLBS_OK) { ZeroMemory(pParams, sizeof(*pParams)); TRACE_CRIT("Internal error: WlbsSetDefaults failed"); ASSERT(FALSE); } }
WBEMSTATUS CfgUtilSafeArrayFromStrings( IN LPCWSTR *pStrings, IN UINT NumStrings, OUT SAFEARRAY **ppSA ) /*
Allocates and returns a SAFEARRAY of strings -- strings are copies of the passed in values.
Call SafeArrayDestroy when done with the array. */ { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; SAFEARRAY *pSA = NULL; HRESULT hr; LONG Index = 0;
*ppSA = NULL;
//
// Create safe array for the parameter values
//
pSA = SafeArrayCreateVector( VT_BSTR, 0, // lower bound
NumStrings // size of the fixed-sized vector.
); if (pSA == NULL) { TRACE_CRIT("Could not create safe array"); Status = WBEM_E_OUT_OF_MEMORY; goto end; }
//
// Place the strings into the safe array
//
{ for (Index = 0; Index<NumStrings; Index++) { LPCWSTR sz = pStrings[Index];
//
// SafeArrayPutElement expects the string passed in to
// be of type BSTR, which is of type wchar *, except, that
// the first 2 wchars contains length and other(?)
// information. This is why you can't simply pass in sz.
//
// So to get this we initalize an object of type _bstr_t
// based on sz. On initializaton, bstrValue allocates memory
// and copies the string.
//
_bstr_t bstrValue = sz; wchar_t *pwchar = (wchar_t *) bstrValue; // returns internal pointer.
// bpStr[Index] = sz; // may work as well.
//
// SafeArrayPutElement internally allocates space for pwchar and
// copies over the string.
// So pSA doesn't contain a direct reference to pwchar.
//
hr = SafeArrayPutElement(pSA, &Index, pwchar); if (FAILED(hr)) { TRACE_CRIT("Unable to put element %wsz", sz); (VOID) SafeArrayUnaccessData(pSA); goto end; }
//
// I think that bstrValue's contents are deallocated on exit of
// this block.
//
} } Status = WBEM_NO_ERROR; end:
if (FAILED(Status)) { if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; } }
*ppSA = pSA;
return Status; }
WBEMSTATUS CfgUtilStringsFromSafeArray( IN SAFEARRAY *pSA, OUT LPWSTR **ppStrings, OUT UINT *pNumStrings ) /*
Extracts copies of the strings in the passed-in safe array. Free *pStrings using the delete operator when done. NOTE: Do NOT delete the individual strings -- they are stored in the memory allocated for pStrings. */ { WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY; LPWSTR *pStrings = NULL; LPCWSTR csz; LPWSTR sz; UINT NumStrings = 0; UINT u; HRESULT hr; BSTR *pbStr =NULL; UINT TotalSize =0; LONG UBound = 0;
*ppStrings = NULL; *pNumStrings = 0;
hr = SafeArrayGetUBound(pSA, 1, &UBound); if (FAILED(hr)) { TRACE_CRIT("Could not get upper bound of safe array"); goto end; } NumStrings = (UINT) (UBound+1); // Convert from UpperBound to NumStrings.
if (NumStrings == 0) { // nothing in array -- we're done.
Status = WBEM_NO_ERROR; goto end;
}
hr = SafeArrayAccessData(pSA, ( void **) &pbStr); if (FAILED(hr)) { TRACE_CRIT("Could not access data of safe array"); goto end; }
//
// Calculate space for the array of pointers to strings...
//
TotalSize = NumStrings*sizeof(LPWSTR);
//
// Calculate space for the strings themselves...
//
for (u=0; u<NumStrings; u++) { csz = pbStr[u]; TotalSize += (wcslen(csz)+1)*sizeof(WCHAR); }
//
// Allocate space for *both* the array of pointers and the strings
// in one shot -- we're doing a new of type LPWSTR[] for the whole
// lot, so need to specify the size in units of LPWSTR (with an
// additional +1 in case there's roundoff.
//
pStrings = new LPWSTR[(TotalSize/sizeof(LPWSTR))+1]; if (pStrings == NULL) { Status = WBEM_E_OUT_OF_MEMORY; (VOID) SafeArrayUnaccessData(pSA); goto end; }
//
// Make sz point to the start of the place where we'll be placing
// the string data.
//
sz = (LPWSTR) (pStrings+NumStrings); for (u=0; u<NumStrings; u++) { csz = pbStr[u]; UINT len = wcslen(csz)+1; CopyMemory(sz, csz, len*sizeof(WCHAR)); pStrings[u] = sz; sz+=len; }
(VOID) SafeArrayUnaccessData(pSA); Status = WBEM_NO_ERROR;
end:
pbStr=NULL; if (FAILED(Status)) { if (pStrings!=NULL) { delete pStrings; pStrings = NULL; } NumStrings = 0; }
*ppStrings = pStrings; *pNumStrings = NumStrings;
return Status; }
WBEMSTATUS CfgUtilGetWmiObjectInstance( IN IWbemServicesPtr spWbemServiceIF, IN LPCWSTR szClassName, IN LPCWSTR szPropertyName, IN LPCWSTR szPropertyValue, OUT IWbemClassObjectPtr &sprefObj // smart pointer
) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; HRESULT hr;
//
// TODO: consider using IWbemServices::ExecQuery
//
IEnumWbemClassObjectPtr spEnum=NULL; // smart pointer
IWbemClassObjectPtr spObj = NULL; // smart pointer.
_bstr_t bstrClassName = szClassName;
//
// get all instances of object
//
hr = spWbemServiceIF->CreateInstanceEnum( bstrClassName, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &spEnum ); if (FAILED(hr)) { TRACE_CRIT("IWbemServices::CreateInstanceEnum failure\n" ); spEnum = NULL; goto end; }
//
// Look for the object with the matching property.
//
do { ULONG count = 1; hr = spEnum->Next( INFINITE, 1, &spObj, &count ); //
// Note -- Next() returns S_OK if number asked == number returned.
// and S_FALSE if number asked < than number requested.
// Since we're asking for only ...
//
if (hr == S_OK) { LPWSTR szEnumValue = NULL;
Status = get_string_parameter( spObj, szPropertyName, &szEnumValue // Delete when done.
); if (FAILED(Status)) { //
// Ignore this failure here.
//
} else if (szEnumValue!=NULL) { BOOL fFound = FALSE; if (!_wcsicmp(szEnumValue, szPropertyValue)) { fFound = TRUE; } delete szEnumValue;
if (fFound) { break; // BREAK BREAK BREAK BREAK
}
} } else { TRACE_INFO( "====0x%p->Next() returns Error 0x%lx; count=0x%lu", (PVOID) spObj, (UINT) hr, count); }
//
// Since I don't fully trust smart pointers, I'm specifically
// setting spObj to NULL here...
//
spObj = NULL; // smart pointer
} while (hr == S_OK);
if (spObj == NULL) { //
// We couldn't find a NIC which matches the one asked for...
//
Status = WBEM_E_NOT_FOUND; goto end; }
end:
if (FAILED(Status)) { sprefObj = NULL; } else { sprefObj = spObj; // smart pointer.
}
return Status; }
WBEMSTATUS CfgUtilGetWmiRelPath( IN IWbemClassObjectPtr spObj, OUT LPWSTR * pszRelPath // free using delete
) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; LPWSTR pRelPath = NULL;
//
// Extract the relative path, needed for ExecMethod.
//
Status = get_string_parameter( spObj, L"__RELPATH", // szParameterName
&pRelPath // Delete when done.
); if (FAILED(Status)) { TRACE_CRIT("Couldn't get rel path"); pRelPath = NULL; goto end; } else { if (pRelPath==NULL) { ASSERT(FALSE); // we don't expect this!
goto end; } TRACE_CRIT("GOT RELATIVE PATH %ws", pRelPath); }
end: *pszRelPath = pRelPath;
return Status; }
WBEMSTATUS CfgUtilGetWmiInputInstanceAndRelPath( IN IWbemServicesPtr spWbemServiceIF, IN LPCWSTR szClassName, IN LPCWSTR szPropertyName, // NULL: return Class rel path
IN LPCWSTR szPropertyValue, IN LPCWSTR szMethodName, OUT IWbemClassObjectPtr &spWbemInputInstance, // smart pointer
OUT LPWSTR * pszRelPath // free using delete
) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; IWbemClassObjectPtr spClassObj = NULL; // smart pointer
HRESULT hr; LPWSTR pRelPath = NULL;
TRACE_INFO(L"-> %!FUNC!(PropertyValue=%ws)", szPropertyValue);
//
// Get CLASS object
//
{ hr = spWbemServiceIF->GetObject( _bstr_t(szClassName), 0, NULL, &spClassObj, NULL );
if (FAILED(hr)) { TRACE_CRIT("Couldn't get nic class object pointer"); Status = (WBEMSTATUS)hr; goto end; } }
//
// Get WMI path to specific object
//
if (szPropertyName == NULL) { // Get WMI path to the class
Status = CfgUtilGetWmiRelPath( spClassObj, &pRelPath ); if (FAILED(Status)) { goto end; } } else { IWbemClassObjectPtr spObj = NULL; // smart pointer
pRelPath = NULL;
Status = CfgUtilGetWmiObjectInstance( spWbemServiceIF, szClassName, szPropertyName, szPropertyValue, spObj // smart pointer, passed by ref
); if (FAILED(Status)) { ASSERT(spObj == NULL); goto end; }
Status = CfgUtilGetWmiRelPath( spObj, &pRelPath ); spObj = NULL; // smart pointer
if (FAILED(Status)) { goto end; } }
//
// Get the input parameters to the call to the method
//
{ IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
// check if any input parameters specified.
hr = spClassObj->GetMethod( szMethodName, 0, &spWbemInput, NULL ); if(FAILED(hr)) { TRACE_CRIT("IWbemClassObject::GetMethod failure"); Status = (WBEMSTATUS) hr; goto end; } if (spWbemInput != NULL) { hr = spWbemInput->SpawnInstance( 0, &spWbemInputInstance ); if( FAILED( hr) ) { TRACE_CRIT("IWbemClassObject::SpawnInstance failure. Unable to spawn instance." ); Status = (WBEMSTATUS) hr; goto end; } } else { //
// This method has no input arguments!
//
spWbemInputInstance = NULL; }
}
Status = WBEM_NO_ERROR;
end:
if (FAILED(Status)) { if (pRelPath != NULL) { delete pRelPath; pRelPath = NULL; } }
*pszRelPath = pRelPath;
TRACE_INFO(L"<- %!FUNC!(Obj=%ws) returns 0x%08lx", szPropertyValue, (UINT) Status);
return Status; }
WBEMSTATUS CfgUtilGetWmiStringParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT LPWSTR *ppStringValue ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; WCHAR *pStringValue = NULL; try {
_variant_t v_value; CIMTYPE v_type; HRESULT hr; hr = spObj->Get( _bstr_t(szParameterName), // Name
0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the Setting ID field!
//
TRACE_CRIT( "get_str_parm:Couldn't retrieve %ws from 0x%p. Hr=0x%08lx", szParameterName, (PVOID) spObj, hr ); goto end; } else if (v_type == VT_NULL) { pStringValue = NULL; Status = WBEM_NO_ERROR; goto end; } else { if (v_type != VT_BSTR) { TRACE_CRIT( "get_str_parm: Parm value not of string type %ws from 0x%p", szParameterName, (PVOID) spObj ); Status = WBEM_E_INVALID_PARAMETER; } else { _bstr_t bstrNicGuid(v_value); LPCWSTR sz = bstrNicGuid; // Pointer to internal buffer.
if (sz==NULL) { // hmm.. null value
pStringValue = NULL; Status = WBEM_NO_ERROR; } else { UINT len = wcslen(sz); pStringValue = new WCHAR[len+1]; if (pStringValue == NULL) { TRACE_CRIT("get_str_parm: Alloc failure!"); Status = WBEM_E_OUT_OF_MEMORY; } else { CopyMemory(pStringValue, sz, (len+1)*sizeof(WCHAR)); Status = WBEM_NO_ERROR; } } TRACE_VERB( "get_str_parm: String parm %ws of 0x%p is %ws", szParameterName, (PVOID) spObj, (sz==NULL) ? L"<null>" : sz ); } v_value.Clear(); // Must be cleared after each call to Get.
}
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); WBEMSTATUS Status = WBEM_E_NOT_FOUND; }
end:
if (!FAILED(Status) && pStringValue == NULL) { //
// We convert a NULL value to an empty, not NULL string.
//
pStringValue = new WCHAR[1]; if (pStringValue == NULL) { Status = WBEM_E_OUT_OF_MEMORY; } else { *pStringValue = 0; Status = WBEM_NO_ERROR; } }
*ppStringValue = pStringValue;
return Status;
}
WBEMSTATUS CfgUtilSetWmiStringParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN LPCWSTR szValue ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
try {
HRESULT hr; _bstr_t bstrName = szParameterName; _variant_t v_value = (LPWSTR) szValue; // Allocates.
hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
); v_value.Clear(); if (FAILED(hr)) { TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR; //
// I think bstrName releases the internally allocated string
// on exiting this block.
//
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_INVALID_PARAMETER; }
end:
return Status; }
WBEMSTATUS CfgUtilGetWmiStringArrayParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT LPWSTR **ppStrings, OUT UINT *pNumStrings ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND;
try { _variant_t v_value; CIMTYPE v_type; HRESULT hr; LONG count = 0; *ppStrings = NULL; *pNumStrings = 0; hr = spObj->Get( _bstr_t(szParameterName), 0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the requested parameter.
//
TRACE_CRIT( "get_multi_str_parm:Couldn't retrieve %ws from 0x%p", szParameterName, (PVOID) spObj ); Status = WBEM_E_INVALID_PARAMETER; goto end; } if (v_type != (VT_ARRAY | VT_BSTR)) {
if (v_type == VT_NULL) { //
// We convert a NULL value to zero strings
//
Status = WBEM_NO_ERROR; goto end; } TRACE_CRIT("vt is not of type string!"); goto end; } else { VARIANT ipsV = v_value.Detach(); SAFEARRAY *pSA = ipsV.parray; Status = CfgUtilStringsFromSafeArray( pSA, ppStrings, pNumStrings ); VariantClear( &ipsV ); } } catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_NOT_FOUND; }
end:
return Status; }
WBEMSTATUS CfgUtilSetWmiStringArrayParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN LPCWSTR *ppStrings, IN UINT NumStrings ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR; SAFEARRAY *pSA = NULL;
try {
HRESULT hr; LONG Index = 0; Status = CfgUtilSafeArrayFromStrings( ppStrings, NumStrings, &pSA ); if (FAILED(Status)) { pSA = NULL; goto end; } //
// Put the parameter.
//
{ VARIANT V; _bstr_t bstrName = szParameterName; VariantInit(&V); V.vt = VT_ARRAY | VT_BSTR; V.parray = pSA; _variant_t v_value; v_value.Attach(V); // Takes owhership of V. V now becomes empty.
ASSERT(V.vt == VT_EMPTY); pSA = NULL; // should be no need to delete this explicitly now.
// v_value.Clear() should delete it, I think.
hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
); v_value.Clear(); if (FAILED(hr)) { Status = (WBEMSTATUS) hr; TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR; }
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_INVALID_PARAMETER; }
end:
if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; }
return Status; }
WBEMSTATUS CfgUtilGetWmiDWORDParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT DWORD *pValue ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; DWORD Value=0;
try { _variant_t v_value; CIMTYPE v_type; HRESULT hr; hr = spObj->Get( _bstr_t(szParameterName), // Name
0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the parameter
//
TRACE_CRIT( "GetDWORDParm:Couldn't retrieve %ws from 0x%p", szParameterName, (PVOID) spObj ); goto end; } else { Value = (DWORD) (long) v_value; v_value.Clear(); // Must be cleared after each call to Get.
Status = WBEM_NO_ERROR; }
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_NOT_FOUND; }
end:
*pValue = Value;
return Status;
}
WBEMSTATUS CfgUtilSetWmiDWORDParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN DWORD Value ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
try {
HRESULT hr; _bstr_t bstrName = szParameterName; _variant_t v_value = (long) Value; hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
); v_value.Clear(); if (FAILED(hr)) { TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR;
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_INVALID_PARAMETER; }
end:
return Status; }
WBEMSTATUS CfgUtilGetWmiBoolParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, OUT BOOL *pValue ) { WBEMSTATUS Status = WBEM_E_NOT_FOUND; BOOL Value=0;
try { _variant_t v_value; CIMTYPE v_type; HRESULT hr; hr = spObj->Get( _bstr_t(szParameterName), // Name
0, // Reserved, must be 0
&v_value, // Place to store value
&v_type, // Type of value
NULL // Flavor (unused)
); if (FAILED(hr)) { // Couldn't read the parameter
//
TRACE_CRIT( "GetDWORDParm:Couldn't retrieve %ws from 0x%p", szParameterName, (PVOID) spObj ); goto end; } else { Value = ((bool) v_value)!=0; v_value.Clear(); // Must be cleared after each call to Get.
Status = WBEM_NO_ERROR; }
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_NOT_FOUND; }
end:
*pValue = Value;
return Status; }
WBEMSTATUS CfgUtilSetWmiBoolParam( IN IWbemClassObjectPtr spObj, IN LPCWSTR szParameterName, IN BOOL Value ) { WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
try { HRESULT hr; _bstr_t bstrName = szParameterName; _variant_t v_value = (long) Value; hr = spObj->Put( bstrName, // Parameter Name
0, // Must be 0
&v_value, 0 // Must be 0
); v_value.Clear(); if (FAILED(hr)) { TRACE_CRIT("Unable to put parameter %ws", szParameterName); goto end; } Status = WBEM_NO_ERROR;
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); Status = WBEM_E_INVALID_PARAMETER; }
end:
return Status; }
WBEMSTATUS CfgUtilConnectToServer( IN LPCWSTR szNetworkResource, // \\machinename\root\microsoftnlb \root\...
IN LPCWSTR szUser, IN LPCWSTR szPassword, IN LPCWSTR szAuthority, OUT IWbemServices **ppWbemService // deref when done.
) { HRESULT hr = WBEM_E_CRITICAL_ERROR; IWbemLocatorPtr spLocator=NULL; // Smart pointer
IWbemServices *pService=NULL;
try {
_bstr_t serverPath(szNetworkResource); *ppWbemService = NULL; hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &spLocator); if (FAILED(hr)) { TRACE_CRIT(L"CoCreateInstance IWebmLocator failed 0x%08lx ", (UINT)hr); goto end; }
for (int timesToRetry=0; timesToRetry<10; timesToRetry++) { hr = spLocator->ConnectServer( serverPath, // (szUser!=NULL) ? (_bstr_t(szUser)) : NULL,
_bstr_t(szUser), // (szPassword==NULL) ? NULL : _bstr_t(szPassword),
_bstr_t(szPassword), NULL, // Locale
0, // Security flags
//(szAuthority==NULL) ? NULL : _bstr_t(szAuthority),
_bstr_t(szAuthority), NULL, &pService );
if( !FAILED( hr) ) { break; }
//
// these have been found to be special cases where retrying may
// help. The errors below are not in any header file, and I searched
// the index2a sources for these constants -- no hits.
// TODO: file bug against WMI.
//
if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) ) { TRACE_CRIT(L"connectserver recoverable failure, retrying."); Sleep(500); } } if (FAILED(hr)) { TRACE_CRIT(L"Error 0x%08lx connecting to server", (UINT) hr); goto end; } else { TRACE_INFO(L"Successfully connected to server %s", serverPath); } // Set the proxy so that impersonation of the client occurs.
//
hr = CoSetProxyBlanket( pService, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
COLE_DEFAULT_PRINCIPAL, // NULL,
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, COLE_DEFAULT_AUTHINFO, // NULL,
EOAC_DEFAULT // EOAC_NONE
); if (FAILED(hr)) { TRACE_CRIT(L"Error 0x%08lx setting proxy blanket", (UINT) hr); goto end; } hr = WBEM_NO_ERROR;
} catch( _com_error e ) { TRACE_INFO(L"%!FUNC! -- com exception"); hr = WBEM_E_INVALID_PARAMETER; }
end:
spLocator = NULL; // smart pointer.
if (FAILED(hr)) { if (pService != NULL) { pService->Release(); pService=NULL; } }
*ppWbemService = pService;
return (WBEMSTATUS) hr; }
WBEMSTATUS CfgUtilsGetNlbCompatibleNics( OUT LPWSTR **ppszNics, OUT UINT *pNumNics, OUT UINT *pNumBoundToNlb // OPTIONAL
) { WBEMSTATUS Status = WBEM_NO_ERROR; BOOL fNetCfgInitialized = FALSE; MyNetCfg NetCfg; BOOL fBound = FALSE;
//
// Get and initialize interface to netcfg
//
Status = NetCfg.Initialize(FALSE); // TRUE == get write lock.
if (FAILED(Status)) { goto end; } fNetCfgInitialized = TRUE;
//
//
//
Status = NetCfg.GetNlbCompatibleNics( ppszNics, pNumNics, pNumBoundToNlb // OPTIONAL
);
end:
if (fNetCfgInitialized) { NetCfg.Deinitialize(); }
return Status; }
WBEMSTATUS CfgUtilGetWmiAdapterObjFromAdapterConfigurationObj( IN IWbemClassObjectPtr spObj, // smart pointer
OUT IWbemClassObjectPtr &spAdapterObj // smart pointer, by reference
) /*
We need to return the "Win32_NetworkAdapter" object associated with the "Win32_NetworkAdapterConfiguration" object.
We use the "Win32_NetworkAdapterSetting" object for this.
*/ { spAdapterObj = spObj; return WBEM_NO_ERROR; }
#if 0
HRESULT Test( IWbemClassObject * pNetworkAdapterIn) //
// FROM: nt\base\cluster\mgmt\cluscfg\server\cenumcluscfgipaddresses.cpp
//
{ #define ARRAYSIZE(_arr) (sizeof(_arr)/sizeof(_arr[0]))
#define TraceSysAllocString(_str) (NULL)
#define TraceSysFreeString( bstrQuery ) (0)
#define THR(_exp) S_OK
#define STHR(_exp) S_OK
#define STATUS_REPORT_STRING(_a, _b, _c, _d, _e) (0)
#define STATUS_REPORT( _a, _b, _c, _d) (0)
#define Assert ASSERT
#define HRETURN( hr ) return hr
HRESULT hr = S_OK; BSTR bstrQuery = NULL; BSTR bstrWQL = NULL; VARIANT var; WCHAR sz[ 256 ]; IEnumWbemClassObject * pConfigurations = NULL; ULONG ulReturned; IWbemClassObject * pConfiguration = NULL; int cFound = 0; BSTR bstrAdapterName = NULL; int idx;
VariantInit( &var );
bstrWQL = TraceSysAllocString( L"WQL" ); if ( bstrWQL == NULL ) { goto OutOfMemory; } // if:
hr = THR( HrGetWMIProperty( pNetworkAdapterIn, L"DeviceID", VT_BSTR, &var ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
_snwprintf( sz, ARRAYSIZE( sz ), L"Associators of {Win32_NetworkAdapter.DeviceID='%s'} where AssocClass=Win32_NetworkAdapterSetting", var.bstrVal );
bstrQuery = TraceSysAllocString( sz ); if ( bstrQuery == NULL ) { goto OutOfMemory; } // if:
VariantClear( &var );
hr = THR( HrGetWMIProperty( pNetworkAdapterIn, L"NetConnectionID", VT_BSTR, &var ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
bstrAdapterName = TraceSysAllocString( var.bstrVal ); if ( bstrAdapterName == NULL ) { goto OutOfMemory; } // if:
hr = THR( m_pIWbemServices->ExecQuery( bstrWQL, bstrQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pConfigurations ) ); if ( FAILED( hr ) ) { STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WMI_NetworkAdapterSetting_Qry_Failed, IDS_ERROR_WMI_NETWORKADAPTERSETTINGS_QRY_FAILED, bstrAdapterName, hr ); goto Cleanup; } // if:
for ( idx = 0; ; idx++ ) { hr = pConfigurations->Next( WBEM_INFINITE, 1, &pConfiguration, &ulReturned ); if ( ( hr == S_OK ) && ( ulReturned == 1 ) ) { //
// KB: 25-AUG-2000 GalenB
//
// WMI only supports one configuration per adapter!
//
Assert( idx < 1 );
VariantClear( &var );
hr = THR( HrGetWMIProperty( pConfiguration, L"IPEnabled", VT_BOOL, &var ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
//
// If this configuration is not for TCP/IP then skip it.
//
if ( ( var.vt != VT_BOOL ) || ( var.boolVal != VARIANT_TRUE ) ) { hr = S_FALSE; STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Non_Tcp_Config, IDS_WARNING__NON_TCP_CONFIG, bstrAdapterName, hr ); continue; } // if:
hr = STHR( HrSaveIPAddresses( bstrAdapterName, pConfiguration ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if:
//
// KB: 24-AUG-2000 GalenB
//
// If any configuration returns S_FALSE then we skip.
//
if ( hr == S_FALSE ) { pConfiguration->Release(); pConfiguration = NULL; continue; } // if:
cFound++; pConfiguration->Release(); pConfiguration = NULL; } // if:
else if ( ( hr == S_FALSE ) && ( ulReturned == 0 ) ) { hr = S_OK; break; } // else if:
else { STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WQL_Qry_Next_Failed, IDS_ERROR_WQL_QRY_NEXT_FAILED, bstrQuery, hr ); goto Cleanup; } // else:
} // for:
//
// If we didn't find any valid configurations then we should return S_FALSE
// to tell the caller to ingore that adpater.
//
if ( cFound == 0 ) { hr = S_FALSE; STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_No_Valid_TCP_Configs, IDS_WARNING_NO_VALID_TCP_CONFIGS, bstrAdapterName, hr ); } // if:
goto Cleanup;
OutOfMemory:
hr = THR( E_OUTOFMEMORY ); STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetAdapterConfiguration, IDS_ERROR_OUTOFMEMORY, hr );
Cleanup:
VariantClear( &var );
TraceSysFreeString( bstrQuery ); TraceSysFreeString( bstrWQL ); TraceSysFreeString( bstrAdapterName );
if ( pConfiguration != NULL ) { pConfiguration->Release(); } // if:
if ( pConfigurations != NULL ) { pConfigurations->Release(); } // if:
HRETURN( hr );
} //*** CEnumClusCfgIPAddresses::HrGetAdapterConfiguration
#endif // 0
|