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
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;
|
|
}
|