|
|
/******************************************************************
Copyright (c) 1999 Microsoft Corporation
NlbsNic.CPP -- WMI provider class implementation
Generated by Microsoft WMI Code Generation Engine TO DO: - See individual function headers - When linking, make sure you link to framedyd.lib & msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail).
Description: ******************************************************************/
// History:
// --------
//
// Revised by : mhakim
// Date : 02-12-01
// Reason : Added password support.
//
// Revised by : mhakim
// Date : 02-16-01
// Reason : Added friendly name support.
//
// Reason : filling out version info. This was being not
// done previously in GetObject.
#include <fwcommon.h> // This must be the first include.
#include "private.h"
#include <winsock2.h>
#include "wlbsutil.h"
#include "nlbsnic.h"
#include "nlbsnic.tmh"
// using namespace std;
// MUsingCom com;
BOOL g_UpdateConfigurationEnabled = TRUE;
WBEMSTATUS ProvExecStaticMethod( const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvGetCompatibleAdapterGuids( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvGetClusterConfiguration( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvUpdateClusterConfiguration( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvQueryConfigurationUpdateStatus( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvControlCluster( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvGetClusterMembers( CInstance *pInParams, CInstance *pOutParams );
WBEMSTATUS ProvRegisterManagementApplication( CInstance *pInParams, CInstance *pOutParams ); WBEMSTATUS ProvUnregisterManagementApplication( CInstance *pInParams, CInstance *pOutParams );
// TO DO: Replace "NameSpace" with the appropriate namespace for your
// provider instance. For instance: "root\\default or "root\\cimv2".
// DONE : mhakim
//===================================================================
CNlbsNic MyNlbsNicSet (PROVIDER_NAME_NLBSNIC, L"root\\microsoftnlb") ;
// Property names
//===============
const static WCHAR* cszAdapterGuid = L"AdapterGuid" ; const static WCHAR* pDependent = L"Dependent" ; const static WCHAR* pFriendlyName = L"FriendlyName" ; const static WCHAR* pFullName = L"FullName" ; const static WCHAR* pVersion = L"Version" ;
/*****************************************************************************
* * FUNCTION : CNlbsNic::CNlbsNic * * DESCRIPTION : Constructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : Calls the Provider constructor. * *****************************************************************************/ CNlbsNic::CNlbsNic (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider(lpwszName, lpwszNameSpace), m_fDelayedInitializationComplete(FALSE) { HRESULT hr;
InitializeCriticalSection(&m_Lock);
//
// Static Initialization of the NlbConfigurationUpdate class.
//
NlbConfigurationUpdate::StaticInitialize();
}
/*****************************************************************************
* * FUNCTION : CNlbsNic::~CNlbsNic * * DESCRIPTION : Destructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : * *****************************************************************************/ CNlbsNic::~CNlbsNic () { // this->DelayedDeinitialize();
//
// Static Deinitialization the NlbConfigurationUpdate class.
//
NlbConfigurationUpdate::StaticDeinitialize();
DeleteCriticalSection(&m_Lock); }
BOOL CNlbsNic::DelayedInitialize(VOID) { BOOL fRet = FALSE;
mfn_Lock();
if (m_fDelayedInitializationComplete == FALSE) { WBEMSTATUS Status; Status = CfgUtilInitialize( TRUE, // TRUE == server
TRUE // TRUE == don't use ping
); if (!FAILED(Status)) { m_fDelayedInitializationComplete = TRUE; } }
fRet = m_fDelayedInitializationComplete;
mfn_Unlock();
return fRet; }
VOID CNlbsNic::DelayedDeinitialize(VOID) { mfn_Lock();
if (m_fDelayedInitializationComplete) { //
// Prepare NlbConfigurationUpdate for deinitialization.
//
NlbConfigurationUpdate::PrepareForDeinitialization();
//
// Deinitialize the configuration utilities
//
CfgUtilDeitialize();
m_fDelayedInitializationComplete = FALSE; }
mfn_Unlock();
return; }
/*****************************************************************************
* * FUNCTION : CNlbsNic::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * * INPUTS : A pointer to the MethodContext for communication with WinMgmt. * A long that contains the flags described in * IWbemServices::CreateInstanceEnumAsync. Note that the following * flags are handled by (and filtered out by) WinMgmt: * WBEM_FLAG_DEEP * WBEM_FLAG_SHALLOW * WBEM_FLAG_RETURN_IMMEDIATELY * WBEM_FLAG_FORWARD_ONLY * WBEM_FLAG_BIDIRECTIONAL * * RETURNS : WBEM_S_NO_ERROR if successful * * COMMENTS : TO DO: All instances on the machine should be returned here and * all properties that this class knows how to populate must * be filled in. If there are no instances, return * WBEM_S_NO_ERROR. It is not an error to have no instances. * If you are implementing a 'method only' provider, you * should remove this method. * DONE: mhakim * *****************************************************************************/ HRESULT CNlbsNic::EnumerateInstances ( MethodContext* pMethodContext, long lFlags ) { return WBEM_S_NO_ERROR; }
/*****************************************************************************
* * FUNCTION : CNlbsNic::GetObject * * DESCRIPTION : Find a single instance based on the key properties for the * class. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::GetObjectAsync. * * RETURNS : WBEM_S_NO_ERROR if the instance can be found * WBEM_E_NOT_FOUND if the instance described by the key properties * could not be found * WBEM_E_FAILED if the instance could be found but another error * occurred. * * COMMENTS : If you are implementing a 'method only' provider, you should * remove this method. * *****************************************************************************/ HRESULT CNlbsNic::GetObject ( CInstance* pInstance, long lFlags ) { return WBEM_E_NOT_FOUND; }
/*****************************************************************************
* * FUNCTION : CNlbsNic::ExecQuery * * DESCRIPTION : You are passed a method context to use in the creation of * instances that satisfy the query, and a CFrameworkQuery * which describes the query. Create and populate all * instances which satisfy the query. You may return more * instances or more properties than are requested and WinMgmt * will post filter out any that do not apply. * * INPUTS : A pointer to the MethodContext for communication with WinMgmt. * A query object describing the query to satisfy. * A long that contains the flags described in * IWbemServices::CreateInstanceEnumAsync. Note that the following * flags are handled by (and filtered out by) WinMgmt: * WBEM_FLAG_FORWARD_ONLY * WBEM_FLAG_BIDIRECTIONAL * WBEM_FLAG_ENSURE_LOCATABLE * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if queries not supported for * this class or if the query is too complex for this class * to interpret. The framework will call the EnumerateInstances * function instead and let Winmgmt post filter. * WBEM_E_FAILED if the query failed * WBEM_S_NO_ERROR if query was successful * * COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt * will call your enumerate function to get all the instances and perform the * filtering for you. Unless you expect SIGNIFICANT savings from implementing * queries, you should remove this method. You should also remove this method * if you are implementing a 'method only' provider. * *****************************************************************************/ HRESULT CNlbsNic::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags) { return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::PutInstance * * DESCRIPTION : PutInstance should be used in provider classes that can * write instance information back to the hardware or * software. For example: Win32_Environment will allow a * PutInstance to create or update an environment variable. * However, a class like MotherboardDevice will not allow * editing of the number of slots, since it is difficult for * a provider to affect that number. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::PutInstanceAsync. * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available * WBEM_E_FAILED if there is an error delivering the instance * WBEM_E_INVALID_PARAMETER if any of the instance properties * are incorrect. * WBEM_S_NO_ERROR if instance is properly delivered * * COMMENTS : TO DO: If you don't intend to support writing to your provider, * or are creating a 'method only' provider, remove this * method. * *****************************************************************************/ HRESULT CNlbsNic::PutInstance ( const CInstance &Instance, long lFlags) { // Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CNlbsNic::DeleteInstance * * DESCRIPTION : DeleteInstance, like PutInstance, actually writes information * to the software or hardware. For most hardware devices, * DeleteInstance should not be implemented, but for software * configuration, DeleteInstance implementation is plausible. * * INPUTS : A pointer to a CInstance object containing the key properties. * A long that contains the flags described in * IWbemServices::DeleteInstanceAsync. * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available. * WBEM_E_FAILED if there is an error deleting the instance. * WBEM_E_INVALID_PARAMETER if any of the instance properties * are incorrect. * WBEM_S_NO_ERROR if instance is properly deleted. * * COMMENTS : TO DO: If you don't intend to support deleting instances or are * creating a 'method only' provider, remove this method. * *****************************************************************************/ HRESULT CNlbsNic::DeleteInstance ( const CInstance &Instance, long lFlags ) { // Use the CInstance Get functions (for example, call
// GetCHString(L"Name", sTemp)) against Instance to see the key values
// the client requested.
return (WBEM_E_PROVIDER_NOT_CAPABLE); }
BOOL g_Impersonate = TRUE;
/*****************************************************************************
* * FUNCTION : CNlbsNic::ExecMethod * * DESCRIPTION : Override this function to provide support for methods. * A method is an entry point for the user of your provider * to request your class perform some function above and * beyond a change of state. (A change of state should be * handled by PutInstance() ) * * INPUTS : A pointer to a CInstance containing the instance the method was executed against. * A string containing the method name * A pointer to the CInstance which contains the IN parameters. * A pointer to the CInstance to contain the OUT parameters. * A set of specialized method flags * * RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class * WBEM_S_NO_ERROR if method executes successfully * WBEM_E_FAILED if error occurs executing method * * COMMENTS : TO DO: If you don't intend to support Methods, remove this method. * *****************************************************************************/ HRESULT CNlbsNic::ExecMethod ( const CInstance& Instance, const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams, long lFlags) { // For non-static methods, use the CInstance Get functions (for example,
// call GetCHString(L"Name", sTemp)) against Instance to see the key
// values the client requested.
HRESULT hresult = WBEM_E_PROVIDER_NOT_CAPABLE; BOOL fImpersonating = FALSE;
TRACE_INFO("-> %!FUNC! Method Name : %ls", bstrMethodName);
if (!DelayedInitialize()) { TRACE_CRIT("%!FUNC! -- delayed initialization failed!"); goto end; }
//
// The NLB Manager provider runs under the context of "NetworkServiceHost" and hence
// may NOT have sufficient privileges to perform sensitive operations (like binding/
// unbinding NLB). So, we impersonate the client in order to use the client's (potentially
// higher) credentials to perform such operations.
//
hresult = CoImpersonateClient();
// 2/13/02 JosephJ SECURITY BUGBUG: is this check for RPC_E_CALL_COMPLETE
// ok?
if (hresult != S_OK && hresult != RPC_E_CALL_COMPLETE) { TRACE_CRIT("%!FUNC! ERROR: CoImpersonateClient returns 0x%08lx", (UINT) hresult); goto end; }
fImpersonating = TRUE;
// Adding this assert since we are not sure if RPC_E_CALL_COMPLETE
// could be a legitimate error. - KarthicN, 4/12/02.
ASSERT(hresult != RPC_E_CALL_COMPLETE);
// Check if caller is an administrator?
if (mfn_IsCallerAdmin() == FALSE) { TRACE_CRIT("%!FUNC! IsCallerAdmin() returned FALSE, returning WBEM_E_ACCESS_DENIED"); hresult= WBEM_E_ACCESS_DENIED; goto end; }
if (!g_Impersonate) { // Revert to using server credentials
CoRevertToSelf(); fImpersonating = FALSE; }
hresult = ProvExecStaticMethod(bstrMethodName, pInParams, pOutParams);
end:
if (fImpersonating) { CoRevertToSelf(); }
TRACE_INFO("<- %!FUNC! return : 0x%08lx", (UINT)hresult);
return hresult; }
////////////////////////////////////////////////////////////////////////////////
//
// Name : IsCallerAdmin
// Description : This function checks if the caller is a member of the
// Administrators local group. Since the provider is acting on
// behalf of the client, it is important to IMPERSONATE the client
// BEFORE calling this function. Impersonating the client will ensure
// that this function checks if the client (& NOT this process that
// runs under the identity of NetworkServiceHost) is a member of
// the Administrators local group.
// Arguments : None.
// Return Value:
// TRUE - Caller is a member of Administrators local group.
// FALSE - Caller is NOT a member of Administrators local group.
////////////////////////////////////////////////////////////////////////////////
BOOL CNlbsNic::mfn_IsCallerAdmin(VOID) { BOOL bRet; PSID AdministratorsGroup; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
TRACE_VERB(L"->%!FUNC!");
//
// Allocate and Initialize SID for Administrators in the built-in system domain
//
bRet = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, // The built-in system domain (S-1-5-32)
DOMAIN_ALIAS_RID_ADMINS, // Local group used for administration of the domain
0, 0, 0, 0, 0, 0, &AdministratorsGroup); if(bRet) { //
// Is SID enabled in the impersonation token of the calling thread ?
//
if (!CheckTokenMembership(NULL, // Use the Impersonation token of the calling thread
AdministratorsGroup, &bRet)) { bRet = FALSE; TRACE_CRIT(L"%!FUNC! CheckTokenMembership() failed. Error : 0x%x", GetLastError()); } FreeSid(AdministratorsGroup); } else { TRACE_CRIT("%!FUNC! AllocateAndInitializeSid() failed. Error : 0x%x", GetLastError()); }
TRACE_VERB(L"<-%!FUNC! Returning %ls", bRet ? L"TRUE" : L"FALSE"); return bRet; }
////////////////////////////////////////////////////////////////////////////////
//
// Check_Load_Unload_Driver_Privilege
//
// Purpose: This function checks if the SE_LOAD_DRIVER_NAME (= "SeLoadDriverPrivilege")
// is enabled in the impersonation access token. If there is no impersonation
// access token and if the global impersonation flag is set to false (used for
// debug purposes), then we check the primary access token.
//
////////////////////////////////////////////////////////////////////////////////
BOOL Check_Load_Unload_Driver_Privilege() { PRIVILEGE_SET PrivilegeSet; DWORD dwError; LUID Luid; BOOL bResult = FALSE; HANDLE TokenHandle = NULL;
TRACE_INFO("->%!FUNC!");
// Look up the LUID for "SeLoadDriverPrivilege"
if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
SE_LOAD_DRIVER_NAME, // "SeLoadDriverPrivilege" : Load and unload device drivers
&Luid)) // receives LUID of privilege
{ TRACE_CRIT("%!FUNC! LookupPrivilegeValue error: %u", GetLastError()); TRACE_INFO("<-%!FUNC! Returning FALSE"); return FALSE; }
//
// Get a handle to the impersonation access token with TOKEN_QUERY right.
//
// Note: If this thread is NOT impersonating, then, the following call
// will fail with ERROR_NO_TOKEN.
//
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, // Use the credentials of the client that is being impersonated
&TokenHandle)) { dwError = GetLastError();
//
// We were unable to open the impersonation access token. If it is because it doesn't
// exist and if the "g_Impersonate" flag is set to FALSE , then try to open the primary
// access token.
// This blob is mainly to handle the case where we are intentionally NOT
// impersonating by setting the "g_Impersonate" to FALSE. This flag was introduced
// mainly to easily switch between impersonating and not impersonating for debugging
// purposes. This was needed due to the problems that we encountered when impersonating
// + using "NetworkServiceHost".
// --KarthicN, May 6, 2002.
//
if ((dwError == ERROR_NO_TOKEN) && (g_Impersonate == FALSE)) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &TokenHandle)) { TRACE_CRIT("%!FUNC! OpenProcessToken error: %u", GetLastError()); TRACE_INFO("<-%!FUNC! Returning FALSE"); return FALSE; } } else { TRACE_CRIT("%!FUNC! OpenThreadToken error: %u, Global Impersonation flag = %ls", dwError, g_Impersonate ? L"TRUE" : L"FALSE"); TRACE_INFO("<-%!FUNC! Returning FALSE"); return FALSE; } }
PrivilegeSet.PrivilegeCount = 1; PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; PrivilegeSet.Privilege[0].Luid = Luid; PrivilegeSet.Privilege[0].Attributes = 0;
if (!PrivilegeCheck(TokenHandle, &PrivilegeSet, &bResult)) { bResult = FALSE; TRACE_CRIT("%!FUNC! PrivilegeCheck error: %u", GetLastError()); }
CloseHandle(TokenHandle);
TRACE_INFO(L"<-%!FUNC! Returning %ls", bResult ? L"TRUE" : L"FALSE"); return bResult; }
WBEMSTATUS ProvExecStaticMethod( const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams ) /*
If bstrMethodName is one of the recognized static methods, we execute the method. Otherwise we return WBEM_E_PROVIDER_NOT_CAPABLE */ { WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
if (!g_UpdateConfigurationEnabled) { goto end; }
if (_wcsicmp(bstrMethodName, L"GetCompatibleAdapterGuids") == 0) { Status = ProvGetCompatibleAdapterGuids( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"GetClusterConfiguration") == 0) { Status = ProvGetClusterConfiguration( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"UpdateClusterConfiguration") == 0) { //
// NOTE:
// One of the functions of this method is to bind/unbind NLB to the network adapter. Since this operation involves unloading
// and loading of the device driver, PnP apis (that are called), attempt to enable the "SeLoadDriverPrivilege"
// privilege in the impersonation access token. Enabling a privilege is successful only when the privilege is present,
// in the first place to be enabled. When the wmi client and wmi provider are in the same machine, it was observed that
// the "SeLoadDriverPrivilege" privilege was NOT event present in the impersonation access token of the server. This is
// because, only the enabled privileges of the client are passed along to the server.
// So, we now require that the client enable the "SeLoadDriverPrivilege" privilege in its access token before calling
// this method. The following call to Check_Load_Unload_Driver_Privilege() checks if "SeLoadDriverPrivilege" privilege
// is enabled in the impersonation access token (except if "g_Impersonate" is false). Although the PnP apis only
// require that this privilege be present, we have decided to elevate the requirement to this privilege being present
// AND enabled. This is because, if the privilege is NOT enabled, the operation to enable it may or may not succeed
// depending on the client's credentials.
// --KarthicN, May 6, 2002.
//
if(!Check_Load_Unload_Driver_Privilege()) { TRACE_CRIT("%!FUNC! Check_Load_Unload_Driver_Privilege() failed, Returning WBEM_E_ACCESS_DENIED !!!"); Status = WBEM_E_ACCESS_DENIED; goto end; }
Status = ProvUpdateClusterConfiguration( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"QueryConfigurationUpdateStatus") == 0) { Status = ProvQueryConfigurationUpdateStatus( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"ControlCluster") == 0) { Status = ProvControlCluster( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"GetClusterMembers") == 0) { Status = ProvGetClusterMembers( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"RegisterManagementApplication") == 0) { Status = ProvRegisterManagementApplication( pInParams, pOutParams ); } else if (_wcsicmp(bstrMethodName, L"UnregisterManagementApplication") == 0) { Status = ProvUnregisterManagementApplication( pInParams, pOutParams ); } end:
return Status; }
WBEMSTATUS ProvGetCompatibleAdapterGuids( CInstance *pInParams, CInstance *pOutParams ) /*++
Implementation of the "GetCompatibleAdapterGuids" method.
--*/ {
LPWSTR *pszNics = NULL; UINT NumNics = 0; UINT NumNlbBound = 0; WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE;
/*
[OUT] String AdapterGuids[], // "{......}"
[OUT] uint32 NumBoundToNlb */
TRACE_VERB(L"->%!FUNC!");
Status = CfgUtilsGetNlbCompatibleNics(&pszNics, &NumNics, &NumNlbBound);
if (FAILED(Status)) { TRACE_CRIT("CfgUtilsGetNlbCompatibleNics returns error 0x%08lx", (UINT) Status); pszNics = NULL; goto end; }
//
// Fill in AdapterGuids[]
//
{ SAFEARRAY *pSA = NULL; Status = CfgUtilSafeArrayFromStrings( (LPCWSTR*) pszNics, NumNics, &pSA ); if (FAILED(Status)) { pSA = NULL; goto end; }
pOutParams->SetStringArray( L"AdapterGuids", *pSA // pass by reference
); SafeArrayDestroy(pSA); pSA = NULL; } pOutParams->SetDWORD(L"NumBoundToNlb", NumNlbBound); Status = WBEM_NO_ERROR;
end:
pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
if (pszNics != NULL) { delete pszNics; pszNics = NULL; }
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return WBEM_NO_ERROR; // real status is in the "ReturnResult" outparm.
}
WBEMSTATUS ProvGetClusterConfiguration( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::GetConfiguration
--*/ { LPCWSTR pAdapterGuid = NULL; WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sTemp; bool fRet; NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg; SAFEARRAY *pSA = NULL; bool fNicNotFound = FALSE;
/*
[IN] String AdapterGuid, [OUT] uint32 Generation, [OUT] String NetworkAddresses[], // "10.1.1.1/255.0.0.0"
[OUT] Boolean NLBBound, [OUT] Boolean DHCPEnabled, [OUT] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
[OUT] String ClusterName, [OUT] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
[OUT] String PortRules[], [OUT] uint32 HostPriority, [OUT] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
[OUT] uint32 ClusterModeOnStart, // 0 : STOPPED, 1 : STARTED, 2 : SUSPENDED
[OUT] Boolean PersistSuspendOnReboot, [OUT] Boolean RemoteControlEnabled, [OUT] uint32 HashedRemoteControlPassword */
fRet = pInParams->GetCHString( L"AdapterGuid", sTemp ); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sTemp;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else {
TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
Status = NlbConfigurationUpdate::GetConfiguration( pAdapterGuid, &Cfg );
if (FAILED(Status)) { if (Status == WBEM_E_NOT_FOUND) { fNicNotFound = TRUE; } goto end; }
pOutParams->SetDWORD(L"Generation", Cfg.GetGeneration());
//
// Fill in NetworkAddresses[]
//
{ Status = Cfg.GetNetworkAddressesSafeArray( &pSA ); if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: couldn't extract network addresses from Cfg" " for NIC %ws", pAdapterGuid ); pSA = NULL; goto end; }
if (pSA!=NULL) { pOutParams->SetStringArray( L"NetworkAddresses", *pSA // pass by reference
); SafeArrayDestroy(pSA); pSA = NULL; } }
//
// Adapter Friendly Name
//
{ LPWSTR szFriendlyName = NULL; Status = Cfg.GetFriendlyName(&szFriendlyName);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract adapter friendly name for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"FriendlyName", szFriendlyName); delete (szFriendlyName); szFriendlyName = NULL; }
//
// Set dhcp state
//
pOutParams->Setbool(L"DHCPEnabled", Cfg.fDHCP);
if (!Cfg.IsNlbBound()) { //
// NLB is not bound
//
pOutParams->Setbool(L"NLBBound", FALSE); Status = WBEM_NO_ERROR; goto end; }
//
// NLB is bound
//
pOutParams->Setbool(L"NLBBound", TRUE);
if (!Cfg.IsValidNlbConfig()) { TRACE_CRIT( "%!FUNC!: NLB-specific configuration on NIC %ws is invalid", pAdapterGuid ); goto end; }
//
// Cluster name
//
{ LPWSTR szName = NULL; Status = Cfg.GetClusterName(&szName);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract cluster name for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"ClusterName", szName); delete (szName); szName = NULL; } //
// Cluster and dedicated network addresses
//
{ LPWSTR szAddress = NULL; Status = Cfg.GetClusterNetworkAddress(&szAddress);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract cluster address for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"ClusterNetworkAddress", szAddress); delete (szAddress); szAddress = NULL;
Status = Cfg.GetDedicatedNetworkAddress(&szAddress);
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: Could not extract dedicated address for NIC %ws", pAdapterGuid ); goto end; } pOutParams->SetCHString(L"DedicatedNetworkAddress", szAddress); delete (szAddress); szAddress = NULL; }
//
// TrafficMode
//
{ LPCWSTR szMode = NULL; switch(Cfg.GetTrafficMode()) { case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST: szMode = L"UNICAST"; break; case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST: szMode = L"MULTICAST"; break; case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST: szMode = L"IGMPMULTICAST"; break; default: assert(FALSE); Status = WBEM_E_CRITICAL_ERROR; goto end; } pOutParams->SetCHString(L"TrafficMode", szMode); }
pOutParams->SetDWORD(L"HostPriority", Cfg.GetHostPriority());
/*
if (Cfg.GetClusterModeOnStart() == NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED) { pOutParams->Setbool(L"ClusterModeOnStart", TRUE); } else { pOutParams->Setbool(L"ClusterModeOnStart", FALSE); } */
pOutParams->SetDWORD(L"ClusterModeOnStart", Cfg.GetClusterModeOnStart());
pOutParams->Setbool(L"PersistSuspendOnReboot", Cfg.GetPersistSuspendOnReboot());
pOutParams->Setbool(L"RemoteControlEnabled", Cfg.GetRemoteControlEnabled()); pOutParams->SetDWORD( L"HashedRemoteControlPassword", CfgUtilGetHashedRemoteControlPassword(&Cfg.NlbParams) );
//
// [OUT] String PortRules[],
//
{
LPWSTR *pszPortRules = NULL; UINT NumPortRules = 0; pSA=NULL; Status = Cfg.GetPortRules( &pszPortRules, &NumPortRules ); if (FAILED(Status)) { pszPortRules = NULL; goto end; } Status = CfgUtilSafeArrayFromStrings( (LPCWSTR*) pszPortRules, NumPortRules, // can be zero
&pSA );
if (FAILED(Status)) { TRACE_CRIT( "%!FUNC!: couldn't extract port rules from Cfg" " for NIC %ws", pAdapterGuid ); pSA = NULL; goto end; }
if (pSA!=NULL) { pOutParams->SetStringArray( L"PortRules", *pSA // pass by reference
); SafeArrayDestroy(pSA); pSA = NULL; } }
Status = WBEM_NO_ERROR;
end:
if (FAILED(Status)) { //
// We want to reserve WBEM_NOT_FOUND for the SPECIFIC case
// of the NIC not being found
//
if (Status == WBEM_E_NOT_FOUND && !fNicNotFound) { Status = WBEM_E_FAILED; }
pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status);
} else { pOutParams->SetDWORD(L"ReturnValue", (DWORD) WBEM_NO_ERROR); }
if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; }
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return WBEM_NO_ERROR;
}
WBEMSTATUS ProvUpdateClusterConfiguration( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper NlbConfigurationUpdate::UpdateConfiguration with some additional wrinkles: we selectively update the current version.
--*/ { LPCWSTR pAdapterGuid = NULL; LPCWSTR pClientDescription = L"Unspecified WMI Client"; // TODO: localize
WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sClientDescription; CHString sAdapterGuid; CHString sTemp; bool fRet; NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg; SAFEARRAY *pSA = NULL;
/*
[IN] String ClientDescription, [IN] String AdapterGuid, [IN] uint32 Generation, [IN] Boolean PartialUpdate, [IN] String NetworkAddresses[], // "10.1.1.1/255.255.255.255"
[IN] Boolean NLBBound, [IN] String ClusterNetworkAddress, // "10.1.1.1/255.0.0.0"
[IN] String ClusterName, [IN] String TrafficMode, // UNICAST MULTICAST IGMPMULTICAST
[IN] String PortRules[], [IN] uint32 HostPriority, [IN] String DedicatedNetworkAddress, // "10.1.1.1/255.0.0.0"
[IN] uint32 ClusterModeOnStart, // 0 : STOPPED, 1 : STARTED, 2 : SUSPENDED
[IN] Boolean PersistSuspendOnReboot, [IN] Boolean RemoteControlEnabled, [IN] String Password, [OUT] uint32 NewGeneration, [OUT] String Log */
fRet = pInParams->GetCHString( L"ClientDescription", sClientDescription); if (fRet) { // Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
pClientDescription = (LPCWSTR) sClientDescription; }
fRet = pInParams->GetCHString( L"AdapterGuid", sAdapterGuid); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sAdapterGuid;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
//
// Get the current configuration
//
Status = NlbConfigurationUpdate::GetConfiguration( pAdapterGuid, &Cfg );
if (FAILED(Status)) { goto end; }
//
// Modify the snapshot of the current configuration with whatever
// cluster configuration information is specified in the input
// parameters
//
{ DWORD InGeneration = 0; bool NlbBound = FALSE; bool bResult = FALSE; bool bPartialUpdate = FALSE; bool bCheckForAddressConflicts = FALSE; //
// Determine if this is a partial or full update.
// If partial update, we allow a subset of cluster configuration
// parameters to be specified, but allow only a restricted set
// of update operations.
//
// Disallowed partial update operations:
// - Transitions between bound and !bound
// - Currently bound but nlb parameters are invalid
//
// Some allowed partial updates:
// - Modifying IP address lists
// - Modifying cluster / dedicated addresses/subnets
// - Modifying existing portrules
// - Adding/deleting port rules
//
bResult = pInParams->GetDWORD( L"Generation", // <--------------------------------
InGeneration ); if (!bResult) { //
// We allow generation to be unspecified.
//
InGeneration = 0; } else { //
// If generation is specified,
// we verify that the current generation matches the
// specified generation.
// TODO: this really must be done in the context of
// mfn_Start update -- after we've acquired the global lock!
//
if (InGeneration != Cfg.GetGeneration()) { TRACE_CRIT("Partial update: input generation(%lu) != current generation(%lu)", InGeneration, Cfg.GetGeneration()); Status = WBEM_E_HANDLE_OUT_OF_DATE; goto end; } }
bResult = pInParams->Getbool( L"CheckForAddressConflicts", // <--------------------------------
bCheckForAddressConflicts ); if (!bResult) { TRACE_CRIT(L"Could not read CheckForAddressConflicts -- assuming FALSE\n"); bCheckForAddressConflicts = FALSE;
}
bResult = pInParams->Getbool( L"NLBBound", // <--------------------------------
NlbBound ); if (!bResult) { NlbBound = Cfg.IsNlbBound(); TRACE_CRIT(L"Could not read NLBBound -- assuming current state %d.", NlbBound); }
bResult = pInParams->GetStringArray( L"NetworkAddresses", // <--------------------------------
pSA ); if (!bResult) { //
// We set pCfg to zero addresses, which causes update to
// use it's own defaults...
//
TRACE_CRIT(L"Could not read Network addresses -- using defaults"); Status = Cfg.SetNetworkAddresses(NULL, 0); pSA = NULL; } else { if (pSA != NULL) { Status = Cfg.SetNetworkAddressesSafeArray(pSA); SafeArrayDestroy(pSA); pSA = NULL; } }
if (!NlbBound) { // NLB is not to be bound -- no need to read the input params.
Cfg.fBound = FALSE; Cfg.fValidNlbCfg = FALSE; } else { BOOL fNewConfig = FALSE; bool bAddDedicatedIp = FALSE; bool bAddClusterIps = FALSE;
if (!Cfg.fBound || Cfg.fValidNlbCfg == FALSE) { //
// If we were previously unbound or we were bound but with
// a bad configuration, we need to setup our
// new cfg with good defaults
//
CfgUtilInitializeParams(&Cfg.NlbParams); Cfg.fBound = TRUE; Cfg.fValidNlbCfg = TRUE; fNewConfig = TRUE; }
bResult = pInParams->Getbool( L"AddDedicatedIp", // <------------------------
bAddDedicatedIp ); if (!bResult) { TRACE_CRIT(L"Could not read AddDedicatedIp -- assuming TRUE\n"); bAddDedicatedIp = TRUE; } Cfg.fAddDedicatedIp = (bAddDedicatedIp!=FALSE); bResult = pInParams->Getbool( L"AddClusterIps", // <-------------------------
bAddClusterIps ); if (!bResult) { TRACE_CRIT(L"Could not read AddClusterIps -- assuming TRUE\n"); bAddClusterIps = TRUE; } Cfg.fAddClusterIps = (bAddClusterIps!=FALSE); bResult = pInParams->GetCHString( L"ClusterNetworkAddress", // <--------------------
sTemp ); if (!bResult) { if (fNewConfig) { //
// Cluster address MUST be specified for new config.
//
TRACE_CRIT(L"ERROR: Could not read Cluster IP for new config."); Status = WBEM_E_INVALID_PARAMETER; goto end; } TRACE_CRIT(L"Could not read Cluster IP. Keeping existing."); } else { LPCWSTR szClusterNetworkAddress = NULL; szClusterNetworkAddress = (LPCWSTR) sTemp; // no copies here.
Cfg.SetClusterNetworkAddress(szClusterNetworkAddress); szClusterNetworkAddress = NULL; } bResult = pInParams->GetCHString( L"ClusterName", // <-------------------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not read Cluster Name. Keeping existing"); } else { LPCWSTR szClusterName = NULL; szClusterName = (LPCWSTR) sTemp; // no copies here.
Cfg.SetClusterName(szClusterName); szClusterName = NULL; } //
// Traffic mode
//
{ bResult = pInParams->GetCHString( L"TrafficMode", // <-------------------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not read TrafficMode. Keeping existing"); } else { LPCWSTR szTrafficMode = NULL; NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST; szTrafficMode = (LPCWSTR) sTemp; // no copies here.
if (!_wcsicmp(szTrafficMode, L"UNICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST; } else if (!_wcsicmp(szTrafficMode, L"MULTICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST; } else if (!_wcsicmp(szTrafficMode, L"IGMPMULTICAST")) { TrafficMode = NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST; } else { TRACE_CRIT("Invalid TrafficMode: %ws", szTrafficMode); Status = WBEM_E_INVALID_PARAMETER; goto end; }
Cfg.SetTrafficMode(TrafficMode); szTrafficMode = NULL; } } //
// String PortRules[]
//
bResult = pInParams->GetStringArray( L"PortRules", // <--------------------------------
pSA ); if (!bResult) { //
// We set pCfg to zero port rules
//
TRACE_CRIT(L"Could not read port rules-- assuming ZERO"); Status = Cfg.SetPortRules(NULL, 0); pSA = NULL; } else { if (pSA != NULL) { LPWSTR *pStrings=NULL; UINT NumStrings = 0;
Status = CfgUtilStringsFromSafeArray( pSA, &pStrings, // delete when done
&NumStrings ); if (FAILED(Status)) { pStrings=NULL; TRACE_CRIT(L"Could not extract port rules"); goto end; } Status = Cfg.SetPortRules( (LPCWSTR*)pStrings, NumStrings ); delete pStrings; SafeArrayDestroy(pSA); pSA = NULL; } }
DWORD HostPriority = 0; bResult = pInParams->GetDWORD( L"HostPriority", // <---------------------------
HostPriority ); if (!bResult) { TRACE_CRIT(L"Could not read HostPriority. Keeping existing"); } else { Cfg.SetHostPriority(HostPriority); } bResult = pInParams->GetCHString( L"DedicatedNetworkAddress", // <-----------------
sTemp ); if (!bResult) { TRACE_CRIT(L"Could not dedicated IP. Keeping existing"); } else { LPCWSTR szAddress = NULL; szAddress = (LPCWSTR) sTemp; // no copies here.
Cfg.SetDedicatedNetworkAddress(szAddress); szAddress = NULL; } //
// StartMode
//
{ DWORD ClusterModeOnStart = FALSE; bResult = pInParams->GetDWORD( L"ClusterModeOnStart", // <-----------------
ClusterModeOnStart ); if (!bResult) { TRACE_CRIT(L"Could not read StartMode. Keeping existing"); } else { /*
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE ClusterModeOnStart; if (StartMode) { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED; } else { ClusterModeOnStart = NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED; } */ Cfg.SetClusterModeOnStart(ClusterModeOnStart); } }
//
// Persist Suspend on Reboot
//
{ bool bPersistSuspendOnReboot; bResult = pInParams->Getbool( L"PersistSuspendOnReboot", // <---------------
bPersistSuspendOnReboot ); if (!bResult) { TRACE_CRIT(L"Could not read PersistSuspendOnReboot. Keeping existing"); } else { Cfg.SetPersistSuspendOnReboot(bPersistSuspendOnReboot); } }
//
// Remote control enabled
//
{ bool bRemoteControlEnabled; bResult = pInParams->Getbool( L"RemoteControlEnabled", // <---------------
bRemoteControlEnabled ); if (!bResult) { TRACE_CRIT(L"Could not read RemoteControlEnabled. Keeping existing"); } else { Cfg.SetRemoteControlEnabled(bRemoteControlEnabled!=FALSE);
if (bRemoteControlEnabled) { DWORD dwPwd; LPCWSTR szPwd = NULL; //
// Now read and set string or hashed version of password
// if either are specified.
//
bResult = pInParams->GetCHString( L"RemoteControlPassword", // <-----------------
sTemp );
if (bResult) { szPwd = (LPCWSTR) sTemp; // no copies here.
(VOID) CfgUtilSetRemotePassword(&Cfg.NlbParams, szPwd); }
if (szPwd == NULL) { //
// Only look for hashed pwd if the real pwd is
// not specified.
//
bResult = pInParams->GetDWORD( L"HashedRemoteControlPassword", // <-----------------
dwPwd ); if (bResult) { CfgUtilSetHashedRemoteControlPassword( &Cfg.NlbParams, dwPwd ); } } } } }
//
// TODO: if PartialUpdate is specified, we need to
// make sure that fValidNlbCfg is already set.
//
Cfg.fValidNlbCfg = TRUE; } while (FALSE) ;
}
//
// Call NlbConfigurationUpdate::DuUpdate to do the actual work.
//
UINT NewGeneration = 0; LPWSTR pLog = NULL;
try { Status = NlbConfigurationUpdate::DoUpdate( pAdapterGuid, pClientDescription, &Cfg, &NewGeneration, &pLog ); } catch (...) { TRACE_CRIT(L"%!FUNC! Caught exception!\n"); ASSERT(!"Caught exception!"); throw; }
//
// Fill out the out parameters: status new generation and log
//
pOutParams->SetDWORD(L"ReturnValue", (DWORD) Status); pOutParams->SetDWORD(L"NewGeneration", (DWORD) NewGeneration); if (pLog != NULL) { pOutParams->SetCHString(L"Log", pLog); delete pLog; pLog = NULL; }
//
// If we've actually called DoUpdate,
// we always return WBEM_NO_ERROR. The return value has the
// real result.
//
Status = WBEM_NO_ERROR;
end:
if (pSA!=NULL) { SafeArrayDestroy(pSA); pSA = NULL; }
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
WBEMSTATUS ProvQueryConfigurationUpdateStatus( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::GetUpdateStatus
--*/ { LPCWSTR pAdapterGuid = NULL; WBEMSTATUS Status = WBEM_E_PROVIDER_NOT_CAPABLE; CHString sTemp; bool fRet; DWORD Generation = 0;
/*
[IN] String AdapterGuid, [IN] uint32 Generation, [OUT] String Log */
fRet = pInParams->GetCHString( L"AdapterGuid", sTemp); if (!fRet) { TRACE_CRIT("->%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Note: (LPCWSTR) sTemp returns an internal pointer to sTemp's char
// buffer -- see operator LPCWSTR() of WString docs.
//
pAdapterGuid = (LPCWSTR) sTemp;
if (pAdapterGuid == NULL || *pAdapterGuid == 0) { TRACE_CRIT("->%!FUNC!: Null of empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { TRACE_VERB(L"->%!FUNC!(Nic=%ws)", pAdapterGuid); }
fRet = pInParams->GetDWORD( L"Generation", // <--------------------------------
Generation ); if (!fRet) { TRACE_CRIT("%!FUNC!: Missing generation!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Call NlbConfigurationUpdate::GetUpdateResult to do the actual work.
//
LPWSTR pLog = NULL; WBEMSTATUS CompletionStatus = WBEM_NO_ERROR;
Status = NlbConfigurationUpdate::GetUpdateStatus( pAdapterGuid, Generation, FALSE, // FALSE == Don't delete completion record
&CompletionStatus, &pLog );
if (!FAILED(Status)) { //
// Fill out the out parameters: status new generation and log
//
pOutParams->SetDWORD(L"ReturnValue", (DWORD) CompletionStatus); if (pLog != NULL) { pOutParams->SetCHString(L"Log", pLog); delete pLog; pLog = NULL; } }
end:
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
WBEMSTATUS ProvControlCluster( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
TODO: Implement NlbConfigurationUpdate::ProvControlCluster, which should be a wrapper around around WlbsControlCluster where the work is actually done (WlbsControlCluster will take the handle to the device).
--*/ { LPCWSTR szAdapterGuid, szVip; CHString sAdapterGuid, sVip; bool fRet; DWORD dwPort, dwRetVal, dwVip, dwHostMap, dwStatus; WBEMSTATUS Status; WLBS_OPERATION_CODES Opcode;
TRACE_VERB(L"->%!FUNC!");
dwRetVal = dwStatus = WLBS_FAILURE; dwHostMap = 0; Status = WBEM_NO_ERROR; szVip = NULL; dwVip = dwPort = 0;
// Get the Adapter GUID
fRet = pInParams->GetCHString(L"AdapterGuid", sAdapterGuid); if (!fRet) { TRACE_CRIT(L"%!FUNC!: Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { szAdapterGuid = (LPCWSTR) sAdapterGuid;
if (szAdapterGuid == NULL || *szAdapterGuid == UNICODE_NULL) { TRACE_CRIT(L"%!FUNC!: Null or empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } }
// Get the operation to be performed
DWORD dwOperation; fRet = pInParams->GetDWORD(L"Operation", dwOperation); if (!fRet) { TRACE_CRIT("%!FUNC!: Missing operation!"); Status = WBEM_E_INVALID_PARAMETER; goto end; }
Opcode = (WLBS_OPERATION_CODES)dwOperation;
// If present, get the Virtual IP Address
fRet = pInParams->GetCHString( L"VirtualIpAddress", sVip); if (fRet) { szVip = (LPCWSTR) sVip;
// Check for an empty string
if (szVip != NULL && *szVip == UNICODE_NULL) { szVip = NULL; } // Check for null
if (szVip != NULL) { // If the VIP is "All Vip", then, fill in the numeric value
// directly from the macro, else use the conversion function.
// This is 'cos INADDR_NONE, the return value of inet_addr
// function (called by IpAddressFromAbcdWsz) in the failure
// case, is equivalent to the numeric value of CVY_DEF_ALL_VIP
if (_wcsicmp(szVip, CVY_DEF_ALL_VIP) == 0) { dwVip = CVY_ALL_VIP_NUMERIC_VALUE; } else { dwVip = IpAddressFromAbcdWsz(szVip); if (dwVip == INADDR_NONE) { TRACE_CRIT("%!FUNC! Invalid value (%ls) passed for Vip",szVip); Status = WBEM_E_INVALID_PARAMETER; goto end; } } } }
// If present, Get the port number
// The return value fRet is used in the switch statement further down, so
// do NOT re-assign/change it
fRet = pInParams->GetDWORD(L"Port", dwPort);
switch(Opcode) { case WLBS_START: case WLBS_STOP: case WLBS_DRAIN: case WLBS_SUSPEND: case WLBS_RESUME: CfgUtilControlCluster( szAdapterGuid, Opcode, 0, 0, NULL, &dwRetVal ); CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwStatus ); // Fill the out parameter: Host Map
pOutParams->SetDWORD(L"HostMap", (DWORD) dwHostMap); break;
case WLBS_PORT_ENABLE: case WLBS_PORT_DISABLE: case WLBS_PORT_DRAIN: if ((szVip == NULL) || !fRet) { TRACE_CRIT("%!FUNC! Virtual IP Address or Port NOT passed for port operation : 0x%x", Opcode); Status = WBEM_E_INVALID_PARAMETER; goto end; } CfgUtilControlCluster( szAdapterGuid, Opcode, dwVip, dwPort, NULL, &dwRetVal ); CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY_PORT_STATE, dwVip, dwPort, NULL, &dwStatus ); break;
case WLBS_QUERY: CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwStatus ); // Fill the out parameter: Host Map
pOutParams->SetDWORD(L"HostMap", (DWORD) dwHostMap); dwRetVal = WLBS_OK; break;
case WLBS_QUERY_PORT_STATE: CfgUtilControlCluster( szAdapterGuid, WLBS_QUERY_PORT_STATE, dwVip, dwPort, NULL, &dwStatus ); dwRetVal = WLBS_OK; break;
default: TRACE_CRIT("%!FUNC! Invalid value (0x%x) passed for Operation",Opcode); Status = WBEM_E_INVALID_PARAMETER; goto end; }
//
// Fill out the out parameters: return value, cluster/port status
//
pOutParams->SetDWORD(L"ReturnValue", dwRetVal); pOutParams->SetDWORD(L"CurrentState", dwStatus);
end:
TRACE_VERB(L"<-%!FUNC! returns 0x%08lx", (UINT) Status);
return Status;
}
WBEMSTATUS ProvGetClusterMembers( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::ProvGetClusterMembers
--*/ { WBEMSTATUS Status; LPCWSTR szAdapterGuid; CHString sAdapterGuid; bool fRet; NLB_CLUSTER_MEMBER_INFO *pMembers = NULL; DWORD dwRetVal, dwStatus, dwNumHosts; LPWSTR *ppwszHostId = NULL; LPWSTR *ppwszDedicatedIpAddress= NULL; LPWSTR *ppwszHostName = NULL;
SAFEARRAY *pSAHostId = NULL; SAFEARRAY *pSADedicatedIpAddress = NULL; SAFEARRAY *pSAHostName = NULL;
TRACE_VERB(L"->");
dwRetVal = dwStatus = WLBS_FAILURE; Status = WBEM_NO_ERROR;
// Get the Adapter GUID
fRet = pInParams->GetCHString(L"AdapterGuid", sAdapterGuid); if (!fRet) { TRACE_CRIT(L"Missing adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } else { szAdapterGuid = (LPCWSTR) sAdapterGuid;
if (szAdapterGuid == NULL || *szAdapterGuid == UNICODE_NULL) { TRACE_CRIT(L"Null or empty adapter guid!"); Status = WBEM_E_INVALID_PARAMETER; goto end; } }
dwStatus = CfgUtilGetClusterMembers(szAdapterGuid, &dwNumHosts, &pMembers);
pOutParams->SetDWORD(L"ReturnValue", dwStatus);
if (dwStatus != WBEM_S_NO_ERROR) { dwNumHosts = 0; pMembers = NULL; TRACE_CRIT(L"CfgUtilGetClusterMembers failed with 0x%x", dwStatus); goto end; }
ASSERT (pMembers != NULL);
#define MY_MAX_HOSTID_DIGITS 3
ppwszHostId = CfgUtilsAllocateStringArray(dwNumHosts, MY_MAX_HOSTID_DIGITS); ppwszDedicatedIpAddress = CfgUtilsAllocateStringArray(dwNumHosts, WLBS_MAX_CL_IP_ADDR); ppwszHostName = CfgUtilsAllocateStringArray(dwNumHosts, CVY_MAX_FQDN + 1);
if (ppwszHostId == NULL || ppwszDedicatedIpAddress == NULL || ppwszHostName == NULL) { TRACE_CRIT(L"Memory allocation failed for strings of host information"); Status = WBEM_E_OUT_OF_MEMORY; goto end; }
//
// Copy the cluster member information into the string arrays for the caller
//
for (int i=0; i < dwNumHosts; i++) { ASSERT (pMembers[i].HostId <= WLBS_MAX_HOSTS);
if (pMembers[i].HostId > WLBS_MAX_HOSTS) { TRACE_CRIT(L"Illegal host id %d obatined from query to cluster", pMembers[i].HostId); Status = WBEM_E_FAILED; goto end; }
_itow(pMembers[i].HostId, ppwszHostId[i], 10);
wcsncpy(ppwszDedicatedIpAddress[i], pMembers[i].DedicatedIpAddress, WLBS_MAX_CL_IP_ADDR); (ppwszDedicatedIpAddress[i])[WLBS_MAX_CL_IP_ADDR - 1] = L'\0';
wcsncpy(ppwszHostName[i], pMembers[i].HostName, CVY_MAX_FQDN + 1); (ppwszHostName[i])[CVY_MAX_FQDN] = L'\0'; }
Status = CfgUtilSafeArrayFromStrings( (LPCWSTR *) ppwszHostId, dwNumHosts, &pSAHostId ); if (FAILED(Status)) { TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszHostId failed with 0x%x", Status); pSAHostId = NULL; goto end; }
Status = CfgUtilSafeArrayFromStrings( (LPCWSTR *) ppwszDedicatedIpAddress, dwNumHosts, &pSADedicatedIpAddress ); if (FAILED(Status)) { TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszDedicatedIpAddress failed with 0x%x", Status); pSADedicatedIpAddress = NULL; goto end; }
Status = CfgUtilSafeArrayFromStrings( (LPCWSTR *) ppwszHostName, dwNumHosts, &pSAHostName ); if (FAILED(Status)) { TRACE_CRIT(L"CfgUtilSafeArrayFromStrings for ppwszHostName failed with 0x%x", Status); pSAHostName = NULL; goto end; }
if (pSAHostId != NULL) { pOutParams->SetStringArray(L"HostIds", *pSAHostId); }
if (pSADedicatedIpAddress != NULL) { pOutParams->SetStringArray(L"DedicatedIpAddresses", *pSADedicatedIpAddress); }
if (pSAHostName != NULL) { pOutParams->SetStringArray(L"HostNames", *pSAHostName); }
//
// Everything is cool. Reset the status in case the last call gave it some funky, non-failure value.
//
Status = WBEM_NO_ERROR;
end: if (pSAHostId != NULL) { SafeArrayDestroy(pSAHostId); pSAHostId = NULL; }
if (pSADedicatedIpAddress != NULL) { SafeArrayDestroy(pSADedicatedIpAddress); pSADedicatedIpAddress = NULL; }
if (pSAHostName != NULL) { SafeArrayDestroy(pSAHostName); pSAHostName = NULL; }
if (ppwszHostId != NULL) { delete [] ppwszHostId; ppwszHostId = NULL; }
if (ppwszDedicatedIpAddress != NULL) { delete [] ppwszDedicatedIpAddress; ppwszDedicatedIpAddress = NULL; }
if (ppwszHostName != NULL) { delete [] ppwszHostName; ppwszHostName = NULL; }
if (pMembers != NULL) { delete [] pMembers; }
TRACE_VERB(L"<-returns 0x%08lx", (UINT) Status);
return Status; }
WBEMSTATUS ProvRegisterManagementApplication( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
TODO: Read from NLB registry location to see if a differnt GUID is already register -- if so fail, else set this information, else return failure and set the out params to the existing application name and company name. --*/ { return WBEM_E_PROVIDER_NOT_CAPABLE; }
WBEMSTATUS ProvUnregisterManagementApplication( CInstance *pInParams, CInstance *pOutParams ) /*++
WMI provider wrapper around NlbConfigurationUpdate::ProvControlCluster
TODO: Read from NLB registry location to see if a the specified GUID is is registered if so remove the stuff from the registry.
--*/ { return WBEM_E_PROVIDER_NOT_CAPABLE; }
|