// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved #include "stdafx.h" #pragma region COM helpers using unique_connectionpoint_token = wil::unique_com_token; unique_connectionpoint_token FindConnectionPointAndAdvise(REFIID itf, IUnknown* source, IUnknown* sink) { wil::com_ptr container = wil::com_query(source); wil::com_ptr connectionPoint; THROW_IF_FAILED(container->FindConnectionPoint(itf, connectionPoint.put())); unique_connectionpoint_token token{ connectionPoint.get() }; THROW_IF_FAILED(connectionPoint->Advise(sink, token.put())); return token; } // typename T is the connection point interface we are connecting to. template unique_connectionpoint_token FindConnectionPointAndAdvise(IUnknown* source, IUnknown* sink) { return FindConnectionPointAndAdvise(__uuidof(T), source, sink); } #pragma endregion #pragma region QueryCurrentNetworkConnectivitySample void QueryCurrentNetworkConnectivitySample(bool optedIn) { std::wcout << L"Querying current network connectivity." << std::endl; if (optedIn) { std::wcout << L"User has opted into possible network usage charges." << std::endl; } else { std::wcout << L"User has not opted into possible network usage charges." << std::endl; } const wil::com_ptr networkListManager = wil::CoCreateInstance(); // Checks machine level connectivity via ipv4 or ipv6 or both. NLM_CONNECTIVITY connectivity{ NLM_CONNECTIVITY_DISCONNECTED }; THROW_IF_FAILED(networkListManager->GetConnectivity(&connectivity)); Utility::EvaluateAndReportConnectivity(optedIn, connectivity, networkListManager.get()); } #pragma endregion #pragma region QueryCurrentNetworkCostSample void QueryCurrentNetworkCostSample() { std::wcout << "Querying current network cost information." << std::endl; // Use INetworkCostManager to query machine-wide cost associated with // a network connection used for machine-wide Internet connectivity. const wil::com_ptr networkCostManager = wil::CoCreateInstance(); DWORD cost{ 0 }; THROW_IF_FAILED(networkCostManager->GetCost(&cost, nullptr)); const auto connectionCost = static_cast(cost); Utility::EvaluateAndReportConnectionCost(connectionCost); } #pragma endregion #pragma region ListenToNetworkConnectivityChangesSample class NetworkConnectivityListener final : public Microsoft::WRL::RuntimeClass, INetworkListManagerEvents> { public: NetworkConnectivityListener(bool optedIn, INetworkListManager* networkListManager) : m_optedIn(optedIn), m_networkListManager(networkListManager) {} NetworkConnectivityListener(const NetworkConnectivityListener&) = delete; NetworkConnectivityListener& operator=(const NetworkConnectivityListener&) = delete; IFACEMETHODIMP ConnectivityChanged(NLM_CONNECTIVITY connectivity) noexcept override try { std::wcout << L"INetworkListManagerEvents::ConnectivityChanged" << std::endl; Utility::EvaluateAndReportConnectivity(m_optedIn, connectivity, m_networkListManager.get()); return S_OK; } CATCH_RETURN(); private: wil::com_ptr m_networkListManager; bool m_optedIn; }; void ListenToNetworkConnectivityChangesSample(bool optedIn) { std::wcout << "Listening to network connectivity changes." << std::endl; if (optedIn) { std::wcout << L"User has opted into possible network usage charges." << std::endl; } else { std::wcout << L"User has not opted into possible network usage charges." << std::endl; } const wil::com_ptr networkListManager = wil::CoCreateInstance(); unique_connectionpoint_token token = FindConnectionPointAndAdvise( networkListManager.get(), Microsoft::WRL::Make(optedIn, networkListManager.get()).Get()); std::wcout << "Press Enter to stop." << std::endl; static_cast(getchar()); } #pragma endregion #pragma region ListenToNetworkCostChangesSample class NetworkCostListener final : public Microsoft::WRL::RuntimeClass, INetworkCostManagerEvents> { public: NetworkCostListener(INetworkCostManager* networkCostManager) : m_networkCostManager(networkCostManager) {} NetworkCostListener(const NetworkCostListener&) = delete; NetworkCostListener& operator=(const NetworkCostListener&) = delete; IFACEMETHODIMP CostChanged(DWORD cost, __RPC__in_opt NLM_SOCKADDR* /*pDestAddr*/) noexcept override try { const auto connectionCost = static_cast(cost); std::wcout << L"INetworkCostManagerEvents::CostChanged" << std::endl; Utility::EvaluateAndReportConnectionCost(connectionCost); return S_OK; } CATCH_RETURN(); IFACEMETHODIMP DataPlanStatusChanged(__RPC__in_opt NLM_SOCKADDR* /*pDestAddr*/) noexcept override { // This event is not used by the sample. return S_OK; } private: wil::com_ptr m_networkCostManager; }; void ListenToNetworkCostChangesSample() { std::wcout << "Listening to network cost changes." << std::endl; const wil::com_ptr networkCostManager = wil::CoCreateInstance(); unique_connectionpoint_token token = FindConnectionPointAndAdvise( networkCostManager.get(), Microsoft::WRL::Make(networkCostManager.get()).Get()); std::wcout << "Press Enter to stop." << std::endl; static_cast(getchar()); } #pragma endregion int __cdecl wmain(int argc, wchar_t** argv) try { auto coinit = wil::CoInitializeEx_failfast(COINIT_MULTITHREADED); int scenario = argc == 2 ? _wtoi(argv[1]) : 0; switch (scenario) { case 1: case 2: QueryCurrentNetworkConnectivitySample(scenario == 2); break; case 3: QueryCurrentNetworkCostSample(); break; case 4: case 5: ListenToNetworkConnectivityChangesSample(scenario == 5); break; case 6: ListenToNetworkCostChangesSample(); break; default: std::wcout << "NetworkListManager.exe sample demonstrates how to use network list manager APIs." << std::endl << " [parameter]" << std::endl << " 1: Query current network connectivity: User has not opted into possible network usage charges." << std::endl << " 2: Query current network connectivity: User has opted into possible network usage charges." << std::endl << " 3: Query current network cost information." << std::endl << " 4: Listen to network connectivity changes: User has not opted into possible network usage charges." << std::endl << " 5: Listen to network connectivity changes: User has opted into possible network usage charges." << std::endl << " 6: Listen to network cost changes." << std::endl; break; } return 0; } CATCH_RETURN();