2022 lines
50 KiB
C++
2022 lines
50 KiB
C++
/*++
|
|
|
|
Copyright(c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
NLB Manager
|
|
|
|
File Name:
|
|
|
|
nlbhost.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of class NLBHost
|
|
|
|
NLBHost is responsible for connecting to an NLB host and getting/setting
|
|
its NLB-related configuration.
|
|
|
|
History:
|
|
|
|
03/31/01 JosephJ Created
|
|
|
|
--*/
|
|
|
|
#include "tprov.h"
|
|
#include "nlbhost.tmh"
|
|
|
|
|
|
//
|
|
// Static members of class NLBHost.
|
|
//
|
|
WSADATA NLBHost::s_WsaData;
|
|
LONG NLBHost::s_InstanceCount;
|
|
BOOL NLBHost::s_FatalError;
|
|
BOOL NLBHost::s_WsaInitialized;
|
|
BOOL NLBHost::s_ComInitialized;
|
|
IWbemStatusCodeTextPtr NLBHost::s_sp_werr; // Smart pointer
|
|
|
|
|
|
WBEMSTATUS
|
|
extract_GetClusterConfiguration_output_params(
|
|
IN IWbemClassObjectPtr spWbemOutput,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
|
|
);
|
|
|
|
WBEMSTATUS
|
|
setup_GetClusterConfiguration_input_params(
|
|
IN LPCWSTR szNic,
|
|
IN IWbemClassObjectPtr spWbemInput
|
|
);
|
|
|
|
WBEMSTATUS
|
|
setup_UpdateClusterConfiguration_input_params(
|
|
IN LPCWSTR szNic,
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg,
|
|
IN IWbemClassObjectPtr spWbemInput
|
|
);
|
|
|
|
|
|
VOID
|
|
NLBHost::mfn_LogHr(
|
|
LPCWSTR pwszMessage,
|
|
HRESULT hr
|
|
)
|
|
{
|
|
|
|
if (s_sp_werr)
|
|
{
|
|
BSTR bstr1 = 0;
|
|
BSTR bstr2 = 0;
|
|
|
|
SCODE sc;
|
|
|
|
sc = s_sp_werr->GetFacilityCodeText( hr,
|
|
0,
|
|
0,
|
|
&bstr1 );
|
|
if( sc != S_OK )
|
|
{
|
|
bstr2 = L"Unknown Error";
|
|
}
|
|
|
|
|
|
sc = s_sp_werr->GetErrorCodeText( hr,
|
|
0,
|
|
0,
|
|
&bstr2 );
|
|
if( sc != S_OK )
|
|
{
|
|
bstr2 = L"Unknown Code";
|
|
}
|
|
|
|
mfn_Log(
|
|
L"%s %s: %s(hr=0x%08lx)",
|
|
pwszMessage,
|
|
(LPCWSTR) bstr1,
|
|
(LPCWSTR) bstr2,
|
|
hr
|
|
);
|
|
|
|
SysFreeString( bstr1 );
|
|
SysFreeString( bstr2 );
|
|
}
|
|
else
|
|
{
|
|
mfn_Log(
|
|
L"%s (hr=0x%08lx)",
|
|
pwszMessage,
|
|
hr
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NLBHost::mfn_Log(
|
|
LPCWSTR pwszMessage,
|
|
...
|
|
)
|
|
{
|
|
WCHAR wszBuffer[1024];
|
|
wszBuffer[0] = 0;
|
|
|
|
va_list arglist;
|
|
va_start (arglist, pwszMessage);
|
|
int cch = vswprintf(wszBuffer, pwszMessage, arglist);
|
|
va_end (arglist);
|
|
|
|
m_pfnLogger(m_pLoggerContext, wszBuffer);
|
|
}
|
|
|
|
|
|
|
|
NLBHost::NLBHost(
|
|
const WCHAR * pBindString,
|
|
const WCHAR * pFriendlyName,
|
|
PFN_LOGGER pfnLogger,
|
|
PVOID pLoggerContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for NLBHost.
|
|
|
|
The constructor does not initiate any connections to the host. Connections
|
|
to the host are initiated on demand (based on method calls).
|
|
|
|
Arguments:
|
|
|
|
pBindString - String used to connect to the remote host.
|
|
pFriendlyName - Descriptive name of the host. Used for logging.
|
|
pfnLogger - Function called to log textual information.
|
|
pLoggerContext - Caller's context, passed in calls to pfnLogger
|
|
|
|
--*/
|
|
{
|
|
m_BindString = pBindString; // implicit copy
|
|
m_FriendlyName = pFriendlyName; // implicit copy
|
|
m_pfnLogger = pfnLogger;
|
|
m_pLoggerContext = pLoggerContext;
|
|
|
|
if (InterlockedIncrement(&s_InstanceCount) == 1)
|
|
{
|
|
mfn_InitializeStaticFields();
|
|
|
|
}
|
|
|
|
InitializeCriticalSection(&m_Lock);
|
|
|
|
mfn_Log(
|
|
L"NLBHost(BindString=%s, FriendlyName=%s) constructor succeeded.",
|
|
(LPCWSTR) pBindString,
|
|
(LPCWSTR) pFriendlyName
|
|
);
|
|
}
|
|
|
|
NLBHost::~NLBHost()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for NLBHost.
|
|
|
|
--*/
|
|
{
|
|
mfn_Log(L"NLBHost distructor(%s).", (LPCWSTR) m_FriendlyName);
|
|
|
|
ASSERT(m_fProcessing == FALSE); // Shouldn't be doing any processing when
|
|
// calling the distructor.
|
|
|
|
if (InterlockedDecrement(&s_InstanceCount)==0)
|
|
{
|
|
mfn_DeinitializeStaticFields();
|
|
}
|
|
|
|
DeleteCriticalSection(&m_Lock);
|
|
|
|
}
|
|
|
|
|
|
UINT
|
|
NLBHost::Ping(
|
|
VOID
|
|
)
|
|
{
|
|
if (s_FatalError) return ERROR_INTERNAL_ERROR;
|
|
|
|
return mfn_ping();
|
|
}
|
|
|
|
WBEMSTATUS
|
|
NLBHost::GetHostInformation(
|
|
OUT HostInformation **ppHostInfo
|
|
)
|
|
{
|
|
WBEMSTATUS Status;
|
|
HostInformation *pHostInfo = NULL;
|
|
BOOL fConnected = FALSE;
|
|
NicInformation *pNicInfo=NULL;
|
|
|
|
if (s_FatalError)
|
|
{
|
|
Status = WBEM_E_CRITICAL_ERROR;
|
|
goto end;
|
|
}
|
|
|
|
pHostInfo = new HostInformation;
|
|
if (pHostInfo == NULL)
|
|
{
|
|
Status = WBEM_E_OUT_OF_MEMORY;
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Connect to the host.
|
|
//
|
|
Status = mfn_connect();
|
|
|
|
if (FAILED(Status)) goto end;
|
|
|
|
fConnected = TRUE;
|
|
|
|
#if 0
|
|
//
|
|
// Now find the instance and execute the method to get the host info.
|
|
//
|
|
mfn_find_host_instance();
|
|
... stuff parameters ...
|
|
mfn_execute_method();
|
|
#endif //
|
|
|
|
pHostInfo->MachineName = L"ACME-Machine-Name";
|
|
|
|
pNicInfo = pHostInfo->nicInformation;
|
|
|
|
pNicInfo->fullNicName = L"ACME Full Nic Name";
|
|
pNicInfo->adapterGuid = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}";
|
|
pNicInfo->friendlyName = L"ACME Friendly Name";
|
|
|
|
pHostInfo->NumNics = 1;
|
|
|
|
|
|
end:
|
|
|
|
if (fConnected)
|
|
{
|
|
mfn_disconnect();
|
|
}
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
if (pHostInfo != NULL)
|
|
{
|
|
delete pHostInfo;
|
|
}
|
|
pHostInfo = NULL;
|
|
}
|
|
|
|
*ppHostInfo = pHostInfo;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// Configuration operations:
|
|
//
|
|
|
|
WBEMSTATUS
|
|
NLBHost::GetClusterConfiguration(
|
|
IN const WCHAR* pNicGuid,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
IWbemClassObjectPtr spWbemInputInstance = NULL; // smart pointer
|
|
BOOL fConnected = FALSE;
|
|
LPWSTR pRelPath = NULL;
|
|
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
|
|
|
|
ZeroMemory(pCfg, sizeof(*pCfg));
|
|
|
|
if (s_FatalError)
|
|
{
|
|
Status = WBEM_E_CRITICAL_ERROR;
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Connect to the host.
|
|
//
|
|
Status = mfn_connect();
|
|
|
|
if (FAILED(Status)) goto end;
|
|
|
|
fConnected = TRUE;
|
|
|
|
|
|
mfn_Log(
|
|
L"NLBHost -- getting cluster configuration on NIC (%s).",
|
|
pNicGuid
|
|
);
|
|
|
|
//
|
|
// Get input instance and relpath...
|
|
//
|
|
Status = CfgUtilGetWmiInputInstanceAndRelPath(
|
|
m_sp_pws,
|
|
L"NlbsNic", // szClassName
|
|
L"AdapterGuid", // szParameterName
|
|
pNicGuid, // szPropertyValue
|
|
L"GetClusterConfiguration", // szMethodName,
|
|
spWbemInputInstance, // smart pointer
|
|
&pRelPath // free using delete
|
|
);
|
|
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
mfn_Log(
|
|
L"NLBHost -- error 0x%08lx trying to find NIC instance\n",
|
|
(UINT) Status
|
|
);
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// NOTE: spWbemInputInstance could be NULL -- in fact it is
|
|
// NULL because GetClusterConfiguration doesn't require input args
|
|
//
|
|
|
|
//
|
|
// Run the Method!
|
|
//
|
|
{
|
|
HRESULT hr;
|
|
|
|
printf("Going to call GetClusterConfiguration\n");
|
|
|
|
hr = m_sp_pws->ExecMethod(
|
|
_bstr_t(pRelPath),
|
|
L"GetClusterConfiguration",
|
|
0,
|
|
NULL,
|
|
spWbemInputInstance,
|
|
&spWbemOutput,
|
|
NULL
|
|
);
|
|
printf("GetClusterConfiguration returns\n");
|
|
|
|
if( FAILED( hr) )
|
|
{
|
|
printf("IWbemServices::ExecMethod failure 0x%08lx\n", (UINT) hr);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
printf("GetClusterConfiguration method returns SUCCESS!\n");
|
|
}
|
|
|
|
if (spWbemOutput == NULL)
|
|
{
|
|
//
|
|
// Hmm --- no output ?!
|
|
//
|
|
printf("ExecMethod GetClusterConfiguration had no output\n");
|
|
Status = WBEM_E_NOT_FOUND;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Extract all the out parameters!
|
|
//
|
|
{
|
|
DWORD dwRet=0;
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"ReturnValue",
|
|
&dwRet
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
printf("IWbemClassObject::Get failure\n");
|
|
//
|
|
// Let's ignore for now...
|
|
//
|
|
dwRet = 0;
|
|
}
|
|
Status = extract_GetClusterConfiguration_output_params(
|
|
spWbemOutput,
|
|
pCfg
|
|
);
|
|
|
|
}
|
|
|
|
|
|
end:
|
|
|
|
if (fConnected)
|
|
{
|
|
mfn_disconnect();
|
|
}
|
|
|
|
if (pRelPath != NULL)
|
|
{
|
|
delete pRelPath;
|
|
}
|
|
|
|
spWbemInputInstance = NULL; // smart pointer.
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WBEMSTATUS
|
|
NLBHost::SetClusterConfiguration(
|
|
IN const WCHAR * pNicGuid,
|
|
IN const PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg,
|
|
IN UINT GenerationId,
|
|
OUT UINT * pRequestId
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
|
|
if (s_FatalError)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
mfn_Log(
|
|
L"NLBHost -- setting cluster configuration on NIC (%s).",
|
|
pNicGuid
|
|
);
|
|
*pRequestId = 123;
|
|
|
|
Status = WBEM_S_PENDING;
|
|
|
|
end:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
WBEMSTATUS
|
|
NLBHost::GetAsyncResult(
|
|
IN UINT RequestId,
|
|
OUT UINT * pGenerationId,
|
|
OUT UINT * pResultCode,
|
|
OUT _bstr_t * pResultText
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
if (s_FatalError)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
mfn_Log(
|
|
L"NLBHost -- checking result of Async operation %d\n",
|
|
RequestId
|
|
);
|
|
*pGenerationId = 1;
|
|
*pResultCode = 1;
|
|
*pResultText = L"Result";
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
end:
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
WBEMSTATUS
|
|
NLBHost::mfn_connect(
|
|
VOID
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
HRESULT hr;
|
|
_bstr_t serverPath;
|
|
|
|
hr = CoCreateInstance(CLSID_WbemLocator, 0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID *) &m_sp_pwl);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
mfn_LogHr(L"CoCreateInstance IWebmLocator failed", hr);
|
|
m_sp_pwl = NULL;
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
|
|
serverPath = _bstr_t(L"\\\\") + m_BindString + L"\\root\\microsoftnlb";
|
|
|
|
|
|
hr = m_sp_pwl->ConnectServer(
|
|
serverPath,
|
|
NULL, // strUser,
|
|
NULL, // strPassword,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&m_sp_pws
|
|
);
|
|
// these have been found to be special cases where retrying may help.
|
|
if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) )
|
|
{
|
|
int delay = 250; // milliseconds
|
|
int timesToRetry = 20;
|
|
|
|
for( int i = 0; i < timesToRetry; ++i )
|
|
{
|
|
Sleep(delay);
|
|
mfn_Log(L"connectserver recoverable failure, retrying.");
|
|
hr = m_sp_pwl->ConnectServer(
|
|
serverPath,
|
|
NULL, // strUser,
|
|
NULL, // strPassword,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&m_sp_pws );
|
|
if( !FAILED( hr) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if ( hr == 0x80041064 )
|
|
{
|
|
// trying to connect to local machine. Cannot use credentials.
|
|
mfn_Log(L"Connecting to self. Retrying without using credentials");
|
|
hr = m_sp_pwl->ConnectServer(
|
|
serverPath,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
&m_sp_pws
|
|
);
|
|
}
|
|
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
mfn_LogHr(L"Error connecting to server", hr);
|
|
m_sp_pws = NULL;
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
mfn_Log(L"Successfully connected to server %s", serverPath);
|
|
}
|
|
|
|
|
|
// Set the proxy so that impersonation of the client occurs.
|
|
//
|
|
hr = CoSetProxyBlanket(
|
|
m_sp_pws,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
|
|
COLE_DEFAULT_PRINCIPAL, // NULL,
|
|
RPC_C_AUTHN_LEVEL_DEFAULT,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
COLE_DEFAULT_AUTHINFO, // NULL,
|
|
EOAC_DEFAULT // EOAC_NONE
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
mfn_LogHr(L"Error setting proxy blanket", hr);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
mfn_Log(L"Successfully set up proxy settings.");
|
|
}
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
|
|
end:
|
|
if (FAILED(Status))
|
|
{
|
|
if (m_sp_pws != NULL)
|
|
{
|
|
// Smart pointer.
|
|
m_sp_pws = NULL;
|
|
}
|
|
|
|
if (m_sp_pwl != NULL)
|
|
{
|
|
// Smart pointer.
|
|
m_sp_pwl = NULL;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
NLBHost::mfn_disconnect(
|
|
VOID
|
|
)
|
|
{
|
|
mfn_Log(L"Disconnecting from host %s", m_BindString);
|
|
if (m_sp_pws != NULL)
|
|
{
|
|
// Smart pointer
|
|
m_sp_pws = NULL;
|
|
}
|
|
|
|
if (m_sp_pwl != NULL)
|
|
{
|
|
// Smart pointer
|
|
m_sp_pwl = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NLBHost::mfn_InitializeStaticFields(
|
|
VOID
|
|
)
|
|
{
|
|
s_FatalError = TRUE;
|
|
|
|
// Initialize com.
|
|
//
|
|
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
|
|
if ( FAILED(hr) )
|
|
{
|
|
mfn_Log(L"Failed to initialize COM library (hr=0x%08lx)", hr);
|
|
goto end;
|
|
}
|
|
s_ComInitialized = TRUE;
|
|
|
|
|
|
//
|
|
// Initialize Winsock
|
|
//
|
|
int err = WSAStartup(MAKEWORD(2,2), &s_WsaData);
|
|
mfn_Log(L"Initializing Winsock");
|
|
err = WSAStartup(MAKEWORD(2,2), &s_WsaData);
|
|
if (err) {
|
|
mfn_Log(L"PING_WSASTARTUP_FAILED %d", GetLastError());
|
|
goto end;
|
|
}
|
|
s_WsaInitialized = TRUE;
|
|
s_FatalError = FALSE;
|
|
|
|
|
|
//
|
|
// Get some WMI interface pointers...
|
|
//
|
|
SCODE sc = CoCreateInstance(
|
|
CLSID_WbemStatusCodeText,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemStatusCodeText,
|
|
(LPVOID *) &s_sp_werr
|
|
);
|
|
if( sc != S_OK )
|
|
{
|
|
s_sp_werr = NULL;
|
|
mfn_Log(L"CoCreateInstance IWbemStatusCodeText failure\n");
|
|
}
|
|
|
|
end:
|
|
|
|
if (s_FatalError)
|
|
{
|
|
mfn_DeinitializeStaticFields();
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
NLBHost::mfn_DeinitializeStaticFields(
|
|
VOID
|
|
)
|
|
{
|
|
if (s_sp_werr != NULL)
|
|
{
|
|
s_sp_werr = NULL; // Smart pointer
|
|
}
|
|
|
|
if (s_WsaInitialized)
|
|
{
|
|
mfn_Log(L"Deinitializing Winsock");
|
|
WSACleanup();
|
|
s_WsaInitialized = FALSE;
|
|
}
|
|
|
|
if (s_ComInitialized)
|
|
{
|
|
mfn_Log(L"Deinitializing COM");
|
|
CoUninitialize();
|
|
s_ComInitialized = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
WBEMSTATUS
|
|
extract_extended_config_from_wmi(
|
|
IN IWbemClassObjectPtr &spWbemOutput,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
|
|
)
|
|
{
|
|
|
|
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
|
|
UINT NumIpAddresses = 0;
|
|
BOOL fNlbBound = FALSE;
|
|
WLBS_REG_PARAMS NlbParams; // The WLBS-specific configuration
|
|
BOOL fNlbParamsValid = FALSE;
|
|
UINT Generation = 1;
|
|
|
|
//
|
|
// Verify that pCfg is indeed zero-initialized.
|
|
// We are doing this because we want to make sure that the caller
|
|
// doesn't pass in a perviously initialized pCfg which may have a non-null
|
|
// ip address array.
|
|
//
|
|
{
|
|
BYTE *pb = (BYTE*) pCfg;
|
|
BYTE *pbEnd = (BYTE*) (pCfg+1);
|
|
|
|
for (; pb < pbEnd; pb++)
|
|
{
|
|
if (*pb!=0)
|
|
{
|
|
printf(L"uninitialized pCfg\n");
|
|
ASSERT(!"uninitialized pCfg");
|
|
Status = WBEM_E_INVALID_PARAMETER;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Get the ip address list.
|
|
//
|
|
Status = CfgUtilGetStaticIpAddresses(
|
|
m_szNicGuid,
|
|
&NumIpAddresses,
|
|
&pIpInfo
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
printf("Error 0x%08lx getting ip address list for %ws\n",
|
|
(UINT) Status, m_szNicGuid);
|
|
mfn_Log(L"Error IP Address list on this NIC\n");
|
|
pIpInfo = NULL;
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// TEST TEST TEST
|
|
//
|
|
if (0)
|
|
{
|
|
if (NumIpAddresses>1)
|
|
{
|
|
//
|
|
// Let's munge the 2nd IP address
|
|
//
|
|
if (!_wcsicmp(pIpInfo[1].IpAddress, L"10.0.0.33"))
|
|
{
|
|
wcscpy(pIpInfo[1].IpAddress, L"10.0.0.44");
|
|
}
|
|
else
|
|
{
|
|
wcscpy(pIpInfo[1].IpAddress, L"10.0.0.33");
|
|
}
|
|
}
|
|
MyBreak(L"Break just before calling CfgUtilSetStaticIpAddresses\n");
|
|
Status = CfgUtilSetStaticIpAddresses(
|
|
m_szNicGuid,
|
|
NumIpAddresses,
|
|
pIpInfo
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// Check if NLB is bound
|
|
//
|
|
Status = CfgUtilCheckIfNlbBound(
|
|
m_szNicGuid,
|
|
&fNlbBound
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
printf("Error 0x%08lx determining if NLB is bound to %ws\n",
|
|
(UINT) Status, m_szNicGuid);
|
|
mfn_Log(L"Error determining if NLB is bound to this NIC\n");
|
|
goto end;
|
|
}
|
|
|
|
if (fNlbBound)
|
|
{
|
|
//
|
|
// Get the latest NLB configuration information for this NIC.
|
|
//
|
|
Status = CfgUtilGetNlbConfig(
|
|
m_szNicGuid,
|
|
&NlbParams
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
//
|
|
// We don't consider a catastrophic failure.
|
|
//
|
|
printf("Error 0x%08lx reading NLB configuration for %ws\n",
|
|
(UINT) Status, m_szNicGuid);
|
|
mfn_Log(L"Error reading NLB configuration for this NIC\n");
|
|
Status = WBEM_NO_ERROR;
|
|
fNlbParamsValid = FALSE;
|
|
ZeroMemory(&NlbParams, sizeof(NlbParams));
|
|
}
|
|
else
|
|
{
|
|
fNlbParamsValid = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the current generation
|
|
//
|
|
{
|
|
BOOL fExists=FALSE;
|
|
HKEY hKey = sfn_RegOpenKey(
|
|
m_szNicGuid,
|
|
NULL // NULL == root for this guid.,
|
|
);
|
|
|
|
Generation = 1; // We assume generation is 1 on error reading gen.
|
|
|
|
if (hKey!=NULL)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwType;
|
|
DWORD dwData;
|
|
|
|
dwData = sizeof(Generation);
|
|
lRet = RegQueryValueEx(
|
|
hKey, // handle to key to query
|
|
L"Generation", // address of name of value to query
|
|
NULL, // reserved
|
|
&dwType, // address of buffer for value type
|
|
(LPBYTE) &Generation, // address of data buffer
|
|
&dwData // address of data buffer size
|
|
);
|
|
if ( lRet != ERROR_SUCCESS
|
|
|| dwType != REG_DWORD
|
|
|| dwData != sizeof(Generation))
|
|
{
|
|
//
|
|
// Couldn't read the generation. Let's assume it's
|
|
// a starting value of 1.
|
|
//
|
|
printf("Error reading generation for %ws; assuming its 0\n",
|
|
m_szNicGuid);
|
|
Generation = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Success ... fill out pCfg
|
|
//
|
|
pCfg->fValidNlbCfg = fNlbParamsValid;
|
|
pCfg->Generation = Generation;
|
|
pCfg->fBound = fNlbBound;
|
|
pCfg->NumIpAddresses = NumIpAddresses;
|
|
pCfg->pIpAddressInfo = pIpInfo;
|
|
if (fNlbBound)
|
|
{
|
|
pCfg->NlbParams = NlbParams; // struct copy
|
|
}
|
|
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
end:
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
if (pIpInfo!=NULL)
|
|
{
|
|
delete pIpInfo;
|
|
}
|
|
pCfg->fValidNlbCfg = FALSE;
|
|
}
|
|
|
|
return Status;
|
|
return WBEM_NO_ERROR;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
WBEMSTATUS
|
|
NlbHostGetConfiguration(
|
|
IN LPCWSTR szMachine, // empty string for local
|
|
IN LPCWSTR szNicGuid,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCurrentCfg
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
IWbemServicesPtr spWbemService = NULL; // Smart pointer
|
|
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
|
|
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
|
|
LPWSTR pRelPath = NULL;
|
|
|
|
//
|
|
// Get interface to the NLB namespace on the specified machine
|
|
//
|
|
{
|
|
#define _MaxLen 256
|
|
WCHAR NetworkResource[_MaxLen];
|
|
|
|
if (*szMachine == 0)
|
|
{
|
|
szMachine = L".";
|
|
}
|
|
_snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb",
|
|
szMachine);
|
|
NetworkResource[_MaxLen-1]=0;
|
|
|
|
wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
|
|
|
|
Status = CfgUtilConnectToServer(
|
|
NetworkResource,
|
|
NULL, // szUser
|
|
NULL, // szPassword
|
|
NULL, // szAuthority (domain)
|
|
&spWbemService
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine);
|
|
goto end;
|
|
}
|
|
wprintf(L"Successfully connected to NLB on %ws...\n", szMachine);
|
|
}
|
|
|
|
//
|
|
// Get wmi input instance to "GetClusterConfiguration" method
|
|
//
|
|
{
|
|
Status = CfgUtilGetWmiInputInstanceAndRelPath(
|
|
spWbemService,
|
|
L"NlbsNic", // szClassName
|
|
L"AdapterGuid", // szParameterName
|
|
szNicGuid, // szPropertyValue
|
|
L"GetClusterConfiguration", // szMethodName,
|
|
spWbemInput, // smart pointer
|
|
&pRelPath // free using delete
|
|
);
|
|
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(
|
|
L"ERROR 0x%08lx trying to get instance of GetClusterConfiguration\n",
|
|
(UINT) Status
|
|
);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setup params for the "GetClusterConfiguration" method
|
|
// NOTE: spWbemInput could be NULL.
|
|
//
|
|
Status = setup_GetClusterConfiguration_input_params(
|
|
szNicGuid,
|
|
spWbemInput
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Call the "GetClusterConfiguration" method
|
|
//
|
|
{
|
|
HRESULT hr;
|
|
|
|
wprintf(L"Going get GetClusterConfiguration...\n");
|
|
|
|
hr = spWbemService->ExecMethod(
|
|
_bstr_t(pRelPath),
|
|
L"GetClusterConfiguration",
|
|
0,
|
|
NULL,
|
|
spWbemInput,
|
|
&spWbemOutput,
|
|
NULL
|
|
);
|
|
|
|
if( FAILED( hr) )
|
|
{
|
|
wprintf(L"GetClusterConfiguration returns with failure 0x%8lx\n",
|
|
(UINT) hr);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"GetClusterConfiguration returns successfully\n");
|
|
}
|
|
|
|
if (spWbemOutput == NULL)
|
|
{
|
|
//
|
|
// Hmm --- no output ?!
|
|
//
|
|
printf("ExecMethod GetClusterConfiguration had no output");
|
|
Status = WBEM_E_NOT_FOUND;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Extract params from the "GetClusterConfiguration" method
|
|
//
|
|
Status = extract_GetClusterConfiguration_output_params(
|
|
spWbemOutput,
|
|
pCurrentCfg
|
|
);
|
|
|
|
end:
|
|
|
|
if (pRelPath != NULL)
|
|
{
|
|
delete pRelPath;
|
|
}
|
|
|
|
spWbemService = NULL; // Smart pointer
|
|
spWbemInput = NULL; // smart pointer
|
|
spWbemOutput = NULL; // smart pointer.
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
WBEMSTATUS
|
|
NlbHostDoUpdate(
|
|
IN LPCWSTR szMachine, // NULL or empty for local
|
|
IN LPCWSTR szNicGuid,
|
|
IN LPCWSTR szClientDescription,
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState,
|
|
OUT UINT *pGeneration,
|
|
OUT WCHAR **ppLog // free using delete operator.
|
|
)
|
|
{
|
|
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
IWbemServicesPtr spWbemService = NULL; // Smart pointer
|
|
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
|
|
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
|
|
LPWSTR pRelPath = NULL;
|
|
|
|
*pGeneration = 0;
|
|
*ppLog = NULL;
|
|
|
|
//
|
|
// Get interface to the NLB namespace on the specified machine
|
|
//
|
|
{
|
|
#define _MaxLen 256
|
|
WCHAR NetworkResource[_MaxLen];
|
|
|
|
if (*szMachine == 0)
|
|
{
|
|
szMachine = L".";
|
|
}
|
|
_snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb",
|
|
szMachine);
|
|
NetworkResource[_MaxLen-1]=0;
|
|
|
|
wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
|
|
|
|
Status = CfgUtilConnectToServer(
|
|
NetworkResource,
|
|
NULL, // szUser
|
|
NULL, // szPassword
|
|
NULL, // szAuthority (domain)
|
|
&spWbemService
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine);
|
|
goto end;
|
|
}
|
|
wprintf(L"Successfully connected to NLB on %ws...\n", szMachine);
|
|
}
|
|
|
|
//
|
|
// Get wmi input instance to "UpdateClusterConfiguration" method
|
|
//
|
|
{
|
|
Status = CfgUtilGetWmiInputInstanceAndRelPath(
|
|
spWbemService,
|
|
L"NlbsNic", // szClassName
|
|
L"AdapterGuid", // szParameterName
|
|
szNicGuid, // szPropertyValue
|
|
L"UpdateClusterConfiguration", // szMethodName,
|
|
spWbemInput, // smart pointer
|
|
&pRelPath // free using delete
|
|
);
|
|
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(
|
|
L"ERROR 0x%08lx trying to get instance of UpdateConfiguration\n",
|
|
(UINT) Status
|
|
);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setup params for the "UpdateClusterConfiguration" method
|
|
// NOTE: spWbemInput could be NULL.
|
|
//
|
|
Status = setup_UpdateClusterConfiguration_input_params(
|
|
szNicGuid,
|
|
pNewState,
|
|
spWbemInput
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Call the "UpdateClusterConfiguration" method
|
|
//
|
|
{
|
|
HRESULT hr;
|
|
|
|
wprintf(L"Going get UpdateClusterConfiguration...\n");
|
|
|
|
hr = spWbemService->ExecMethod(
|
|
_bstr_t(pRelPath),
|
|
L"UpdateClusterConfiguration",
|
|
0,
|
|
NULL,
|
|
spWbemInput,
|
|
&spWbemOutput,
|
|
NULL
|
|
);
|
|
|
|
if( FAILED( hr) )
|
|
{
|
|
wprintf(L"UpdateConfiguration returns with failure 0x%8lx\n",
|
|
(UINT) hr);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"UpdateConfiguration returns successfully\n");
|
|
}
|
|
|
|
if (spWbemOutput == NULL)
|
|
{
|
|
//
|
|
// Hmm --- no output ?!
|
|
//
|
|
printf("ExecMethod UpdateConfiguration had no output");
|
|
Status = WBEM_E_NOT_FOUND;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Extract params from the "UpdateClusterConfiguration" method
|
|
//
|
|
{
|
|
DWORD dwReturnValue = 0;
|
|
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"ReturnValue", // <--------------------------------
|
|
&dwReturnValue
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read ReturnValue failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
|
|
|
|
LPWSTR szLog = NULL;
|
|
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"Log", // <-------------------------
|
|
&szLog
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
szLog = NULL;
|
|
}
|
|
*ppLog = szLog;
|
|
|
|
DWORD dwGeneration = 0;
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"NewGeneration", // <--------------------------------
|
|
&dwGeneration
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
//
|
|
// Generation should always be specified for pending operations.
|
|
// TODO: for successful operations also?
|
|
//
|
|
if ((WBEMSTATUS)dwReturnValue == WBEM_S_PENDING)
|
|
{
|
|
wprintf(L"Attempt to read NewGeneration for pending update failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
Status = WBEM_E_CRITICAL_ERROR;
|
|
goto end;
|
|
}
|
|
dwGeneration = 0; // we don't care if it's not set for non-pending
|
|
}
|
|
*pGeneration = (UINT) dwGeneration;
|
|
|
|
|
|
//
|
|
// Make the return status reflect the true status of the update
|
|
// operation.
|
|
//
|
|
Status = (WBEMSTATUS) dwReturnValue;
|
|
}
|
|
|
|
end:
|
|
|
|
if (pRelPath != NULL)
|
|
{
|
|
delete pRelPath;
|
|
}
|
|
|
|
spWbemService = NULL; // Smart pointer
|
|
spWbemInput = NULL; // smart pointer
|
|
spWbemOutput = NULL; // smart pointer.
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
WBEMSTATUS
|
|
NlbHostGetUpdateStatus(
|
|
IN LPCWSTR szMachine, // NULL or empty for local
|
|
IN LPCWSTR szNicGuid,
|
|
IN UINT Generation,
|
|
OUT WBEMSTATUS *pCompletionStatus,
|
|
OUT WCHAR **ppLog // free using delete operator.
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
IWbemServicesPtr spWbemService = NULL; // Smart pointer
|
|
IWbemClassObjectPtr spWbemInput = NULL; // smart pointer
|
|
IWbemClassObjectPtr spWbemOutput = NULL; // smart pointer.
|
|
LPWSTR pRelPath = NULL;
|
|
|
|
*ppLog = NULL;
|
|
*pCompletionStatus = WBEM_E_CRITICAL_ERROR;
|
|
|
|
//
|
|
// Get interface to the NLB namespace on the specified machine
|
|
//
|
|
{
|
|
#define _MaxLen 256
|
|
WCHAR NetworkResource[_MaxLen];
|
|
|
|
if (*szMachine == 0)
|
|
{
|
|
szMachine = L".";
|
|
}
|
|
_snwprintf(NetworkResource, (_MaxLen-1), L"\\\\%ws\\root\\microsoftnlb",
|
|
szMachine);
|
|
NetworkResource[_MaxLen-1]=0;
|
|
|
|
// wprintf(L"Connecting to NLB on %ws ...\n", szMachine);
|
|
|
|
Status = CfgUtilConnectToServer(
|
|
NetworkResource,
|
|
NULL, // szUser
|
|
NULL, // szPassword
|
|
NULL, // szAuthority (domain)
|
|
&spWbemService
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"ERROR: COULD NOT CONNECT TO NLB ON %ws\n", szMachine);
|
|
goto end;
|
|
}
|
|
// wprintf(L"Successfully connected to NLB on %ws...\n", szMachine);
|
|
}
|
|
|
|
//
|
|
// Get wmi input instance to "QueryConfigurationUpdateStatus" method
|
|
//
|
|
{
|
|
Status = CfgUtilGetWmiInputInstanceAndRelPath(
|
|
spWbemService,
|
|
L"NlbsNic", // szClassName
|
|
L"AdapterGuid", // szParameterName
|
|
szNicGuid, // szPropertyValue
|
|
L"QueryConfigurationUpdateStatus", // szMethodName,
|
|
spWbemInput, // smart pointer
|
|
&pRelPath // free using delete
|
|
);
|
|
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(
|
|
L"ERROR 0x%08lx trying to find instance to QueryUpdateStatus\n",
|
|
(UINT) Status
|
|
);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setup params for the "QueryConfigurationUpdateStatus" method
|
|
// NOTE: spWbemInput could be NULL.
|
|
//
|
|
{
|
|
Status = CfgUtilSetWmiStringParam(
|
|
spWbemInput,
|
|
L"AdapterGuid",
|
|
szNicGuid
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(
|
|
L"Couldn't set Adapter GUID parameter to QueryUpdateStatus\n");
|
|
goto end;
|
|
}
|
|
|
|
Status = CfgUtilSetWmiDWORDParam(
|
|
spWbemInput,
|
|
L"Generation",
|
|
Generation
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(
|
|
L"Couldn't set Generation parameter to QueryUpdateStatus\n");
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the "QueryConfigurationUpdateStatus" method
|
|
//
|
|
{
|
|
HRESULT hr;
|
|
|
|
// wprintf(L"Going call QueryConfigurationUpdateStatus...\n");
|
|
|
|
hr = spWbemService->ExecMethod(
|
|
_bstr_t(pRelPath),
|
|
L"QueryConfigurationUpdateStatus", // szMethodName,
|
|
0,
|
|
NULL,
|
|
spWbemInput,
|
|
&spWbemOutput,
|
|
NULL
|
|
);
|
|
|
|
if( FAILED( hr) )
|
|
{
|
|
wprintf(L"QueryConfigurationUpdateStatus returns with failure 0x%8lx\n",
|
|
(UINT) hr);
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
// wprintf(L"QueryConfigurationUpdateStatus returns successfully\n");
|
|
}
|
|
|
|
if (spWbemOutput == NULL)
|
|
{
|
|
//
|
|
// Hmm --- no output ?!
|
|
//
|
|
printf("ExecMethod QueryConfigurationUpdateStatus had no output");
|
|
Status = WBEM_E_NOT_FOUND;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Extract output params --- return code and log.
|
|
//
|
|
{
|
|
DWORD dwReturnValue = 0;
|
|
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"ReturnValue", // <--------------------------------
|
|
&dwReturnValue
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read ReturnValue failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
|
|
*pCompletionStatus = (WBEMSTATUS) dwReturnValue;
|
|
|
|
|
|
LPWSTR szLog = NULL;
|
|
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"Log", // <-------------------------
|
|
&szLog
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
szLog = NULL;
|
|
}
|
|
|
|
*ppLog = szLog;
|
|
|
|
ASSERT(Status != WBEM_S_PENDING);
|
|
}
|
|
|
|
end:
|
|
|
|
if (pRelPath != NULL)
|
|
{
|
|
delete pRelPath;
|
|
}
|
|
|
|
spWbemService = NULL; // Smart pointer
|
|
spWbemInput = NULL; // smart pointer
|
|
spWbemOutput = NULL; // smart pointer.
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
WBEMSTATUS
|
|
setup_GetClusterConfiguration_input_params(
|
|
IN LPCWSTR szNic,
|
|
IN IWbemClassObjectPtr spWbemInput
|
|
)
|
|
/*
|
|
Setup the input wmi parameters for the GetClusterConfiguration method
|
|
*/
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
|
|
Status = CfgUtilSetWmiStringParam(
|
|
spWbemInput,
|
|
L"AdapterGuid",
|
|
szNic
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
|
|
WBEMSTATUS
|
|
extract_GetClusterConfiguration_output_params(
|
|
IN IWbemClassObjectPtr spWbemOutput,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
|
|
DWORD Generation = 0;
|
|
BOOL NlbBound = FALSE;
|
|
LPWSTR *pszNetworkAddresses= NULL;
|
|
UINT NumNetworkAddresses = 0;
|
|
BOOL ValidNlbCfg = FALSE;
|
|
LPWSTR szClusterName = NULL;
|
|
LPWSTR szClusterNetworkAddress = NULL;
|
|
LPWSTR szTrafficMode = NULL;
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE
|
|
TrafficMode
|
|
= NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
|
|
LPWSTR *pszPortRules = NULL;
|
|
UINT NumPortRules = 0;
|
|
DWORD HostPriority = 0;
|
|
LPWSTR szDedicatedNetworkAddress = NULL;
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
|
|
ClusterModeOnStart
|
|
= NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
|
|
BOOL RemoteControlEnabled= FALSE;
|
|
|
|
#if 0
|
|
[OUT] uint32 Generation,
|
|
[OUT] String NetworkAddresses[], // "10.1.1.1/255.0.0.0"
|
|
[OUT] Boolean NLBBound,
|
|
[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] Boolean ClusterModeOnStart,
|
|
[OUT] Boolean RemoteControlEnabled
|
|
#endif // 0
|
|
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"Generation", // <--------------------------------
|
|
&Generation
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read Generation failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
|
|
Status = CfgUtilGetWmiStringArrayParam(
|
|
spWbemOutput,
|
|
L"NetworkAddresses", // <--------------------------------
|
|
&pszNetworkAddresses,
|
|
&NumNetworkAddresses
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read Network addresses failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
|
|
Status = CfgUtilGetWmiBoolParam(
|
|
spWbemOutput,
|
|
L"NLBBound", // <--------------------------------
|
|
&NlbBound
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read NLBBound failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
|
|
|
|
do // while false -- just to allow us to break out
|
|
{
|
|
ValidNlbCfg = FALSE;
|
|
|
|
if (!NlbBound)
|
|
{
|
|
wprintf(L"NLB is UNBOUND\n");
|
|
break;
|
|
}
|
|
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"ClusterNetworkAddress", // <-------------------------
|
|
&szClusterNetworkAddress
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read Cluster IP failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
wprintf(L"NLB is BOUND, and the cluster address is %ws\n",
|
|
szClusterNetworkAddress);
|
|
|
|
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"ClusterName", // <-------------------------
|
|
&szClusterName
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read Cluster Name failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Traffic mode
|
|
//
|
|
{
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"TrafficMode", // <-------------------------
|
|
&szTrafficMode
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read Traffic Mode failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// TODO: [OUT] String PortRules[],
|
|
|
|
Status = CfgUtilGetWmiDWORDParam(
|
|
spWbemOutput,
|
|
L"HostPriority", // <--------------------------------
|
|
&HostPriority
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read HostPriority failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
Status = CfgUtilGetWmiStringParam(
|
|
spWbemOutput,
|
|
L"DedicatedNetworkAddress", // <-------------------------
|
|
&szDedicatedNetworkAddress
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read dedicated IP failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// StartMode
|
|
//
|
|
{
|
|
BOOL StartMode = FALSE;
|
|
Status = CfgUtilGetWmiBoolParam(
|
|
spWbemOutput,
|
|
L"ClusterModeOnStart", // <-------------------------
|
|
&StartMode
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read ClusterModeOnStart failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
if (StartMode)
|
|
{
|
|
ClusterModeOnStart =
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED;
|
|
}
|
|
else
|
|
{
|
|
ClusterModeOnStart =
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
|
|
}
|
|
}
|
|
|
|
Status = CfgUtilGetWmiBoolParam(
|
|
spWbemOutput,
|
|
L"RemoteControlEnabled", // <----------------------------
|
|
&RemoteControlEnabled
|
|
);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to read RemoteControlEnabled failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
break;
|
|
}
|
|
|
|
ValidNlbCfg = TRUE;
|
|
|
|
} while (FALSE) ;
|
|
|
|
//
|
|
// Now let's set all the the parameters in Cfg
|
|
//
|
|
{
|
|
pCfg->Generation = Generation;
|
|
pCfg->fBound = NlbBound;
|
|
Status = pCfg->SetNetworkAddresses(
|
|
(LPCWSTR*) pszNetworkAddresses,
|
|
NumNetworkAddresses
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to set NetworkAddresses failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
pCfg->fValidNlbCfg = ValidNlbCfg;
|
|
pCfg->SetClusterName(szClusterName);
|
|
pCfg->SetClusterNetworkAddress(szClusterNetworkAddress);
|
|
pCfg->SetTrafficMode(TrafficMode);
|
|
Status = pCfg->SetPortRules((LPCWSTR*)pszPortRules, NumPortRules);
|
|
Status = WBEM_NO_ERROR; // TODO -- change once port rules is done
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
wprintf(L"Attempt to set PortRules failed. Error=0x%08lx\n",
|
|
(UINT) Status);
|
|
goto end;
|
|
}
|
|
pCfg->SetHostPriority(HostPriority);
|
|
pCfg->SetDedicatedNetworkAddress(szDedicatedNetworkAddress);
|
|
pCfg->SetClusterModeOnStart(ClusterModeOnStart);
|
|
pCfg->SetRemoteControlEnabled(RemoteControlEnabled);
|
|
}
|
|
|
|
end:
|
|
|
|
delete szClusterNetworkAddress;
|
|
delete pszNetworkAddresses;
|
|
delete szClusterName;
|
|
delete szTrafficMode;
|
|
delete pszPortRules;
|
|
delete szDedicatedNetworkAddress;
|
|
|
|
return Status;
|
|
}
|
|
|
|
WBEMSTATUS
|
|
setup_UpdateClusterConfiguration_input_params(
|
|
IN LPCWSTR szNic,
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg,
|
|
IN IWbemClassObjectPtr spWbemInput
|
|
)
|
|
/*
|
|
Setup the input wmi parameters for the UpdateGetClusterConfiguration method
|
|
|
|
[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] Boolean ClusterModeOnStart,
|
|
[IN] Boolean RemoteControlEnabled,
|
|
[IN] String Password,
|
|
*/
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
|
|
Status = CfgUtilSetWmiStringParam(
|
|
spWbemInput,
|
|
L"AdapterGuid",
|
|
szNic
|
|
);
|
|
//
|
|
// Fill in NetworkAddresses[]
|
|
//
|
|
{
|
|
LPWSTR *pszAddresses = NULL;
|
|
UINT NumAddresses = 0;
|
|
Status = pCfg->GetNetworkAddresses(
|
|
&pszAddresses,
|
|
&NumAddresses
|
|
);
|
|
if (FAILED(Status))
|
|
{
|
|
printf(
|
|
"Setup update params: couldn't extract network addresses from Cfg"
|
|
" for NIC %ws\n",
|
|
szNic
|
|
);
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Note it's ok to not specify any IP addresses -- in which case
|
|
// the default ip addresses will be set up.
|
|
//
|
|
if (pszAddresses != NULL)
|
|
{
|
|
Status = CfgUtilSetWmiStringArrayParam(
|
|
spWbemInput,
|
|
L"NetworkAddresses",
|
|
(LPCWSTR *)pszAddresses,
|
|
NumAddresses
|
|
);
|
|
delete pszAddresses;
|
|
pszAddresses = NULL;
|
|
}
|
|
}
|
|
|
|
if (!pCfg->IsNlbBound())
|
|
{
|
|
//
|
|
// NLB is not bound
|
|
//
|
|
|
|
Status = CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", FALSE);
|
|
goto end;
|
|
}
|
|
else if (!pCfg->IsValidNlbConfig())
|
|
{
|
|
printf(
|
|
"Setup update params: NLB-specific configuration on NIC %ws is invalid\n",
|
|
szNic
|
|
);
|
|
Status = WBEM_E_INVALID_PARAMETER;
|
|
goto end;
|
|
}
|
|
|
|
Status = CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", TRUE);
|
|
if (FAILED(Status))
|
|
{
|
|
printf("Error trying to set NLBBound parameter\n");
|
|
}
|
|
|
|
|
|
//
|
|
// NLB is bound
|
|
//
|
|
|
|
CfgUtilSetWmiBoolParam(spWbemInput, L"NLBBound", TRUE);
|
|
|
|
|
|
//
|
|
// Cluster name
|
|
//
|
|
{
|
|
LPWSTR szName = NULL;
|
|
Status = pCfg->GetClusterName(&szName);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
printf(
|
|
"Setup update params: Could not extract cluster name for NIC %ws\n",
|
|
szNic
|
|
);
|
|
goto end;
|
|
}
|
|
CfgUtilSetWmiStringParam(spWbemInput, L"ClusterName", szName);
|
|
delete (szName);
|
|
szName = NULL;
|
|
}
|
|
|
|
//
|
|
// Cluster and dedicated network addresses
|
|
//
|
|
{
|
|
LPWSTR szAddress = NULL;
|
|
Status = pCfg->GetClusterNetworkAddress(&szAddress);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
printf(
|
|
"Setup update params: Could not extract cluster address for NIC %ws\n",
|
|
szNic
|
|
);
|
|
goto end;
|
|
}
|
|
CfgUtilSetWmiStringParam(
|
|
spWbemInput,
|
|
L"ClusterNetworkAddress",
|
|
szAddress
|
|
);
|
|
delete (szAddress);
|
|
szAddress = NULL;
|
|
|
|
Status = pCfg->GetDedicatedNetworkAddress(&szAddress);
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
printf(
|
|
"Setup update params: Could not extract dedicated address for NIC %ws\n",
|
|
szNic
|
|
);
|
|
goto end;
|
|
}
|
|
CfgUtilSetWmiStringParam(
|
|
spWbemInput,
|
|
L"DedicatedNetworkAddress",
|
|
szAddress
|
|
);
|
|
delete (szAddress);
|
|
szAddress = NULL;
|
|
}
|
|
|
|
//
|
|
// TrafficMode
|
|
//
|
|
{
|
|
LPCWSTR szMode = NULL;
|
|
switch(pCfg->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;
|
|
}
|
|
CfgUtilSetWmiStringParam(spWbemInput, L"TrafficMode", szMode);
|
|
}
|
|
|
|
CfgUtilSetWmiDWORDParam(
|
|
spWbemInput,
|
|
L"HostPriority",
|
|
pCfg->GetHostPriority()
|
|
);
|
|
|
|
if (pCfg->GetClusterModeOnStart() ==
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STARTED)
|
|
{
|
|
CfgUtilSetWmiBoolParam(spWbemInput, L"ClusterModeOnStart", TRUE);
|
|
}
|
|
else
|
|
{
|
|
CfgUtilSetWmiBoolParam(spWbemInput, L"ClusterModeOnStart", FALSE);
|
|
}
|
|
|
|
CfgUtilSetWmiBoolParam(
|
|
spWbemInput,
|
|
L"RemoteControlEnabled",
|
|
pCfg->GetRemoteControlEnabled()
|
|
);
|
|
|
|
//
|
|
// TODO: get port rules
|
|
// [OUT] String PortRules[],
|
|
//
|
|
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
end:
|
|
|
|
wprintf(L"<-Setup update params returns 0x%08lx\n", (UINT) Status);
|
|
|
|
return Status;
|
|
|
|
}
|