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.
1047 lines
25 KiB
1047 lines
25 KiB
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "private.h"
|
|
#include "engine.h"
|
|
#include "resource.h"
|
|
#include "Document.h"
|
|
#include "Application.h"
|
|
#include "MainForm.h"
|
|
#include "AboutDialog.h"
|
|
#include "application.tmh"
|
|
#include <process.h>
|
|
|
|
Application theApplication;
|
|
|
|
MUsingCom usingCom;
|
|
|
|
BOOL CanRunNLB(void);
|
|
|
|
BEGIN_MESSAGE_MAP( Application, CWinApp )
|
|
ON_COMMAND( ID_HELP, OnHelp )
|
|
ON_COMMAND( ID_APP_ABOUT, OnAppAbout )
|
|
END_MESSAGE_MAP()
|
|
|
|
// #define szNLBMGRREG_DISABLE_DISCLAIMER L"DisableNlbMgrDisclaimer"
|
|
|
|
|
|
#if DBG
|
|
//
|
|
// Allow the DEMO cmdline option
|
|
//
|
|
#define ALLOW_DEMO 1
|
|
#endif //DBG
|
|
|
|
BOOL NoAdminNics(void);
|
|
|
|
|
|
void
|
|
CNlbMgrCommandLineInfo::ParseParam(
|
|
LPCTSTR lpszParam,
|
|
BOOL bFlag,
|
|
BOOL bLast
|
|
)
|
|
//
|
|
// -demo
|
|
// -hostlist file.txt
|
|
// -help -?
|
|
// -autoresfresh
|
|
// -noping
|
|
{
|
|
static enum Commands {
|
|
None = 0,
|
|
Demo,
|
|
NoPing,
|
|
HostList,
|
|
AutoRefresh
|
|
};
|
|
|
|
static UINT LastCommand = None;
|
|
|
|
TRACE_VERB("-> %!FUNC! (szParm=\"%ws\", bFlag=%lu, bLast=%lu)", lpszParam, bFlag, bLast);
|
|
|
|
if (m_bUsage)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
if (bFlag)
|
|
{
|
|
/* Throw an error if this is a flag, but the last command was the
|
|
HostList command, which REQUIRES a non-flag argument following it. */
|
|
if (LastCommand == HostList)
|
|
{
|
|
/* Turn the host list option off to keep NLB manager
|
|
from trying to open NULL filename. */
|
|
m_bHostList = FALSE;
|
|
|
|
m_bUsage = TRUE; // error
|
|
goto end;
|
|
}
|
|
|
|
#if ALLOW_DEMO
|
|
if (!_wcsicmp(lpszParam, L"demo"))
|
|
{
|
|
if (m_bDemo)
|
|
{
|
|
m_bUsage = TRUE; // error
|
|
goto end;
|
|
}
|
|
|
|
m_bDemo = TRUE;
|
|
LastCommand = Demo;
|
|
}
|
|
else
|
|
#endif // ALLOW_DEMO
|
|
if (!_wcsicmp(lpszParam, L"noping"))
|
|
{
|
|
if (m_bNoPing)
|
|
{
|
|
m_bUsage = TRUE; // error
|
|
goto end;
|
|
}
|
|
|
|
m_bNoPing = TRUE;
|
|
LastCommand = NoPing;
|
|
}
|
|
else if (!_wcsicmp(lpszParam, L"hostlist"))
|
|
{
|
|
if (m_bHostList || bLast)
|
|
{
|
|
m_bUsage = TRUE; // error
|
|
goto end;
|
|
}
|
|
|
|
m_bHostList = TRUE;
|
|
LastCommand = HostList;
|
|
}
|
|
else if (!_wcsicmp(lpszParam, L"autorefresh"))
|
|
{
|
|
if (m_bAutoRefresh)
|
|
{
|
|
m_bUsage = TRUE; // error
|
|
goto end;
|
|
}
|
|
|
|
m_bAutoRefresh = TRUE;
|
|
LastCommand = AutoRefresh;
|
|
}
|
|
else
|
|
{
|
|
m_bUsage = TRUE; // error or help
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (LastCommand) {
|
|
case None:
|
|
m_bUsage = TRUE; // error
|
|
break;
|
|
case Demo:
|
|
m_bUsage = TRUE; // error
|
|
break;
|
|
case NoPing:
|
|
m_bUsage = TRUE; // error
|
|
break;
|
|
case HostList:
|
|
m_bstrHostListFile = _bstr_t(lpszParam); // read the file name of the host list
|
|
break;
|
|
case AutoRefresh:
|
|
m_refreshInterval = _wtoi(lpszParam); // read the refresh interval
|
|
|
|
/* If the specified refresh interval is too small to be practical, re-set it. */
|
|
if (m_refreshInterval < NLBMGR_AUTOREFRESH_MIN_INTERVAL)
|
|
m_refreshInterval = NLBMGR_AUTOREFRESH_MIN_INTERVAL;
|
|
|
|
break;
|
|
default:
|
|
m_bUsage = TRUE; // error
|
|
break;
|
|
}
|
|
|
|
/* Re-set the last command. */
|
|
LastCommand = None;
|
|
}
|
|
|
|
end:
|
|
|
|
TRACE_VERB("%!FUNC! <-");
|
|
}
|
|
|
|
|
|
BOOL
|
|
Application::ProcessShellCommand(
|
|
CNlbMgrCommandLineInfo& rCmdInfo
|
|
)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LPCWSTR szFile = NULL;
|
|
TRACE_CRIT("-> %!FUNC!");
|
|
|
|
fRet = CWinApp::ProcessShellCommand(rCmdInfo);
|
|
|
|
if (!fRet)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
szFile = (LPCWSTR) rCmdInfo.m_bstrHostListFile;
|
|
if (szFile==NULL)
|
|
{
|
|
szFile = L"<null>";
|
|
}
|
|
|
|
TRACE_VERB("%!FUNC! bUsage=%lu bDemo=%lu bNoPing=%lu bHostList=%lu szFile=\"%ws\"",
|
|
rCmdInfo.m_bUsage,
|
|
rCmdInfo.m_bDemo,
|
|
rCmdInfo.m_bNoPing,
|
|
rCmdInfo.m_bHostList,
|
|
szFile
|
|
);
|
|
|
|
if (rCmdInfo.m_bUsage)
|
|
{
|
|
_bstr_t bstrMsg = GETRESOURCEIDSTRING( IDS_USAGE_MESSAGE );
|
|
_bstr_t bstrTitle = GETRESOURCEIDSTRING( IDS_USAGE_TITLE );
|
|
|
|
::MessageBox(
|
|
NULL,
|
|
(LPCWSTR) bstrMsg,
|
|
(LPCWSTR) bstrTitle,
|
|
MB_ICONINFORMATION | MB_OK
|
|
);
|
|
fRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (rCmdInfo.m_bDemo)
|
|
{
|
|
_bstr_t bstrMsg = GETRESOURCEIDSTRING( IDS_DEMO_MESSAGE );
|
|
_bstr_t bstrTitle = GETRESOURCEIDSTRING( IDS_DEMO_TITLE );
|
|
::MessageBox(
|
|
NULL,
|
|
(LPCWSTR) bstrMsg,
|
|
(LPCWSTR) bstrTitle,
|
|
MB_ICONINFORMATION | MB_OK
|
|
);
|
|
}
|
|
fRet = TRUE;
|
|
}
|
|
|
|
end:
|
|
|
|
TRACE_CRIT("<- %!FUNC! returns %lu", fRet);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
Application::InitInstance()
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
WPP_INIT_TRACING(L"Microsoft\\NLB\\TPROV");
|
|
|
|
TRACE_INFO("------------ APPLICATION INITITIALIZATION -------------");
|
|
|
|
//
|
|
// Set the current thread id as the main thread id
|
|
//
|
|
m_dwMainThreadId = GetCurrentThreadId();
|
|
|
|
ParseCommandLine(gCmdLineInfo);
|
|
|
|
m_pSingleDocumentTemplate =
|
|
new CSingleDocTemplate( IDR_MAINFRAME,
|
|
RUNTIME_CLASS( Document ),
|
|
RUNTIME_CLASS( MainForm ),
|
|
RUNTIME_CLASS( LeftView) );
|
|
|
|
AddDocTemplate( m_pSingleDocumentTemplate );
|
|
|
|
//
|
|
// NOTE: ProcessShellCommand is our (Application) own version. It
|
|
// calls CWinApp::ProcessShellCommand.
|
|
//
|
|
fRet = ProcessShellCommand( gCmdLineInfo );
|
|
|
|
if (!fRet)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
fRet = CanRunNLB();
|
|
|
|
// fall through...
|
|
|
|
end:
|
|
|
|
if (!fRet)
|
|
{
|
|
// Deinit tracing here.
|
|
WPP_CLEANUP();
|
|
}
|
|
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void
|
|
Application::OnAppAbout()
|
|
{
|
|
AboutDialog aboutDlg;
|
|
aboutDlg.DoModal();
|
|
}
|
|
|
|
void
|
|
Application::OnHelp()
|
|
{
|
|
WCHAR wbuf[CVY_STR_SIZE];
|
|
|
|
/* Spawn the windows help process. */
|
|
StringCbPrintf(wbuf, sizeof(wbuf), L"%ls\\help\\%ls", _wgetenv(L"WINDIR"), CVY_HELP_FILE);
|
|
_wspawnlp(P_NOWAIT, L"hh.exe", L"hh.exe", wbuf, NULL);
|
|
}
|
|
|
|
BOOL CanRunNLB(void)
|
|
/*
|
|
Checks if NLB can run on the current machine. The main check is to make sure that there is atleast one active NIC without NLB bound.
|
|
*/
|
|
{
|
|
if (NoAdminNics())
|
|
{
|
|
|
|
::MessageBox(
|
|
NULL,
|
|
GETRESOURCEIDSTRING( IDS_CANTRUN_NONICS_TEXT), // Contents
|
|
GETRESOURCEIDSTRING( IDS_CANTRUN_NONICS_CAPTION), // caption
|
|
MB_ICONSTOP | MB_OK );
|
|
}
|
|
else
|
|
{
|
|
// ::ShowDisclaimer();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// This class manages NetCfg interfaces
|
|
//
|
|
class AppMyNetCfg
|
|
{
|
|
|
|
public:
|
|
|
|
AppMyNetCfg(VOID)
|
|
{
|
|
m_pINetCfg = NULL;
|
|
m_pLock = NULL;
|
|
}
|
|
|
|
~AppMyNetCfg()
|
|
{
|
|
ASSERT(m_pINetCfg==NULL);
|
|
ASSERT(m_pLock==NULL);
|
|
}
|
|
|
|
WBEMSTATUS
|
|
Initialize(
|
|
BOOL fWriteLock
|
|
);
|
|
|
|
VOID
|
|
Deinitialize(
|
|
VOID
|
|
);
|
|
|
|
|
|
WBEMSTATUS
|
|
GetNlbCompatibleNics(
|
|
OUT LPWSTR **ppszNics,
|
|
OUT UINT *pNumNics,
|
|
OUT UINT *pNumBoundToNlb // OPTIONAL
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetBindingIF(
|
|
IN LPCWSTR szComponent,
|
|
OUT INetCfgComponentBindings **ppIBinding
|
|
);
|
|
|
|
private:
|
|
|
|
INetCfg *m_pINetCfg;
|
|
INetCfgLock *m_pLock;
|
|
|
|
}; // Class AppMyNetCfg
|
|
|
|
|
|
WBEMSTATUS
|
|
AppMyNetCfg::Initialize(
|
|
BOOL fWriteLock
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
INetCfg *pnc = NULL;
|
|
INetCfgLock *pncl = NULL;
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
BOOL fLocked = FALSE;
|
|
BOOL fInitialized=FALSE;
|
|
|
|
if (m_pINetCfg != NULL || m_pLock != NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
goto end;
|
|
}
|
|
|
|
hr = CoCreateInstance( CLSID_CNetCfg,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
IID_INetCfg,
|
|
(void **) &pnc);
|
|
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
// failure to create instance.
|
|
//TRACE_CRIT("ERROR: could not get interface to Net Config");
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// If require, get the write lock
|
|
//
|
|
if (fWriteLock)
|
|
{
|
|
WCHAR *szLockedBy = NULL;
|
|
hr = pnc->QueryInterface( IID_INetCfgLock, ( void **) &pncl );
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
//TRACE_CRIT("ERROR: could not get interface to NetCfg Lock");
|
|
goto end;
|
|
}
|
|
|
|
hr = pncl->AcquireWriteLock( 1, // One Second
|
|
L"NLBManager",
|
|
&szLockedBy);
|
|
if( hr != S_OK )
|
|
{
|
|
//TRACE_CRIT("Could not get write lock. Lock held by %ws",
|
|
// (szLockedBy!=NULL) ? szLockedBy : L"<null>");
|
|
goto end;
|
|
|
|
}
|
|
}
|
|
|
|
// Initializes network configuration by loading into
|
|
// memory all basic networking information
|
|
//
|
|
hr = pnc->Initialize( NULL );
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
// failure to Initialize
|
|
//TRACE_CRIT("INetCfg::Initialize failure ");
|
|
goto end;
|
|
}
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
end:
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
if (pncl!=NULL)
|
|
{
|
|
if (fLocked)
|
|
{
|
|
pncl->ReleaseWriteLock();
|
|
}
|
|
pncl->Release();
|
|
pncl=NULL;
|
|
}
|
|
if( pnc != NULL)
|
|
{
|
|
if (fInitialized)
|
|
{
|
|
pnc->Uninitialize();
|
|
}
|
|
pnc->Release();
|
|
pnc= NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pINetCfg = pnc;
|
|
m_pLock = pncl;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
AppMyNetCfg::Deinitialize(
|
|
VOID
|
|
)
|
|
{
|
|
if (m_pLock!=NULL)
|
|
{
|
|
m_pLock->ReleaseWriteLock();
|
|
m_pLock->Release();
|
|
m_pLock=NULL;
|
|
}
|
|
if( m_pINetCfg != NULL)
|
|
{
|
|
m_pINetCfg->Uninitialize();
|
|
m_pINetCfg->Release();
|
|
m_pINetCfg= NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WBEMSTATUS
|
|
AppMyNetCfg::GetNlbCompatibleNics(
|
|
OUT LPWSTR **ppszNics,
|
|
OUT UINT *pNumNics,
|
|
OUT UINT *pNumBoundToNlb // OPTIONAL
|
|
)
|
|
/*
|
|
Returns an array of pointers to string-version of GUIDS
|
|
that represent the set of alive and healthy NICS that are
|
|
suitable for NLB to bind to -- basically alive ethernet NICs.
|
|
|
|
Delete ppNics using the delete WCHAR[] operator. Do not
|
|
delete the individual strings.
|
|
*/
|
|
{
|
|
#define MY_GUID_LENGTH 38
|
|
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
HRESULT hr;
|
|
IEnumNetCfgComponent* pencc = NULL;
|
|
INetCfgComponent *pncc = NULL;
|
|
ULONG countToFetch = 1;
|
|
ULONG countFetched;
|
|
UINT NumNics = 0;
|
|
LPWSTR *pszNics = NULL;
|
|
INetCfgComponentBindings *pINlbBinding=NULL;
|
|
UINT NumNlbBoundNics = 0;
|
|
|
|
typedef struct _MYNICNODE MYNICNODE;
|
|
|
|
typedef struct _MYNICNODE
|
|
{
|
|
LPWSTR szNicGuid;
|
|
MYNICNODE *pNext;
|
|
} MYNICNODE;
|
|
|
|
MYNICNODE *pNicNodeList = NULL;
|
|
MYNICNODE *pNicNode = NULL;
|
|
|
|
|
|
*ppszNics = NULL;
|
|
*pNumNics = 0;
|
|
|
|
if (pNumBoundToNlb != NULL)
|
|
{
|
|
*pNumBoundToNlb = 0;
|
|
}
|
|
|
|
if (m_pINetCfg == NULL)
|
|
{
|
|
//
|
|
// This means we're not initialized
|
|
//
|
|
ASSERT(FALSE);
|
|
goto end;
|
|
}
|
|
|
|
hr = m_pINetCfg->EnumComponents( &GUID_DEVCLASS_NET, &pencc );
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
// failure to Enumerate net components
|
|
//TRACE_CRIT("%!FUNC! Could not enum netcfg adapters");
|
|
pencc = NULL;
|
|
goto end;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if nlb is bound to the nlb component.
|
|
//
|
|
|
|
//
|
|
// If we need to count of NLB-bound nics, get instance of the nlb component
|
|
//
|
|
if (pNumBoundToNlb != NULL)
|
|
{
|
|
Status = GetBindingIF(L"ms_wlbs", &pINlbBinding);
|
|
if (FAILED(Status))
|
|
{
|
|
//TRACE_CRIT("%!FUNC! WARNING: NLB doesn't appear to be installed on this machine");
|
|
pINlbBinding = NULL;
|
|
}
|
|
}
|
|
|
|
while( ( hr = pencc->Next( countToFetch, &pncc, &countFetched ) )== S_OK )
|
|
{
|
|
LPWSTR szName = NULL;
|
|
|
|
hr = pncc->GetBindName( &szName );
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
//TRACE_CRIT("%!FUNC! WARNING: couldn't get bind name for 0x%p, ignoring",
|
|
// (PVOID) pncc);
|
|
continue;
|
|
}
|
|
|
|
do // while FALSE -- just to allow breaking out
|
|
{
|
|
|
|
|
|
UINT Len = wcslen(szName);
|
|
if (Len != MY_GUID_LENGTH)
|
|
{
|
|
//TRACE_CRIT("%!FUNC! WARNING: GUID %ws has unexpected length %ul",
|
|
// szName, Len);
|
|
break;
|
|
}
|
|
|
|
DWORD characteristics = 0;
|
|
|
|
hr = pncc->GetCharacteristics( &characteristics );
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
//TRACE_CRIT("%!FUNC! WARNING: couldn't get characteristics for %ws, ignoring",
|
|
// szName);
|
|
break;
|
|
}
|
|
|
|
if (((characteristics & NCF_PHYSICAL) || (characteristics & NCF_VIRTUAL)) && !(characteristics & NCF_HIDDEN))
|
|
{
|
|
ULONG devstat = 0;
|
|
|
|
// This is a physical or virtual miniport that is NOT hidden. These
|
|
// are the same adapters that show up in the "Network Connections"
|
|
// dialog. Hidden devices include WAN miniports, RAS miniports and
|
|
// NLB miniports - all of which should be excluded here.
|
|
|
|
// check if the nic is enabled, we are only
|
|
// interested in enabled nics.
|
|
//
|
|
hr = pncc->GetDeviceStatus( &devstat );
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
//TRACE_CRIT(
|
|
// "%!FUNC! WARNING: couldn't get dev status for %ws, ignoring",
|
|
// szName
|
|
// );
|
|
break;
|
|
}
|
|
|
|
// if any of the nics has any of the problem codes
|
|
// then it cannot be used.
|
|
|
|
if( devstat != CM_PROB_NOT_CONFIGURED
|
|
&&
|
|
devstat != CM_PROB_FAILED_START
|
|
&&
|
|
devstat != CM_PROB_NORMAL_CONFLICT
|
|
&&
|
|
devstat != CM_PROB_NEED_RESTART
|
|
&&
|
|
devstat != CM_PROB_REINSTALL
|
|
&&
|
|
devstat != CM_PROB_WILL_BE_REMOVED
|
|
&&
|
|
devstat != CM_PROB_DISABLED
|
|
&&
|
|
devstat != CM_PROB_FAILED_INSTALL
|
|
&&
|
|
devstat != CM_PROB_FAILED_ADD
|
|
)
|
|
{
|
|
//
|
|
// No problem with this nic and also
|
|
// physical device
|
|
// thus we want it.
|
|
//
|
|
|
|
if (pINlbBinding != NULL)
|
|
{
|
|
BOOL fBound = FALSE;
|
|
|
|
hr = pINlbBinding->IsBoundTo(pncc);
|
|
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
//TRACE_CRIT("IsBoundTo method failed for Nic %ws", szName);
|
|
goto end;
|
|
}
|
|
|
|
if( hr == S_OK )
|
|
{
|
|
//TRACE_VERB("BOUND: %ws\n", szName);
|
|
NumNlbBoundNics++;
|
|
fBound = TRUE;
|
|
}
|
|
else if (hr == S_FALSE )
|
|
{
|
|
//TRACE_VERB("NOT BOUND: %ws\n", szName);
|
|
fBound = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
// We allocate a little node to keep this string
|
|
// temporarily and add it to our list of nodes.
|
|
//
|
|
pNicNode = new MYNICNODE;
|
|
if (pNicNode == NULL)
|
|
{
|
|
Status = WBEM_E_OUT_OF_MEMORY;
|
|
goto end;
|
|
}
|
|
ZeroMemory(pNicNode, sizeof(*pNicNode));
|
|
pNicNode->szNicGuid = szName;
|
|
szName = NULL; // so we don't delete inside the lopp.
|
|
pNicNode->pNext = pNicNodeList;
|
|
pNicNodeList = pNicNode;
|
|
NumNics++;
|
|
}
|
|
else
|
|
{
|
|
// There is a problem...
|
|
//TRACE_CRIT(
|
|
// "%!FUNC! WARNING: Skipping %ws because DeviceStatus=0x%08lx",
|
|
// szName, devstat
|
|
// );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//TRACE_VERB("%!FUNC! Ignoring non-physical device %ws", szName);
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
if (szName != NULL)
|
|
{
|
|
CoTaskMemFree( szName );
|
|
}
|
|
pncc->Release();
|
|
pncc=NULL;
|
|
}
|
|
|
|
if (pINlbBinding!=NULL)
|
|
{
|
|
pINlbBinding->Release();
|
|
pINlbBinding = NULL;
|
|
}
|
|
|
|
if (NumNics==0)
|
|
{
|
|
Status = WBEM_NO_ERROR;
|
|
goto end;
|
|
}
|
|
|
|
//
|
|
// Now let's allocate space for all the nic strings and:w
|
|
// 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;
|
|
}
|
|
|
|
pNicNode= pNicNodeList;
|
|
for (UINT u=0; u<NumNics; u++, pNicNode=pNicNode->pNext)
|
|
{
|
|
ASSERT(pNicNode != NULL); // because we just counted NumNics of em.
|
|
UINT Len = wcslen(pNicNode->szNicGuid);
|
|
if (Len != MY_GUID_LENGTH)
|
|
{
|
|
//
|
|
// We should never get here beause we checked the length earlier.
|
|
//
|
|
//TRACE_CRIT("%!FUNC! ERROR: GUID %ws has unexpected length %ul",
|
|
// pNicNode->szNicGuid, Len);
|
|
ASSERT(FALSE);
|
|
Status = WBEM_E_CRITICAL_ERROR;
|
|
goto end;
|
|
}
|
|
CopyMemory(
|
|
pszNics[u],
|
|
pNicNode->szNicGuid,
|
|
(MY_GUID_LENGTH+1)*sizeof(WCHAR));
|
|
ASSERT(pszNics[u][MY_GUID_LENGTH]==0);
|
|
}
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
|
|
end:
|
|
|
|
//
|
|
// Now release the temporarly allocated memory.
|
|
//
|
|
pNicNode= pNicNodeList;
|
|
while (pNicNode!=NULL)
|
|
{
|
|
MYNICNODE *pTmp = pNicNode->pNext;
|
|
CoTaskMemFree(pNicNode->szNicGuid);
|
|
pNicNode->szNicGuid = NULL;
|
|
delete pNicNode;
|
|
pNicNode = pTmp;
|
|
}
|
|
|
|
if (FAILED(Status))
|
|
{
|
|
// TRACE_CRIT("%!FUNC! fails with status 0x%08lx", (UINT) Status);
|
|
NumNics = 0;
|
|
if (pszNics!=NULL)
|
|
{
|
|
delete pszNics;
|
|
pszNics = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pNumBoundToNlb != NULL)
|
|
{
|
|
*pNumBoundToNlb = NumNlbBoundNics;
|
|
}
|
|
*ppszNics = pszNics;
|
|
*pNumNics = NumNics;
|
|
}
|
|
|
|
if (pencc != NULL)
|
|
{
|
|
pencc->Release();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
WBEMSTATUS
|
|
AppMyNetCfg::GetBindingIF(
|
|
IN LPCWSTR szComponent,
|
|
OUT INetCfgComponentBindings **ppIBinding
|
|
)
|
|
{
|
|
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
|
|
INetCfgComponent *pncc = NULL;
|
|
INetCfgComponentBindings *pnccb = NULL;
|
|
HRESULT hr;
|
|
|
|
|
|
if (m_pINetCfg == NULL)
|
|
{
|
|
//
|
|
// This means we're not initialized
|
|
//
|
|
ASSERT(FALSE);
|
|
goto end;
|
|
}
|
|
|
|
|
|
hr = m_pINetCfg->FindComponent(szComponent, &pncc);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// TRACE_CRIT("Error checking if component %ws does not exist\n", szComponent);
|
|
pncc = NULL;
|
|
goto end;
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
Status = WBEM_E_NOT_FOUND;
|
|
// TRACE_CRIT("Component %ws does not exist\n", szComponent);
|
|
goto end;
|
|
}
|
|
|
|
|
|
hr = pncc->QueryInterface( IID_INetCfgComponentBindings, (void **) &pnccb );
|
|
if( !SUCCEEDED( hr ) )
|
|
{
|
|
// TRACE_CRIT("INetCfgComponent::QueryInterface failed ");
|
|
pnccb = NULL;
|
|
goto end;
|
|
}
|
|
|
|
Status = WBEM_NO_ERROR;
|
|
|
|
end:
|
|
|
|
if (pncc)
|
|
{
|
|
pncc->Release();
|
|
pncc=NULL;
|
|
}
|
|
|
|
*ppIBinding = pnccb;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL NoAdminNics(void)
|
|
/*
|
|
Return TRUE IFF all NICs on this machine are bound to NLB.
|
|
*/
|
|
{
|
|
LPWSTR *pszNics = NULL;
|
|
OUT UINT NumNics = 0;
|
|
OUT UINT NumBoundToNlb = 0;
|
|
WBEMSTATUS Status = WBEM_NO_ERROR;
|
|
BOOL fNetCfgInitialized = FALSE;
|
|
AppMyNetCfg NetCfg;
|
|
BOOL fRet = FALSE;
|
|
|
|
//
|
|
// Get and initialize interface to netcfg
|
|
//
|
|
Status = NetCfg.Initialize(FALSE); // TRUE == get write lock.
|
|
if (FAILED(Status))
|
|
{
|
|
goto end;
|
|
}
|
|
fNetCfgInitialized = TRUE;
|
|
|
|
//
|
|
// Get the total list of enabled nics and the list of nics
|
|
// bound to NLB. If there are non-zero enabled nics and all are
|
|
// bound to NLB, we return TRUE.
|
|
//
|
|
Status = NetCfg.GetNlbCompatibleNics(
|
|
&pszNics,
|
|
&NumNics,
|
|
&NumBoundToNlb
|
|
);
|
|
|
|
if (!FAILED(Status))
|
|
{
|
|
fRet = NumNics && (NumNics == NumBoundToNlb);
|
|
if (NumNics)
|
|
{
|
|
delete pszNics;
|
|
pszNics = NULL;
|
|
}
|
|
}
|
|
|
|
end:
|
|
|
|
if (fNetCfgInitialized)
|
|
{
|
|
NetCfg.Deinitialize();
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void
|
|
Application::ProcessMsgQueue()
|
|
{
|
|
MSG msg;
|
|
BOOL bDoingBackgroundProcessing = FALSE;
|
|
|
|
TRACE_INFO(L"-> %!FUNC!");
|
|
|
|
if (!mfn_IsMainThread()) goto end;
|
|
|
|
if (InterlockedIncrement(&m_lMsgProcReentrancyCount) > 1)
|
|
{
|
|
InterlockedDecrement(&m_lMsgProcReentrancyCount);
|
|
goto end;
|
|
}
|
|
|
|
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
|
{
|
|
#if BUGFIX334243
|
|
if (msg.message == MYWM_DEFER_UI_MSG)
|
|
{
|
|
// DummyAction(L"Hey -- got DEFER_UI_MSG ProcessMsgQueue!");
|
|
}
|
|
#endif // BUGFIX334243
|
|
|
|
if ( !this->PumpMessage( ) )
|
|
{
|
|
bDoingBackgroundProcessing = FALSE;
|
|
::PostQuitMessage(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// let MFC do its idle processing
|
|
LONG lIdle = 0;
|
|
while ( this->OnIdle(lIdle++ ) )
|
|
{
|
|
}
|
|
|
|
// Perform some background processing here
|
|
// using another call to OnIdle
|
|
|
|
this->DoWaitCursor(0); // process_msgqueue() breaks the hour glass cursor, This call restores the hour glass cursor if there was one
|
|
|
|
InterlockedDecrement(&m_lMsgProcReentrancyCount);
|
|
|
|
if (m_fQuit)
|
|
{
|
|
::PostQuitMessage(0);
|
|
}
|
|
|
|
end:
|
|
|
|
TRACE_INFO(L"<- %!FUNC!");
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get application-wide lock. If main thread, while waiting to get the lock,
|
|
// periodically process the msg loop.
|
|
//
|
|
VOID
|
|
Application::Lock()
|
|
{
|
|
//
|
|
// See notes.txt entry
|
|
// 01/23/2002 JosephJ DEADLOCK in Leftview::mfn_Lock
|
|
// for the reason for this convoluted implementation of mfn_Lock
|
|
//
|
|
|
|
if (mfn_IsMainThread())
|
|
{
|
|
EnterCriticalSection(&m_crit);
|
|
}
|
|
else
|
|
{
|
|
while (!TryEnterCriticalSection(&m_crit))
|
|
{
|
|
this->ProcessMsgQueue();
|
|
Sleep(100);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get application-wide unlock
|
|
//
|
|
VOID
|
|
Application::Unlock()
|
|
{
|
|
LeaveCriticalSection(&m_crit);
|
|
}
|