Port NetworkDetector code from v1 because v3 NetworkDetector was busted at some point:
* improper detection of Windows version * crashes on downlevel OS
This commit is contained in:
Родитель
83b7fb26a5
Коммит
efdbce852f
|
@ -17,12 +17,15 @@
|
|||
// break Windows 7.1 compatibility. We cannot afford breaking Windows 7.1 compatibility at this time.
|
||||
DEFINE_GUID(IID_INetworkCostManager2, 0xdcb00008, 0x570f, 0x4a9b, 0x8d, 0x69, 0x19, 0x9f, 0xdb, 0xa5, 0x72, 0x3b);
|
||||
|
||||
#define NETDETECTOR_START WM_USER+1
|
||||
#define NETDETECTOR_STOP WM_USER+2
|
||||
|
||||
#define NETDETECTOR_COM_SETTLE_MS 1000
|
||||
|
||||
namespace ARIASDK_NS_BEGIN
|
||||
{
|
||||
|
||||
namespace Windows {
|
||||
|
||||
const UINT32 LparamMessageValue = 111111;
|
||||
// Malwarebytes have been detected
|
||||
static bool mbDetected = false;
|
||||
|
||||
|
@ -31,7 +34,7 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
std::string to_string(const HString *name)
|
||||
std::string to_string(HString *name)
|
||||
{
|
||||
UINT32 length;
|
||||
PCWSTR rawString = name->GetRawBuffer(&length);
|
||||
|
@ -45,35 +48,46 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
inline std::string to_string(GUID guid)
|
||||
{
|
||||
return MAT::to_string(guid);
|
||||
std::string to_string(GUID guid) {
|
||||
std::string result;
|
||||
char buff[40] = { 0 }; // Maximum hyphenated GUID length with braces is 38 + null terminator
|
||||
sprintf_s(buff, sizeof(buff),
|
||||
"{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
|
||||
guid.Data1, guid.Data2, guid.Data3,
|
||||
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
|
||||
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
result = buff;
|
||||
return result;
|
||||
}
|
||||
|
||||
NetworkCost const& NetworkDetector::GetNetworkCost() const
|
||||
{
|
||||
NetworkCost const& NetworkDetector::GetNetworkCost() {
|
||||
return (NetworkCost const &)m_currentNetworkCost;
|
||||
}
|
||||
|
||||
NetworkType NetworkDetector::GetNetworkType()
|
||||
{
|
||||
return m_currentNetworkType.load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get current realtime network cost synchronously.
|
||||
/// This function can be called on any Windows release and it provides a SEH handler.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:6320)
|
||||
#pragma warning(disable: 6320)
|
||||
int NetworkDetector::GetCurrentNetworkCost()
|
||||
{
|
||||
#if 0
|
||||
// We don't know the cost of something that is not there
|
||||
if (m_connectivity == NLM_CONNECTIVITY_DISCONNECTED)
|
||||
{
|
||||
LOG_TRACE("Disconnected!");
|
||||
TRACE("Disconnected!");
|
||||
m_currentNetworkCost = NetworkCost_Unknown;
|
||||
}
|
||||
#endif
|
||||
m_currentNetworkCost = NetworkCost_Unknown;
|
||||
try {
|
||||
__try {
|
||||
m_currentNetworkCost = _GetCurrentNetworkCost();
|
||||
}
|
||||
//******************************************************************************************************************************
|
||||
|
@ -85,7 +99,7 @@ namespace ARIASDK_NS_BEGIN
|
|||
// Exception thrown at XXX (KernelBase.dll) in YYY : The binding handle is invalid.
|
||||
// If there is a handler for this exception, the program may be safely continued.
|
||||
//*******************************************************************************************************************************
|
||||
catch (...)
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
LOG_ERROR("Unable to obtain network state!");
|
||||
m_currentNetworkCost = NetworkCost_Unknown;
|
||||
|
@ -106,7 +120,7 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// Get current network connectivity state
|
||||
/// </summary>
|
||||
/// <returns>Value of enum NLM_CONNECTIVITY</returns>
|
||||
int NetworkDetector::GetConnectivity() const
|
||||
int NetworkDetector::GetConnectivity()
|
||||
{
|
||||
return m_connectivity;
|
||||
}
|
||||
|
@ -159,9 +173,154 @@ namespace ARIASDK_NS_BEGIN
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* This code below uses GetInternetConnectionProfile API. But it's broken by Malwarebytes 3.0 antivirus... (sigh)
|
||||
* App crashes on boot if MalwareBytes Anti-Exploit 3.0 is installed and Microsoft.Office.Telemetry.AriaEventSink
|
||||
* feature gate is enabled: https://office.visualstudio.com/DefaultCollection/OE/_workitems/edit/1384293
|
||||
*/
|
||||
#ifdef WIN32 // Workaround for Malwarebytes crash that reports network cost 'Unknown' because calling into API would crash us.
|
||||
#ifdef _WIN64
|
||||
LPWSTR mbae_dll = L"mbae64.dll";
|
||||
#else
|
||||
LPWSTR mbae_dll = L"mbae.dll";
|
||||
#endif
|
||||
if (GetModuleHandle(mbae_dll) != NULL)
|
||||
{
|
||||
mbDetected = true;
|
||||
LOG_WARN("Malwarebytes have been detected!");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
// Function below may throw "The binding handle is invalid." on Debug builds with debugger attached,
|
||||
// but it is benign. Possible explanation of this behavior is available here:
|
||||
// *** Explaining ‘The Binding Handle Is Invalid’ ***
|
||||
// https://blogs.msdn.microsoft.com/greggm/2006/01/04/explaining-the-binding-handle-is-invalid/
|
||||
// This call is always surrounded by SEH handler implemented in GetCurrentNetworkCost .
|
||||
// If you are running debug bits, exclude this exception in Debugger settings and hit [Continue]
|
||||
HRESULT hr = networkInfoStats->GetInternetConnectionProfile(&m_connection_profile);
|
||||
if (FAILED(hr) || (m_connection_profile == NULL) || (m_connection_profile.Get() == NULL))
|
||||
{
|
||||
LOG_ERROR("Unable to get GetInternetConnectionProfile");
|
||||
return NetworkCost_Unknown;
|
||||
}
|
||||
|
||||
// FIXME: it crashes here if network goes down!!!
|
||||
ComPtr<IConnectionCost> cost;
|
||||
hr = m_connection_profile->GetConnectionCost(&cost);
|
||||
if (hr)
|
||||
{
|
||||
LOG_WARN("Cost unavailable!");
|
||||
}
|
||||
|
||||
boolean isApproachingDataLimit;
|
||||
hr = cost->get_ApproachingDataLimit(&isApproachingDataLimit);
|
||||
if (!hr)
|
||||
{
|
||||
TRACE("isApproachingDataLimit = %d", isApproachingDataLimit);
|
||||
}
|
||||
|
||||
NetworkCostType type;
|
||||
hr = cost->get_NetworkCostType(&type);
|
||||
if (!hr)
|
||||
{
|
||||
TRACE("NetworkCostType = %d [%s]", type, GetNetworkCostName(type));
|
||||
}
|
||||
|
||||
boolean isOverDataLimit;
|
||||
hr = cost->get_OverDataLimit(&isOverDataLimit);
|
||||
if (!hr)
|
||||
{
|
||||
TRACE("isOverDataLimit = %d", isOverDataLimit);
|
||||
}
|
||||
|
||||
boolean isRoaming;
|
||||
hr = cost->get_Roaming(&isRoaming);
|
||||
if (!hr)
|
||||
{
|
||||
TRACE("isRoaming = %d", isRoaming);
|
||||
}
|
||||
|
||||
// Decide what NetworkCost we are here
|
||||
if (isOverDataLimit || isRoaming || isApproachingDataLimit)
|
||||
{
|
||||
result = NetworkCost_Roaming;
|
||||
}
|
||||
else
|
||||
if (type == NetworkCostType_Unrestricted)
|
||||
{
|
||||
result = NetworkCost_Unmetered;
|
||||
}
|
||||
else
|
||||
if (type == NetworkCostType_Fixed || type == NetworkCostType_Variable)
|
||||
{
|
||||
result = NetworkCost_Metered;
|
||||
}
|
||||
#endif
|
||||
// Obtain network type to the best of our knowledge using WinInet.dll
|
||||
// This logic may need further improvements to detect WiFi properly.
|
||||
#if 0 // This code is temporarily disabled because it does not bring enough
|
||||
// value to Office team.
|
||||
DWORD flags = 0;
|
||||
DWORD reserved = 0;
|
||||
if (::InternetGetConnectedState(&flags, reserved)) {
|
||||
switch (flags) {
|
||||
case INTERNET_CONNECTION_MODEM:
|
||||
case INTERNET_CONNECTION_LAN:
|
||||
m_currentNetworkType = NetworkType_Wired;
|
||||
break;
|
||||
default:
|
||||
m_currentNetworkType = NetworkType_Unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get adapter id for IConnectionProfile
|
||||
/// </summary>
|
||||
/// <param name="profile"></param>
|
||||
/// <returns></returns>
|
||||
std::string NetworkDetector::GetAdapterId(IConnectionProfile *profile)
|
||||
{
|
||||
if (!profile)
|
||||
{
|
||||
LOG_ERROR("Invalid profile pointer!");
|
||||
return ""; // Invalid interface ptr
|
||||
}
|
||||
|
||||
#if 0 /* FIXME: do we return none if connectivity level is none? */
|
||||
NetworkConnectivityLevel connectivityLevel;
|
||||
HRESULT hr = profile->GetNetworkConnectivityLevel(&connectivityLevel);
|
||||
if (connectivityLevel != NetworkConnectivityLevel_None)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
ComPtr<INetworkAdapter> adapter;
|
||||
HRESULT hr = profile->get_NetworkAdapter(&adapter);
|
||||
if (hr == E_INVALIDARG)
|
||||
{
|
||||
LOG_ERROR("No network interfaces - device is in airplane mode");
|
||||
return ""; // No interfaces - device is in airplane mode
|
||||
}
|
||||
|
||||
UINT32 type;
|
||||
hr = adapter->get_IanaInterfaceType(&type);
|
||||
if (type == 23)
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
GUID id;
|
||||
hr = adapter->get_NetworkAdapterId(&id);
|
||||
|
||||
return to_string(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COM thread interfaces supported by this class
|
||||
/// </summary>
|
||||
|
@ -190,7 +349,9 @@ namespace ARIASDK_NS_BEGIN
|
|||
ULONG ulNewRef = (ULONG)InterlockedDecrement((LONG *)&m_lRef);
|
||||
if (ulNewRef == 0)
|
||||
{
|
||||
delete this;
|
||||
// NetworkDetector is destroyed from FlushAndTeardown.
|
||||
// If customer forgets to call it, then it is destroyed from atexit(...)
|
||||
LOG_TRACE("NetworkDetector last instance released (this=%p)", this);
|
||||
}
|
||||
return ulNewRef;
|
||||
}
|
||||
|
@ -246,188 +407,200 @@ namespace ARIASDK_NS_BEGIN
|
|||
return RPC_S_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get activation factory and look-up network info statistics
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool NetworkDetector::GetNetworkInfoStats()
|
||||
{
|
||||
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &networkInfoStats);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
LOG_ERROR("Unable to get Windows::Networking::Connectivity::NetworkInformation");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkDetector::RegisterAndListen()
|
||||
{
|
||||
bool retutnValue = true;
|
||||
DWORD dwCookie_INetworkEvents = 0;
|
||||
DWORD dwCookie_INetworkConnectionEvents = 0;
|
||||
DWORD dwCookie_INetworkListManagerEvents = 0;
|
||||
ComPtr<IConnectionPoint> pc1, pc2, pc3;
|
||||
ComPtr<IConnectionPointContainer> pCpc;
|
||||
HRESULT hr;
|
||||
// ???
|
||||
HRESULT hr = pNlm->QueryInterface(IID_IUnknown, (void**)&pSink);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR("cannot query IID_IUnknown!!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
pSink = (INetworkEvents*)this;
|
||||
|
||||
hr = pNlm->QueryInterface(IID_IConnectionPointContainer, (void**)&pCpc);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkConnectionEvents, &pc1);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pc1->Advise(
|
||||
pSink.Get(),
|
||||
&dwCookie_INetworkConnectionEvents);
|
||||
LOG_INFO("listening to INetworkConnectionEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkEvents, &pc2);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pc2->Advise(
|
||||
pSink.Get(),
|
||||
&dwCookie_INetworkEvents);
|
||||
LOG_INFO("listening to INetworkEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkListManagerEvents, &pc3);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pc3->Advise(
|
||||
pSink.Get(),
|
||||
&dwCookie_INetworkListManagerEvents);
|
||||
LOG_INFO("listening to INetworkListManagerEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
isRunning = true;
|
||||
::SetEvent(m_syncEvent);
|
||||
BOOL bRet;
|
||||
MSG msg;
|
||||
m_listener_tid = GetCurrentThreadId();
|
||||
cv.notify_all();
|
||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
||||
{
|
||||
if (bRet == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (msg.message == WM_QUIT && msg.lParam == LparamMessageValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
isRunning = false;
|
||||
if (pc3 != NULL)
|
||||
{
|
||||
pc3->Unadvise(dwCookie_INetworkListManagerEvents);
|
||||
pc3.Reset();
|
||||
}
|
||||
if (pc2 != NULL)
|
||||
{
|
||||
pc2->Unadvise(dwCookie_INetworkEvents);
|
||||
pc2.Reset();
|
||||
}
|
||||
if (pc1 != NULL)
|
||||
{
|
||||
pc1->Unadvise(dwCookie_INetworkConnectionEvents);
|
||||
pc1.Reset();
|
||||
}
|
||||
|
||||
pCpc.Reset();
|
||||
}
|
||||
else
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR("Unable to QueryInterface IID_IConnectionPointContainer!");
|
||||
retutnValue = false;
|
||||
return false;
|
||||
}
|
||||
::SetEvent(m_syncEvent);
|
||||
return retutnValue;
|
||||
}
|
||||
|
||||
bool NetworkDetector::IsWindows8orLater()
|
||||
{
|
||||
static HMODULE hNtDll = ::GetModuleHandle(TEXT("ntdll.dll"));
|
||||
typedef HRESULT NTSTATUS;
|
||||
typedef NTSTATUS(__stdcall * RtlGetVersion_t)(PRTL_OSVERSIONINFOW);
|
||||
static RtlGetVersion_t pRtlGetVersion = hNtDll ? reinterpret_cast<RtlGetVersion_t>(::GetProcAddress(hNtDll, "RtlGetVersion")) : nullptr;
|
||||
|
||||
RTL_OSVERSIONINFOW rtlOsvi = { sizeof(rtlOsvi) };
|
||||
OSVERSIONINFOW osvi = { sizeof(osvi) };
|
||||
bool bIsWindows8orLater = false;
|
||||
if (pRtlGetVersion && SUCCEEDED(pRtlGetVersion(&rtlOsvi)))
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkConnectionEvents, &m_pc1);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bIsWindows8orLater = ((rtlOsvi.dwMajorVersion >= 6) && (rtlOsvi.dwMinorVersion >= 2)) || (rtlOsvi.dwMajorVersion > 6);
|
||||
hr = m_pc1->Advise(
|
||||
pSink.Get(),
|
||||
&m_dwCookie_INetworkConnectionEvents);
|
||||
LOG_INFO("listening to INetworkConnectionEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
LOG_INFO("Running on Windows %d.%d without network detector...", osvi.dwMajorVersion, osvi.dwMinorVersion);
|
||||
return bIsWindows8orLater;
|
||||
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkEvents, &m_pc2);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pc2->Advise(
|
||||
pSink.Get(),
|
||||
&m_dwCookie_INetworkEvents);
|
||||
LOG_INFO("listening to INetworkEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
hr = pCpc->FindConnectionPoint(IID_INetworkListManagerEvents, &m_pc3);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pc3->Advise(
|
||||
pSink.Get(),
|
||||
&m_dwCookie_INetworkListManagerEvents);
|
||||
LOG_INFO("listening to INetworkListManagerEvents... %s",
|
||||
(SUCCEEDED(hr)) ? "OK" : "FAILED");
|
||||
}
|
||||
|
||||
BOOL bRet;
|
||||
MSG msg;
|
||||
m_listener_tid = GetCurrentThreadId();
|
||||
PostThreadMessage(m_listener_tid, NETDETECTOR_START, 0, 0);
|
||||
cv.notify_all();
|
||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0)
|
||||
{
|
||||
switch (msg.message)
|
||||
{
|
||||
case NETDETECTOR_STOP:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register for COM events and block-wait in run
|
||||
///
|
||||
/// </summary>
|
||||
void NetworkDetector::Reset()
|
||||
{
|
||||
if (m_pc1 != nullptr)
|
||||
{
|
||||
m_pc1->Unadvise(m_dwCookie_INetworkConnectionEvents);
|
||||
m_pc1 = nullptr;
|
||||
}
|
||||
|
||||
if (m_pc2 != nullptr)
|
||||
{
|
||||
m_pc2->Unadvise(m_dwCookie_INetworkEvents);
|
||||
m_pc2 = nullptr;
|
||||
}
|
||||
|
||||
if (m_pc3 != nullptr)
|
||||
{
|
||||
m_pc3->Unadvise(m_dwCookie_INetworkListManagerEvents);
|
||||
m_pc3 = nullptr;
|
||||
}
|
||||
|
||||
m_connection_profile.Reset();
|
||||
pSink.Reset();
|
||||
pCpc.Reset();
|
||||
|
||||
networkInfoStats.Reset();
|
||||
if (pNlm != nullptr)
|
||||
{
|
||||
LOG_TRACE("release network list manager...");
|
||||
pNlm->Release();
|
||||
pNlm = nullptr;
|
||||
};
|
||||
|
||||
m_listener_tid = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register for COM events and block-wait in RegisterAndListen
|
||||
/// </summary>
|
||||
#pragma warning( push )
|
||||
#pragma warning(disable:28159)
|
||||
#pragma warning(disable:4996)
|
||||
#pragma warning(disable:6320)
|
||||
// We must use GetVersionEx to retain backwards compat with Win 7 SP1
|
||||
void NetworkDetector::run()
|
||||
{
|
||||
if (isRunning)
|
||||
// Check Windows version and if below Windows 8, then avoid running Network cost detection logic
|
||||
OSVERSIONINFO osvi;
|
||||
BOOL bIsWindows8orLater;
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osvi);
|
||||
bIsWindows8orLater = ((osvi.dwMajorVersion >= 6) && (osvi.dwMinorVersion >= 2)) || (osvi.dwMajorVersion > 6);
|
||||
// Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2)
|
||||
if (!bIsWindows8orLater)
|
||||
{
|
||||
LOG_WARN("Already running!"); //m_syncEvent should be signaled
|
||||
isRunning = false;
|
||||
LOG_INFO("Running on Windows %d.%d without network detector...", osvi.dwMajorVersion, osvi.dwMinorVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check Windows version and if below Windows 8, then avoid running Network cost detection logic
|
||||
if (IsWindows8orLater())
|
||||
__try
|
||||
{
|
||||
try
|
||||
HRESULT hr = CoInitialize(nullptr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
HRESULT hr = CoInitialize(nullptr);
|
||||
if (SUCCEEDED(hr))
|
||||
{// Current network info stats
|
||||
ComPtr<INetworkInformationStatics> networkInfoStats;
|
||||
LOG_ERROR("CoInitialize Failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &networkInfoStats);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
LOG_INFO("create network list manager...");
|
||||
hr = CoCreateInstance(
|
||||
CLSID_NetworkListManager,
|
||||
NULL,
|
||||
CLSCTX_ALL,
|
||||
IID_INetworkListManager,
|
||||
(void**)&pNlm);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR("Unable to CoCreateInstance for CLSID_NetworkListManager!");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentNetworkCost();
|
||||
LOG_TRACE("start listening to events...");
|
||||
RegisterAndListen(); // we block here to process COM events
|
||||
}
|
||||
networkInfoStats.Detach();
|
||||
if (pNlm != NULL)
|
||||
{
|
||||
LOG_TRACE("release network list manager...");
|
||||
pNlm->Release();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Unable to get Windows::Networking::Connectivity::NetworkInformation");
|
||||
}
|
||||
|
||||
networkInfoStats.Reset();
|
||||
CoUninitialize();
|
||||
isCoInitialized = true;
|
||||
if (GetNetworkInfoStats())
|
||||
{
|
||||
LOG_INFO("create network list manager...");
|
||||
hr = CoCreateInstance(
|
||||
CLSID_NetworkListManager,
|
||||
nullptr,
|
||||
CLSCTX_ALL,
|
||||
IID_INetworkListManager,
|
||||
(void**)&pNlm);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOG_ERROR("Unable to CoCreateInstance for CLSID_NetworkListManager!");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("CoInitialize Failed.");
|
||||
GetCurrentNetworkCost();
|
||||
LOG_TRACE("start listening to events...");
|
||||
RegisterAndListen(); // we block here to process COM events
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_ERROR("Handled exception in network cost detection (Windows 7?)");
|
||||
isRunning = false;
|
||||
// Once we are done OR cannot init NLM, we must perform the clean-up
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
isRunning = false;
|
||||
LOG_ERROR("Handled exception in network cost detection (Windows 7?)");
|
||||
}
|
||||
::SetEvent(m_syncEvent); // setting event, so it can be retried after fail
|
||||
|
||||
if (isCoInitialized)
|
||||
{
|
||||
CoUninitialize();
|
||||
isCoInitialized = false;
|
||||
}
|
||||
|
||||
}
|
||||
#pragma warning( pop )
|
||||
|
||||
/// <summary>
|
||||
/// Start network monitoring thread
|
||||
|
@ -435,20 +608,46 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// <returns>true - if start is successful, false - otherwise</returns>
|
||||
bool NetworkDetector::Start()
|
||||
{
|
||||
if (!isRunning)
|
||||
{
|
||||
if (::WaitForSingleObject(m_syncEvent, 0) == WAIT_OBJECT_0)
|
||||
std::lock_guard<std::mutex> lk(m_lock);
|
||||
if (isRunning)
|
||||
{
|
||||
if (!isRunning)
|
||||
{ // Start a new thread. Notify waiters on exit.
|
||||
netDetectThread = std::thread([this]() {
|
||||
run();
|
||||
cv.notify_all();
|
||||
});
|
||||
netDetectThread.detach();
|
||||
WaitForSingleObject(m_syncEvent, 1000);
|
||||
}
|
||||
LOG_TRACE("NetworkDetector tid=%p is already running", m_listener_tid);
|
||||
return true;
|
||||
}
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
// Start a new thread. Notify waiters on exit.
|
||||
netDetectThread = std::thread([this]()
|
||||
{
|
||||
run();
|
||||
LOG_TRACE("NetworkDetector tid=%p is shutting down..", m_listener_tid);
|
||||
isRunning = false;
|
||||
});
|
||||
|
||||
if (netDetectThread.joinable())
|
||||
{
|
||||
LOG_TRACE("NetworkDetector is starting...");
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_lock);
|
||||
// Wait for up to NETDETECTOR_COM_SETTLE_MS ms until:
|
||||
// - COM object is ready; OR
|
||||
// - COM object can't be started (pre-Win 8 scenario)
|
||||
unsigned retry = 1;
|
||||
while (!cv.wait_for(lock, std::chrono::milliseconds(NETDETECTOR_COM_SETTLE_MS),
|
||||
[this] {return (m_listener_tid != 0); }) && (isRunning))
|
||||
{
|
||||
LOG_TRACE("NetworkDetector starting up... [%u]", retry);
|
||||
retry++;
|
||||
}
|
||||
LOG_TRACE("NetworkDetector tid=%p running=%u", m_listener_tid, isRunning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN("NetworkDetector thread can't be started!");
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
return isRunning;
|
||||
|
@ -459,11 +658,19 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// </summary>
|
||||
void NetworkDetector::Stop()
|
||||
{
|
||||
PostThreadMessage(m_listener_tid, WM_QUIT, 0, LparamMessageValue);
|
||||
if (isRunning && netDetectThread.joinable())
|
||||
if ((isRunning) || (netDetectThread.joinable()))
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_lock);
|
||||
cv.wait_for(lock, std::chrono::milliseconds(1000));
|
||||
PostThreadMessage(m_listener_tid, NETDETECTOR_STOP, 0, NULL);
|
||||
try {
|
||||
if (netDetectThread.joinable())
|
||||
netDetectThread.join();
|
||||
LOG_TRACE("NetworkDetector tid=%p has stopped.", m_listener_tid);
|
||||
}
|
||||
catch (std::system_error &ex)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ex);
|
||||
LOG_WARN("NetworkDetector tid=%p is already stopped.", m_listener_tid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -473,20 +680,121 @@ namespace ARIASDK_NS_BEGIN
|
|||
/// <returns></returns>
|
||||
NetworkDetector::~NetworkDetector()
|
||||
{
|
||||
LOG_TRACE("Shutting down NetworkDetector...");
|
||||
LOG_TRACE("NetworkDetector destroyed.");
|
||||
LOG_TRACE("NetworkDetector dtor tid=%p", m_listener_tid);
|
||||
Stop();
|
||||
LOG_TRACE("NetworkDetector done tid=%p", m_listener_tid);
|
||||
}
|
||||
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& NetworkDetector::GetNetworksConnectivity() const
|
||||
/// <summary>
|
||||
/// Get network cost name
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
const char* NetworkDetector::GetNetworkCostName(NetworkCostType type)
|
||||
{
|
||||
char *typeName;
|
||||
switch (type) {
|
||||
case NetworkCostType_Unrestricted:
|
||||
typeName = "Unrestricted";
|
||||
break;
|
||||
case NetworkCostType_Fixed:
|
||||
typeName = "Fixed";
|
||||
break;
|
||||
case NetworkCostType_Variable:
|
||||
typeName = "Variable";
|
||||
case NetworkCostType_Unknown:
|
||||
default:
|
||||
typeName = "Unknown";
|
||||
break;
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& NetworkDetector::GetNetworksConnectivity()
|
||||
{
|
||||
return m_networks_connectivity;
|
||||
}
|
||||
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& NetworkDetector::GetConnectionsConnectivity() const
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& NetworkDetector::GetConnectionsConnectivity()
|
||||
{
|
||||
return m_connections_connectivity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtain various details about network stack
|
||||
/// </summary>
|
||||
void NetworkDetector::GetNetworkDetails()
|
||||
{
|
||||
LOG_TRACE("Getting network details...");
|
||||
ComPtr<IVectorView<HostName *>> hostNames;
|
||||
HRESULT hr = networkInfoStats->GetHostNames(&hostNames);
|
||||
if (!hostNames)
|
||||
return;
|
||||
|
||||
m_hostnames.clear();
|
||||
unsigned int hostNameCount;
|
||||
hr = hostNames->get_Size(&hostNameCount);
|
||||
for (unsigned i = 0; i < hostNameCount; ++i) {
|
||||
MATW::HostNameInfo hostInfo;
|
||||
ComPtr<IHostName> hostName;
|
||||
hr = hostNames->GetAt(i, &hostName);
|
||||
|
||||
HString rawName;
|
||||
hostName->get_RawName(rawName.GetAddressOf());
|
||||
LOG_TRACE("RawName: %s", to_string(&rawName).c_str());
|
||||
|
||||
HostNameType type;
|
||||
hr = hostName->get_Type(&type);
|
||||
LOG_TRACE("HostNameType: %d", type);
|
||||
|
||||
if (type == HostNameType_DomainName)
|
||||
continue;
|
||||
|
||||
ComPtr<IIPInformation> ipInformation;
|
||||
hr = hostName->get_IPInformation(&ipInformation);
|
||||
|
||||
ComPtr<INetworkAdapter> currentAdapter;
|
||||
hr = ipInformation->get_NetworkAdapter(¤tAdapter);
|
||||
hr = currentAdapter->get_NetworkAdapterId(&hostInfo.adapterId);
|
||||
LOG_TRACE("CurrentAdapterId: %s", to_string(hostInfo.adapterId).c_str());
|
||||
|
||||
ComPtr<IReference<unsigned char>> prefixLengthReference;
|
||||
hr = ipInformation->get_PrefixLength(&prefixLengthReference);
|
||||
hr = prefixLengthReference->get_Value(&hostInfo.prefixLength);
|
||||
LOG_TRACE("PrefixLength: %d", hostInfo.prefixLength);
|
||||
|
||||
// invalid prefixes
|
||||
if ((type == HostNameType_Ipv4 && hostInfo.prefixLength > 32)
|
||||
|| (type == HostNameType_Ipv6 && hostInfo.prefixLength > 128))
|
||||
continue;
|
||||
|
||||
HString name;
|
||||
hr = hostName->get_CanonicalName(name.GetAddressOf());
|
||||
hostInfo.address = to_string(&name);
|
||||
LOG_TRACE("CanonicalName: %s", hostInfo.address.c_str());
|
||||
|
||||
m_hostnames.push_back(hostInfo);
|
||||
}
|
||||
|
||||
// hr = networkInfoStats->GetInternetConnectionProfile(&m_connection_profile);
|
||||
// auto profile0 = m_connection_profile.Get();
|
||||
|
||||
ComPtr<IVectorView<ConnectionProfile *>> m_connection_profiles;
|
||||
hr = networkInfoStats->GetConnectionProfiles(&m_connection_profiles);
|
||||
|
||||
unsigned int size;
|
||||
hr = m_connection_profiles->get_Size(&size);
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
ComPtr<IConnectionProfile> profile;
|
||||
hr = m_connection_profiles->GetAt(i, &profile);
|
||||
auto prof = profile.Get();
|
||||
HString name;
|
||||
hr = prof->get_ProfileName(name.GetAddressOf());
|
||||
LOG_TRACE("Profile[%d]: name = %s", i, to_string(&name).c_str());
|
||||
LOG_TRACE("Profile[%d]: guid = %s", i, GetAdapterId(prof).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // ::Windows
|
||||
|
||||
} ARIASDK_NS_END
|
||||
|
|
|
@ -41,9 +41,12 @@
|
|||
#include <map>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
#include "Enums.hpp"
|
||||
|
||||
// #include <Wininet.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
|
@ -55,131 +58,214 @@ using namespace std;
|
|||
|
||||
namespace ARIASDK_NS_BEGIN
|
||||
{
|
||||
namespace Windows {
|
||||
namespace Windows {
|
||||
|
||||
/// <summary>
|
||||
/// Host name information structure
|
||||
/// </summary>
|
||||
struct HostNameInfo {
|
||||
GUID adapterId;
|
||||
unsigned char prefixLength;
|
||||
std::string address;
|
||||
};
|
||||
/// <summary>
|
||||
/// Host name information structure
|
||||
/// </summary>
|
||||
struct HostNameInfo {
|
||||
GUID adapterId;
|
||||
unsigned char prefixLength;
|
||||
std::string address;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Convert HString to std::string
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
std::string to_string(const HString *name);
|
||||
/// <summary>
|
||||
/// Convert HString to std::string
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
std::string to_string(HString *name);
|
||||
|
||||
/// <summary>
|
||||
/// Convert GUID to std::string
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
std::string to_string(GUID guid);
|
||||
/// <summary>
|
||||
/// Convert GUID to std::string
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
std::string to_string(GUID guid);
|
||||
|
||||
class NetworkDetector : public INetworkEvents, INetworkConnectionEvents, INetworkListManagerEvents {
|
||||
class NetworkDetector: public INetworkEvents, INetworkConnectionEvents, INetworkListManagerEvents {
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Obtain network cost RO. This function does not handle potential exceptions and must only be called from GetNetworkCost()
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NetworkCost _GetCurrentNetworkCost();
|
||||
private:
|
||||
|
||||
/// <summary>
|
||||
/// runs the main message loop
|
||||
/// </summary>
|
||||
void run();
|
||||
|
||||
/// <summary>
|
||||
/// Register and listen to network state notifications
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool RegisterAndListen();
|
||||
|
||||
bool IsWindows8orLater();
|
||||
|
||||
std::vector<std::string> m_networks;
|
||||
std::map<std::string, NLM_CONNECTIVITY> m_networks_connectivity;
|
||||
std::map<std::string, NLM_CONNECTIVITY> m_connections_connectivity;
|
||||
std::vector<HostNameInfo> m_hostnames;
|
||||
int m_currentNetworkCost;
|
||||
ULONG m_lRef;
|
||||
DWORD m_listener_tid;
|
||||
NLM_CONNECTIVITY m_connectivity;
|
||||
/// COM INetworkListManager
|
||||
INetworkListManager* pNlm;
|
||||
std::mutex m_lock;
|
||||
std::condition_variable cv;
|
||||
bool isRunning;
|
||||
std::thread netDetectThread;
|
||||
ComPtr<IUnknown> pSink;
|
||||
HANDLE m_syncEvent;
|
||||
/// <summary>
|
||||
/// Current network info stats
|
||||
/// </summary>
|
||||
ComPtr<INetworkInformationStatics> networkInfoStats;
|
||||
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Current connection profile
|
||||
/// </summary>
|
||||
ComPtr<IConnectionProfile> m_connection_profile;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
bool isUp() const { return isRunning; };
|
||||
/// <summary>
|
||||
/// COM INetworkListManager
|
||||
/// </summary>
|
||||
INetworkListManager* pNlm;
|
||||
|
||||
/// <summary>
|
||||
/// Createa network status listener
|
||||
/// </summary>
|
||||
NetworkDetector() :
|
||||
pNlm(NULL),
|
||||
isRunning(false),
|
||||
m_currentNetworkCost(0),
|
||||
m_lRef(0),
|
||||
m_syncEvent(::CreateEvent(NULL, FALSE, TRUE, NULL))
|
||||
{}
|
||||
/// <summary>
|
||||
/// Obtain network cost RO. This function does not handle potential exceptions and must only be called from GetNetworkCost()
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NetworkCost _GetCurrentNetworkCost();
|
||||
|
||||
virtual ~NetworkDetector();
|
||||
bool Start();
|
||||
void Stop();
|
||||
/// <summary>
|
||||
/// Get instance of network info stats
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool GetNetworkInfoStats();
|
||||
|
||||
/// <summary>
|
||||
/// Get current network cost
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int NetworkDetector::GetCurrentNetworkCost();
|
||||
std::mutex m_lock;
|
||||
std::condition_variable cv;
|
||||
bool isRunning;
|
||||
bool isCoInitialized;
|
||||
std::thread netDetectThread;
|
||||
|
||||
/// <summary>
|
||||
/// Get last cached network cost
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NetworkCost const& NetworkDetector::GetNetworkCost() const;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void run();
|
||||
|
||||
ComPtr<IUnknown> pSink;
|
||||
ComPtr<IConnectionPointContainer> pCpc;
|
||||
ComPtr<IConnectionPoint> m_pc1, m_pc2, m_pc3;
|
||||
|
||||
int NetworkDetector::GetConnectivity() const;
|
||||
ULONG m_lRef;
|
||||
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& GetNetworksConnectivity() const;
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& GetConnectionsConnectivity() const;
|
||||
DWORD m_dwCookie_INetworkEvents;
|
||||
DWORD m_dwCookie_INetworkConnectionEvents;
|
||||
DWORD m_dwCookie_INetworkListManagerEvents;
|
||||
DWORD m_listener_tid;
|
||||
|
||||
public:
|
||||
NLM_CONNECTIVITY m_connectivity;
|
||||
|
||||
// Inherited via INetworkListManagerEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) override;
|
||||
/// <summary>
|
||||
/// Register and listen to network state notifications
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool RegisterAndListen();
|
||||
|
||||
// Inherited via INetworkEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) override;
|
||||
/// <summary>
|
||||
/// Reset network state listener to uninitialized state
|
||||
/// </summary>
|
||||
void Reset();
|
||||
|
||||
// Inherited via INetworkConnectionEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectionConnectivityChanged(GUID connectionId, NLM_CONNECTIVITY newConnectivity) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectionPropertyChanged(GUID connectionId, NLM_CONNECTION_PROPERTY_CHANGE flags) override;
|
||||
};
|
||||
std::vector<std::string> m_networks;
|
||||
std::map<std::string, NLM_CONNECTIVITY> m_networks_connectivity;
|
||||
std::map<std::string, NLM_CONNECTIVITY> m_connections_connectivity;
|
||||
std::vector<HostNameInfo> m_hostnames;
|
||||
int m_currentNetworkCost;
|
||||
std::atomic<NetworkType> m_currentNetworkType;
|
||||
|
||||
}
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
bool isUp() { return isRunning; };
|
||||
|
||||
/// <summary>
|
||||
/// Createa network status listener
|
||||
/// </summary>
|
||||
NetworkDetector() :
|
||||
pNlm(nullptr),
|
||||
networkInfoStats(nullptr),
|
||||
m_connection_profile(nullptr),
|
||||
pSink(nullptr),
|
||||
pCpc(nullptr),
|
||||
m_pc1(nullptr),
|
||||
m_pc2(nullptr),
|
||||
m_pc3(nullptr),
|
||||
isRunning(false),
|
||||
isCoInitialized(false),
|
||||
m_dwCookie_INetworkEvents(0),
|
||||
m_dwCookie_INetworkConnectionEvents(0),
|
||||
m_dwCookie_INetworkListManagerEvents(0),
|
||||
m_currentNetworkCost(0),
|
||||
m_currentNetworkType(NetworkType_Unknown),
|
||||
m_listener_tid(0)
|
||||
{};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool Start();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
virtual ~NetworkDetector();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
const char *GetNetworkCostName(NetworkCostType type);
|
||||
|
||||
/// <summary>
|
||||
/// Get current network cost
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int NetworkDetector::GetCurrentNetworkCost();
|
||||
|
||||
/// <summary>
|
||||
/// Get last cached network cost
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NetworkCost const& NetworkDetector::GetNetworkCost();
|
||||
|
||||
/// <summary>
|
||||
/// Get last cached network type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NetworkType NetworkDetector::GetNetworkType();
|
||||
|
||||
/// <summary>
|
||||
/// Get adapter ID for connection profile
|
||||
/// </summary>
|
||||
/// <param name="profile"></param>
|
||||
/// <returns></returns>
|
||||
std::string GetAdapterId(IConnectionProfile *profile);
|
||||
|
||||
int NetworkDetector::GetConnectivity();
|
||||
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& GetNetworksConnectivity();
|
||||
const std::map<std::string, NLM_CONNECTIVITY>& GetConnectionsConnectivity();
|
||||
|
||||
void GetNetworkDetails();
|
||||
|
||||
IConnectionProfile* GetCurrentConnectionProfile()
|
||||
{
|
||||
return m_connection_profile.Get();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Inherited via INetworkListManagerEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject) override;
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) override;
|
||||
|
||||
// Inherited via INetworkEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) override;
|
||||
|
||||
// Inherited via INetworkConnectionEvents
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectionConnectivityChanged(GUID connectionId, NLM_CONNECTIVITY newConnectivity) override;
|
||||
virtual HRESULT STDMETHODCALLTYPE NetworkConnectionPropertyChanged(GUID connectionId, NLM_CONNECTION_PROPERTY_CHANGE flags) override;
|
||||
};
|
||||
|
||||
}
|
||||
} ARIASDK_NS_END
|
||||
|
||||
namespace MATW = MAT::Windows;
|
||||
|
|
Загрузка…
Ссылка в новой задаче