/*++ 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; }