You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2267 lines
71 KiB
2267 lines
71 KiB
/******************************************************************
|
|
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;
|
|
}
|