Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1333 lines
32 KiB

/*++
Copyright(c) 2001 Microsoft Corporation
Module Name:
NLB Manager
File Name:
Fake.cpp
Abstract:
Fake Implementation of NlbHostXXX Apis (FakeNlbHostXXX apis)
NLBHost is responsible for connecting to an NLB host and getting/setting
its NLB-related configuration.
History:
09/02/01 JosephJ Created
--*/
#include "private.h"
#define SZ_REG_HOSTS L"Hosts" // Where host information is saved.
#define SZ_REG_FQDN L"FQDN" // Fully qualified domain name
#define SZ_REG_INTERFACES L"Interfaces" // Fully qualified domain name
#define BASE_SLEEP 125
BOOL
is_ip_address(LPCWSTR szMachine);
HKEY
open_demo_key(LPCWSTR szSubKey, BOOL fCreate);
DWORD WINAPI FakeThreadProc(
LPVOID lpParameter // thread data
);
typedef struct
{
LPCWSTR szDomainName;
LPCWSTR szClusterNetworkAddress;
LPCWSTR *pszPortRules;
} CLUSTER_INFO;
LPCWSTR rgPortRules1[] = {
L"ip=255.255.255.255 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=NONE load=80",
NULL
};
CLUSTER_INFO
Cluster1Info = {L"good1.com", L"10.0.0.100/255.0.0.0", rgPortRules1};
//
// Keeps track of a pending operation...
//
class CFakePendingInfo
{
public:
CFakePendingInfo(const NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
{
wStatus = Config.Update(pCfg);
if (!FAILED(wStatus))
{
wStatus = WBEM_S_PENDING;
}
// bstrLog;
}
NLB_EXTENDED_CLUSTER_CONFIGURATION Config;
WBEMSTATUS wStatus;
_bstr_t bstrLog;
};
typedef struct
{
//
// These fields are set on initialization
//
LPCWSTR szInterfaceGuid;
LPCWSTR szFriendlyName;
LPCWSTR szNetworkAddress;
BOOL fNlb;
BOOL fHidden;
CLUSTER_INFO *pCluster1Info;
UINT InitialHostPriority;
//
// These are set/updated
//
//
// Current configuration
//
PNLB_EXTENDED_CLUSTER_CONFIGURATION pConfig;
//
// If there is a pending update, info about the pending update.
//
CFakePendingInfo *pPendingInfo;
WBEMSTATUS CompletedUpdateStatus;
} FAKE_IF_INFO;
typedef struct
{
LPCWSTR szHostName;
LPCWSTR szFQDN;
FAKE_IF_INFO *IfInfoList;
LPCWSTR szUserName;
LPCWSTR szPassword;
//
// Run-time state:
//
DWORD dwOperationalState; // WLBS_STOPPED, etc...
BOOL fDead; // If set, we'll pretend this host is dead.
} FAKE_HOST_INFO;
WBEMSTATUS initialize_interface(FAKE_IF_INFO *pIF);
WBEMSTATUS lookup_fake_if(
FAKE_HOST_INFO *pHost,
LPCWSTR szNicGuid,
FAKE_IF_INFO **ppIF
);
WBEMSTATUS lookup_fake_host(
LPCWSTR szConnectionString,
FAKE_IF_INFO **ppIF,
FAKE_HOST_INFO **ppHost
);
FAKE_IF_INFO rgH1IfList[] = {
{ L"{H1I10000-0000-0000-0000-000000000000}",
L"NLB-Front1", L"172.31.56.101/255.0.0.0", FALSE },
{ L"{H1I20000-0000-0000-0000-000000000000}",
L"back1", L"10.0.0.1/255.0.0.0", FALSE },
{ L"{H1I30000-0000-0000-0000-000000000000}",
L"back2", L"11.0.0.1/255.0.0.0", FALSE }, { NULL }
};
FAKE_IF_INFO rgH2IfList[] = {
{ L"{H2I10000-0000-0000-0000-000000000000}",
L"NLB-Front2", L"172.31.56.102/255.0.0.0", FALSE },
{ L"{H2I20000-0000-0000-0000-000000000000}",
L"back1", L"10.0.0.2/255.0.0.0", FALSE },
{ L"{H2I30000-0000-0000-0000-000000000000}",
L"back2", L"11.0.0.2/255.0.0.0", FALSE },
{ NULL }
};
FAKE_IF_INFO rgH3IfList[] = {
{ L"{H3I10000-0000-0000-0000-000000000000}",
L"NLB-Front3", L"172.31.56.103/255.0.0.0", FALSE },
{ L"{H3I20000-0000-0000-0000-000000000000}",
L"back1", L"10.0.0.3/255.0.0.0", FALSE },
{ L"{H3I30000-0000-0000-0000-000000000000}",
L"back2", L"11.0.0.3/255.0.0.0", FALSE },
{ NULL }
};
FAKE_IF_INFO rgH4IfList[] = {
{ L"{H4I10000-0000-0000-0000-000000000000}",
L"nic1", L"10.1.0.1/255.0.0.0", TRUE, FALSE, &Cluster1Info},
{ L"{H4I20000-0000-0000-0000-000000000000}",
L"nic2", L"11.1.0.1/255.0.0.0", FALSE },
{ L"{H4I30000-0000-0000-0000-000000000000}",
L"nic3", L"12.1.0.1/255.0.0.0", FALSE },
{ NULL }
};
FAKE_IF_INFO rgH5IfList[] = {
{ L"{H5I10000-0000-0000-0000-000000000000}",
L"nic1", L"10.1.0.2/255.0.0.0", TRUE },
{ L"{H5I20000-0000-0000-0000-000000000000}",
L"nic2", L"11.1.0.2/255.0.0.0", FALSE },
{ L"{H5I30000-0000-0000-0000-000000000000}",
L"nic3", L"12.1.0.2/255.0.0.0", FALSE },
{ NULL }
};
FAKE_IF_INFO rgH6IfList[] = {
{ L"{H6I10000-0000-0000-0000-000000000000}",
L"nic1", L"10.1.0.3/255.0.0.0", TRUE },
{ L"{H6I20000-0000-0000-0000-000000000000}",
L"nic2", L"11.1.0.3/255.0.0.0", FALSE },
{ L"{H6I30000-0000-0000-0000-000000000000}",
L"nic3", L"12.1.0.3/255.0.0.0", FALSE },
{ NULL }
};
FAKE_HOST_INFO rgFakeHostInfo[] =
{
{ L"NLB-A", L"nlb-a.cheesegalaxy.com", rgH1IfList },
{ L"NLB-B", L"nlb-b.cheesegalaxy.com", rgH2IfList },
{ L"NLB-C", L"nlb-c.cheesegalaxy.com", rgH3IfList },
{ L"NLB-X", L"nlb-x.cheesegalaxy.com", rgH4IfList },
{ L"NLB-Y", L"nlb-y.cheesegalaxy.com", rgH5IfList },
{ L"NLB-Z", L"nlb-z.cheesegalaxy.com", rgH6IfList, L"un", L"pwd" },
{ NULL }
};
class CFake
{
public:
CFake(void)
{
InitializeCriticalSection(&m_crit);
}
~CFake()
{
DeleteCriticalSection(&m_crit);
}
CRITICAL_SECTION m_Lock;
PNLB_EXTENDED_CLUSTER_CONFIGURATION pConfig;
// map<_bstr_t, PNLB_EXTENDED_CLUSTER_CONFIGURATION> mapGuidToExtCfg;
// map<_bstr_t, UINT> mapGuidToExtCfg;
CRITICAL_SECTION m_crit;
void mfn_Lock(void) {EnterCriticalSection(&m_crit);}
void mfn_Unlock(void) {LeaveCriticalSection(&m_crit);}
};
CFake gFake;
VOID
FakeInitialize(VOID)
{
//
//
//
}
LPWSTR
reg_read_string(
HKEY hk,
LPCWSTR szName,
BOOL fMultiSz
);
WBEMSTATUS
FakeNlbHostConnect(
PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
OUT FAKE_HOST_INFO **pHost
);
WBEMSTATUS
FakeNlbHostGetCompatibleNics(
PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
OUT LPWSTR **ppszNics, // free using delete
OUT UINT *pNumNics, // free using delete
OUT UINT *pNumBoundToNlb
)
{
FAKE_HOST_INFO *pHost = NULL;
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
UINT NumNics=0;
UINT NumBoundToNlb=0;
LPWSTR *pszNics = NULL;
*ppszNics = NULL;
*pNumNics = NULL;
*pNumBoundToNlb = NULL;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
gFake.mfn_Lock();
if (FAILED(Status))
{
goto end;
}
FAKE_IF_INFO *pIF = NULL;
for (pIF=pHost->IfInfoList; pIF->szInterfaceGuid!=NULL; pIF++)
{
if (!pIF->fHidden)
{
NumNics++;
}
}
if (NumNics==0)
{
Status = WBEM_NO_ERROR;
goto end;
}
//
// Now let's allocate space for all the nic strings and
// copy them over..
//
#define MY_GUID_LENGTH 38
pszNics = CfgUtilsAllocateStringArray(NumNics, MY_GUID_LENGTH);
if (pszNics == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
for (pIF=pHost->IfInfoList; pIF->szInterfaceGuid!=NULL; pIF++)
{
UINT u = (UINT)(pIF-pHost->IfInfoList);
UINT Len = wcslen(pIF->szInterfaceGuid);
if (pIF->fHidden)
{
continue;
}
if (Len > MY_GUID_LENGTH)
{
ASSERT(FALSE);
Status = WBEM_E_CRITICAL_ERROR;
goto end;
}
CopyMemory(
pszNics[u],
pIF->szInterfaceGuid,
(Len+1)*sizeof(WCHAR));
ASSERT(pszNics[u][Len]==0);
if (pIF->fNlb)
{
NumBoundToNlb++;
}
}
Status = WBEM_NO_ERROR;
end:
gFake.mfn_Unlock();
if (FAILED(Status))
{
delete pszNics;
pszNics = NULL;
NumNics = 0;
NumBoundToNlb = 0;
}
*ppszNics = pszNics;
*pNumNics = NumNics;
if (pNumBoundToNlb !=NULL)
{
*pNumBoundToNlb = NumBoundToNlb;
}
return Status;
}
WBEMSTATUS
FakeNlbHostGetMachineIdentification(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
OUT LPWSTR *pszMachineName, // free using delete
OUT LPWSTR *pszMachineGuid, // free using delete -- may be null
OUT BOOL *pfNlbMgrProviderInstalled // If nlb manager provider is installed.
)
{
FAKE_HOST_INFO *pHost = NULL;
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
*pszMachineName = NULL;
*pszMachineGuid = NULL;
*pfNlbMgrProviderInstalled = TRUE;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
//
// Set WMI machine name
//
{
UINT u = wcslen(pHost->szHostName);
LPWSTR szMachineName = NULL;
szMachineName = new WCHAR[u+1];
if (szMachineName == NULL)
{
Status = WBEM_E_CRITICAL_ERROR;
goto end;
}
StringCchCopy(szMachineName, u+1, pHost->szHostName);
*pszMachineName = szMachineName;
}
Status = WBEM_NO_ERROR;
end:
return Status;
}
WBEMSTATUS
FakeNlbHostGetConfiguration(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
IN LPCWSTR szNicGuid,
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCurrentCfg
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
FAKE_HOST_INFO *pHost = NULL;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
//
// Look for the specified interface
//
FAKE_IF_INFO *pIF = NULL;
Status = lookup_fake_if(pHost, szNicGuid, &pIF);
if (!FAILED(Status))
{
gFake.mfn_Lock();
Status = pCurrentCfg->Update(pIF->pConfig);
gFake.mfn_Unlock();
}
end:
return Status;
}
WBEMSTATUS
FakeNlbHostDoUpdate(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies 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;
FAKE_HOST_INFO *pHost = NULL;
*ppLog = NULL;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
//
// Look for the specified interface
//
FAKE_IF_INFO *pIF = NULL;
Status = lookup_fake_if(pHost, szNicGuid, &pIF);
if (!FAILED(Status))
{
BOOL fSetPwd = FALSE;
DWORD dwHashPwd = 0;
//
// Report if there's a password specified...
//
{
LPCWSTR szNewPwd = pNewState->GetNewRemoteControlPasswordRaw();
WCHAR rgTmp[256];
if (szNewPwd == NULL)
{
BOOL fRet = FALSE;
fRet = pNewState->GetNewHashedRemoteControlPassword(
dwHashPwd
);
if (fRet)
{
StringCbPrintf(rgTmp, sizeof(rgTmp), L"NewHashPwd=0x%08lx", dwHashPwd);
szNewPwd = rgTmp;
fSetPwd = TRUE;
}
}
else
{
//
// Create our own ad-hoc hash here...
//
for (LPCWSTR sz = szNewPwd; *sz; sz++)
{
dwHashPwd ^= *sz;
if (dwHashPwd & 0x80000000)
{
dwHashPwd <<= 1;
dwHashPwd |= 1;
}
else
{
dwHashPwd <<=1;
}
}
fSetPwd = TRUE;
}
if (szNewPwd != NULL)
{
#if 0
::MessageBox(
NULL,
szNewPwd, // msg
L"Update: new password specified!", // caption
MB_ICONINFORMATION | MB_OK
);
#endif // 0
}
}
Sleep(2*BASE_SLEEP);
gFake.mfn_Lock();
NLB_EXTENDED_CLUSTER_CONFIGURATION NewCopy;
Status = NewCopy.Update(pNewState);
if (!FAILED(Status))
{
NLBERROR nerr;
BOOL fConnChange = FALSE;
DWORD dwOldHashPwd = CfgUtilGetHashedRemoteControlPassword(
&pIF->pConfig->NlbParams
);
//
// Set the hashed pwd field if necessary, otherwise preserve
// the old one.
//
if (!fSetPwd)
{
dwHashPwd = dwOldHashPwd;
}
#if 0
if (dwHashPwd != dwOldHashPwd)
{
WCHAR buf[64];
(void)StringCbPrintf(
buf,
sizeof(buf),
L"Old=0x%lx New=0x%lx",
dwOldHashPwd, dwHashPwd
);
::MessageBox(
NULL,
buf, // msg
L"Fake Update: Change in dwHashPwd!", // caption
MB_ICONINFORMATION | MB_OK
);
}
#endif // 0
CfgUtilSetHashedRemoteControlPassword(
&NewCopy.NlbParams,
dwHashPwd
);
nerr = pIF->pConfig->AnalyzeUpdate(&NewCopy, &fConnChange);
// TODO: if fConnChange, do stuff in background.
if (NLBOK(nerr))
{
if (pIF->pPendingInfo != NULL)
{
Status = WBEM_E_SERVER_TOO_BUSY;
}
else
{
if (fConnChange)
{
//
// We'll do the update in the background.
//
CFakePendingInfo *pPendingInfo;
pPendingInfo = new CFakePendingInfo(&NewCopy);
if (pPendingInfo == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
}
else
{
BOOL fRet;
pIF->pPendingInfo = pPendingInfo;
fRet = QueueUserWorkItem(
FakeThreadProc,
pIF,
// WT_EXECUTEDEFAULT
WT_EXECUTELONGFUNCTION
);
if (fRet)
{
Status = WBEM_S_PENDING;
}
else
{
Status = WBEM_E_OUT_OF_MEMORY;
pIF->pPendingInfo = NULL;
delete pPendingInfo;
}
}
}
else
{
Status = pIF->pConfig->Update(&NewCopy);
pIF->pConfig->Generation++;
}
}
}
else
{
if (nerr == NLBERR_NO_CHANGE)
{
Status = WBEM_S_FALSE;
}
else if (nerr == NLBERR_INVALID_CLUSTER_SPECIFICATION)
{
Status = WBEM_E_INVALID_PARAMETER;
}
}
}
gFake.mfn_Unlock();
}
end:
return Status;
}
WBEMSTATUS
FakeNlbHostGetUpdateStatus(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
IN LPCWSTR szNicGuid,
IN UINT Generation,
OUT WBEMSTATUS *pCompletionStatus,
OUT WCHAR **ppLog // free using delete operator.
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
FAKE_HOST_INFO *pHost = NULL;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
//
// Look for the specified interface
//
FAKE_IF_INFO *pIF = NULL;
Status = lookup_fake_if(pHost, szNicGuid, &pIF);
if (!FAILED(Status))
{
gFake.mfn_Lock();
if (pIF->pPendingInfo != NULL)
{
*pCompletionStatus = WBEM_S_PENDING;
}
else
{
*pCompletionStatus = pIF->CompletedUpdateStatus;
}
Status = WBEM_NO_ERROR;
gFake.mfn_Unlock();
}
end:
return Status;
}
WBEMSTATUS
FakeNlbHostPing(
IN LPCWSTR szBindString,
IN UINT Timeout, // In milliseconds.
OUT ULONG *pResolvedIpAddress // in network byte order.
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
FAKE_HOST_INFO *pHost = NULL;
//Status = FakeNlbHostConnect(pConnInfo, &pHost);
*pResolvedIpAddress = 0x0100000a;
Status = WBEM_NO_ERROR;
if (FAILED(Status))
{
goto end;
}
end:
return Status;
}
BOOL
is_ip_address(LPCWSTR szMachine)
/*
Returns TRUE IFF szMachine is an IP address.
It doesn't check if it's a valid IP address.
In fact, all it checks is if it's only consisting
of numbers and dots.
*/
{
BOOL fRet = FALSE;
#define BUFSZ 20
WCHAR rgBuf[BUFSZ];
if (wcslen(szMachine) >= BUFSZ) goto end;
if (swscanf(szMachine, L"%[0-9.]", rgBuf)!=1) goto end;
if (wcscmp(szMachine, rgBuf)) goto end;
fRet = TRUE;
end:
return fRet;
}
HKEY
open_demo_key(LPCWSTR szSubKey, BOOL fCreate)
/*
Open nlbmanager demo registry key with read/write access.
*/
{
WCHAR szKey[1024];
HKEY hKey = NULL;
LONG lRet;
StringCbCopy(szKey, sizeof(szKey),
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NLB\\NlbManager\\Demo"
);
if (szSubKey != NULL)
{
StringCbCat(szKey, sizeof(szKey), L"\\");
StringCbCat(szKey, sizeof(szKey), szSubKey);
}
if (fCreate)
{
DWORD dwDisposition;
lRet = RegCreateKeyEx(
HKEY_LOCAL_MACHINE, // handle to an open key
szKey, // address of subkey name
0, // reserved
L"class", // address of class string
0, // special options flag
KEY_ALL_ACCESS, // desired security access
NULL, // address of key security structure
&hKey, // address of buffer for opened handle
&dwDisposition // address of disposition value buffer
);
}
else
{
lRet = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, // handle to an open key
szKey, // address of subkey name
0, // reserved
KEY_ALL_ACCESS, // desired security access
&hKey // address of buffer for opened handle
);
}
if (lRet != ERROR_SUCCESS)
{
hKey = NULL;
}
return hKey;
}
LPWSTR
reg_read_string(
HKEY hk,
LPCWSTR szName,
BOOL fMultiSz
)
/*
Read a string from the registry, allocating memory using "new WCHAR"
*/
{
LONG lRet;
DWORD dwType;
DWORD dwData = 0;
DWORD dwDesiredType = REG_SZ;
if (fMultiSz)
{
dwDesiredType = REG_MULTI_SZ;
}
lRet = RegQueryValueEx(
hk, // handle to key to query
szName,
NULL, // reserved
&dwType, // address of buffer for value type
(LPBYTE) NULL, // address of data buffer
&dwData // address of data buffer size
);
if ( lRet != ERROR_SUCCESS
|| dwType != dwDesiredType
|| dwData <= sizeof(WCHAR))
{
goto end;
}
LPWSTR szValue = new WCHAR[dwData/sizeof(WCHAR)+1]; // bytes to wchars
if (szValue == NULL) goto end;
lRet = RegQueryValueEx(
hk, // handle to key to query
szName,
NULL, // reserved
&dwType, // address of buffer for value type
(LPBYTE) szValue, // address of data buffer
&dwData // address of data buffer size
);
if ( lRet != ERROR_SUCCESS
|| dwType != dwDesiredType
|| dwData <= sizeof(WCHAR))
{
delete[] szValue;
szValue = NULL;
goto end;
}
end:
return szValue;
}
WBEMSTATUS
FakeNlbHostConnect(
PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
OUT FAKE_HOST_INFO **ppHost
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
/*
For now, just look for machine name of fqdn
*/
FAKE_HOST_INFO *pfhi = rgFakeHostInfo;
LPCWSTR szHostName;
LPCWSTR szFQDN;
FAKE_IF_INFO *IfInfoList;
LPCWSTR szMachine = NULL;
LPCWSTR szUserName = pConnInfo->szUserName;
LPCWSTR szPassword = pConnInfo->szPassword;
*ppHost = NULL;
if (pConnInfo == NULL)
{
// We don't support local connections.
Status = WBEM_E_NOT_FOUND;
goto end;
}
if (szUserName == NULL)
{
szUserName = L"null-name";
}
szMachine = pConnInfo->szMachine; // should not be NULL.
for (; pfhi->szHostName != NULL; pfhi++)
{
if ( !_wcsicmp(szMachine, pfhi->szHostName)
|| !_wcsicmp(szMachine, pfhi->szFQDN))
{
break;
}
}
if (pfhi->szHostName == NULL || pfhi->fDead)
{
Sleep(3*BASE_SLEEP);
Status = WBEM_E_NOT_FOUND;
}
else
{
Sleep(BASE_SLEEP);
if (pfhi->szUserName != NULL)
{
WCHAR rgClearPassword[128];
if (szPassword == NULL)
{
ARRAYSTRCPY(rgClearPassword, L"null-password");
}
else
{
BOOL fRet = CfgUtilDecryptPassword(
szPassword,
ASIZE(rgClearPassword),
rgClearPassword
);
if (!fRet)
{
ARRAYSTRCPY(rgClearPassword, L"bogus-password");
}
}
if ( !_wcsicmp(szUserName, pfhi->szUserName)
&& !_wcsicmp(rgClearPassword, pfhi->szPassword))
{
Status = WBEM_NO_ERROR;
*ppHost = pfhi;
}
else
{
Status = (WBEMSTATUS) E_ACCESSDENIED;
}
// We don't need to put this here, because
// this is fake (demo-mode) code:
// RtlSecureZeroMemory(rgClearPassword);
}
else
{
Status = WBEM_NO_ERROR;
*ppHost = pfhi;
}
}
end:
return Status;
}
WBEMSTATUS initialize_interface(FAKE_IF_INFO *pIF)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
PNLB_EXTENDED_CLUSTER_CONFIGURATION pConfig = NULL;
if (pIF->pConfig != NULL)
{
ASSERT(FALSE);
goto end;
}
pConfig = new NLB_EXTENDED_CLUSTER_CONFIGURATION;
if (pConfig == NULL) goto end;
Status = pConfig->SetFriendlyName(pIF->szFriendlyName);
if (FAILED(Status)) goto end;
Status = pConfig->SetNetworkAddresses(&pIF->szNetworkAddress, 1);
if (FAILED(Status)) goto end;
if (pIF->fNlb)
{
pConfig->SetDefaultNlbCluster();
pConfig->SetClusterName(L"BadCluster.COM");
}
pIF->pConfig = pConfig;
pIF->pConfig->Generation = 1;
pIF->pPendingInfo = NULL;
pIF->CompletedUpdateStatus = WBEM_E_CRITICAL_ERROR;
end:
return Status;
}
WBEMSTATUS lookup_fake_if(
FAKE_HOST_INFO *pHost,
LPCWSTR szNicGuid,
FAKE_IF_INFO **ppIF
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
FAKE_IF_INFO *pIF;
*ppIF = NULL;
for (pIF=pHost->IfInfoList; pIF->szInterfaceGuid!=NULL; pIF++)
{
if (!wcscmp(szNicGuid, pIF->szInterfaceGuid))
{
if (!pIF->fHidden)
{
break;
}
}
}
if (pIF->szInterfaceGuid==NULL)
{
Status = WBEM_E_NOT_FOUND;
goto end;
}
//
// Perform on-demand initialization
//
{
Status = WBEM_NO_ERROR;
gFake.mfn_Lock();
if (pIF->pConfig == NULL)
{
Status = initialize_interface(pIF);
ASSERT(pIF->pConfig!=NULL);
}
gFake.mfn_Unlock();
*ppIF = pIF;
}
end:
return Status;
}
WBEMSTATUS lookup_fake_host(
LPCWSTR szConnectionString,
FAKE_IF_INFO **ppIF,
FAKE_HOST_INFO **ppHost
);
WBEMSTATUS
FakeNlbHostControlCluster(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
IN LPCWSTR szNicGuid,
IN LPCWSTR szVip,
IN DWORD *pdwPortNum,
IN WLBS_OPERATION_CODES Operation,
OUT DWORD *pdwOperationStatus,
OUT DWORD *pdwClusterOrPortStatus,
OUT DWORD *pdwHostMap
)
{
FAKE_HOST_INFO *pHost = NULL;
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
DWORD dwPort = 0;
LPCWSTR szPort = L"(null)";
LPCWSTR szOp = L"";
if (pdwPortNum != NULL)
{
dwPort = *pdwPortNum;
szPort = L"";
}
if (szVip == NULL)
{
szVip = L"null";
}
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
DWORD dwOperationalState = WLBS_CONVERGED;
if (pHost->dwOperationalState != 0)
{
dwOperationalState = pHost->dwOperationalState;
}
switch(Operation)
{
case WLBS_START:
szOp = L"start";
if (dwOperationalState == WLBS_STOPPED)
{
dwOperationalState = WLBS_CONVERGING;
}
else
{
dwOperationalState = WLBS_CONVERGED;
}
break;
case WLBS_STOP:
szOp = L"stop";
dwOperationalState = WLBS_STOPPED;
break;
case WLBS_DRAIN:
szOp = L"drain";
dwOperationalState = WLBS_DRAINING;
break;
case WLBS_SUSPEND:
szOp = L"suspend";
dwOperationalState = WLBS_SUSPENDED;
break;
case WLBS_RESUME:
szOp = L"resume";
// dwOperationalState = WLBS_CONVERGED;
dwOperationalState = WLBS_DISCONNECTED;
break;
case WLBS_PORT_ENABLE:
szOp = L"port-enable";
break;
case WLBS_PORT_DISABLE:
szOp = L"port-disable";
break;
case WLBS_PORT_DRAIN:
szOp = L"port-drain";
break;
case WLBS_QUERY:
szOp = L"query";
break;
case WLBS_QUERY_PORT_STATE:
szOp = L"port-query";
break;
default:
szOp = L"unknown";
break;
}
wprintf(
L"FakeNlbHostControlCluster: op=%ws "
L"ip=%ws "
L"Port=%lu%ws\n",
szOp,
szVip,
dwPort, szPort
);
pHost->dwOperationalState = dwOperationalState;
*pdwOperationStatus = WLBS_ALREADY; // dummy values ...
*pdwClusterOrPortStatus = dwOperationalState;
*pdwHostMap = 0x3;
end:
return Status;
}
WBEMSTATUS
FakeNlbHostGetClusterMembers(
IN PWMI_CONNECTION_INFO pConnInfo, // NULL implies local
IN LPCWSTR szNicGuid,
OUT DWORD *pNumMembers,
OUT NLB_CLUSTER_MEMBER_INFO **ppMembers // free using delete[]
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
FAKE_HOST_INFO *pHost = NULL;
*pNumMembers = 0;
*ppMembers = NULL;
Status = FakeNlbHostConnect(pConnInfo, &pHost);
if (FAILED(Status))
{
goto end;
}
//
// Look for the specified interface
//
FAKE_IF_INFO *pIF = NULL;
Status = lookup_fake_if(pHost, szNicGuid, &pIF);
if (!FAILED(Status))
{
gFake.mfn_Lock();
if (pIF->pConfig->IsValidNlbConfig())
{
NLB_CLUSTER_MEMBER_INFO *pMembers;
pMembers = new NLB_CLUSTER_MEMBER_INFO[1];
if (pMembers == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
}
else
{
ZeroMemory(pMembers, sizeof(*pMembers));
pMembers->HostId = pIF->pConfig->NlbParams.host_priority;
StringCbCopy(
pMembers->DedicatedIpAddress,
sizeof(pMembers->DedicatedIpAddress),
pIF->pConfig->NlbParams.ded_ip_addr
);
StringCbCopy(
pMembers->HostName,
sizeof(pMembers->HostName),
pHost->szFQDN
);
*pNumMembers = 1;
*ppMembers = pMembers;
}
}
gFake.mfn_Unlock();
}
end:
return Status;
}
DWORD WINAPI FakeThreadProc(
LPVOID lpParameter // thread data
)
{
FAKE_IF_INFO *pIF = (FAKE_IF_INFO *) lpParameter;
//
// Display the msg box to block input.
//
{
WCHAR rgBuf[256];
gFake.mfn_Lock();
StringCbPrintf(
rgBuf,
sizeof(rgBuf),
L"Update of NIC %ws (GUID %ws)",
pIF->szFriendlyName,
pIF->szInterfaceGuid
);
gFake.mfn_Unlock();
//
// Call this AFTER unlocking!
//
#if 0
MessageBox(NULL, rgBuf, L"FakeThreadProc", MB_OK);
#endif // 0
}
//
// Now actually lock and perform the update...
//
gFake.mfn_Lock();
if (pIF->pPendingInfo == NULL)
{
ASSERT(FALSE);
goto end_unlock;
}
pIF->CompletedUpdateStatus =
pIF->pConfig->Update(&pIF->pPendingInfo->Config);
pIF->pConfig->Generation++;
delete pIF->pPendingInfo;
pIF->pPendingInfo = NULL;
end_unlock:
gFake.mfn_Unlock();
return 0;
}