#include <winsock2.h> #include <Iphlpapi.h> #pragma comment(lib, "IPHLPAPI.lib") #include <windows.h> #include <Wininet.h> #pragma comment(lib, "Wininet.lib") #include <stdio.h> #include <atlbase.h> #pragma comment(lib, "wsock32.lib") #pragma comment(lib, "ws2_32.lib") #include <assert.h> #include <memory> #include<Netlistmgr.h> typedef enum { UNKNOWN, YES, NO }INTERNET_STATE; void print_connection_type(INTERNET_STATE state) { switch(state) { case YES: printf("internet connection exists.\n"); break; case NO: printf("No internet connection.\n"); break; case UNKNOWN: printf("unknown connection.\n"); break; } } BOOL IsWindowsXPorLater() { OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); return (( (osvi.dwMajorVersion > 5) || ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ))); } void wait_for_connection_type_change_with_winsock() { printf("\n"__FUNCTION__"\n"); WSAQUERYSET querySet = {0}; querySet.dwSize = sizeof(WSAQUERYSET); querySet.dwNameSpace = NS_NLA; HANDLE LookupHandle = NULL; WSALookupServiceBegin(&querySet, LUP_RETURN_ALL, &LookupHandle); DWORD BytesReturned = 0; WSANSPIoctl(LookupHandle, SIO_NSP_NOTIFY_CHANGE, NULL, 0, NULL, 0, &BytesReturned, NULL); WSALookupServiceEnd(LookupHandle); } INTERNET_STATE connection_type_with_winsock() { typedef enum _NLA_BLOB_DATA_TYPE { NLA_RAW_DATA = 0, NLA_INTERFACE = 1, NLA_802_1X_LOCATION = 2, NLA_CONNECTIVITY = 3, NLA_ICS = 4, }NLA_BLOB_DATA_TYPE; typedef enum _NLA_CONNECTIVITY_TYPE { NLA_NETWORK_AD_HOC = 0, NLA_NETWORK_MANAGED = 1, NLA_NETWORK_UNMANAGED = 2, NLA_NETWORK_UNKNOWN = 3, }NLA_CONNECTIVITY_TYPE; typedef enum _NLA_INTERNET { NLA_INTERNET_UNKNOWN = 0, NLA_INTERNET_NO = 1, NLA_INTERNET_YES = 2, }NLA_INTERNET; typedef struct _NLA_BLOB { struct { NLA_BLOB_DATA_TYPE type; DWORD dwSize; DWORD nextOffset; } header; union { // header.type -> NLA_RAW_DATA CHAR rawData[1]; // header.type -> NLA_INTERFACE struct { DWORD dwType; DWORD dwSpeed; CHAR adapterName[1]; } interfaceData; // header.type -> NLA_802_1X_LOCATION struct { CHAR information[1]; } locationData; // header.type -> NLA_CONNECTIVITY struct { NLA_CONNECTIVITY_TYPE type; NLA_INTERNET internet; } connectivity; // header.type -> NLA_ICS struct { struct { DWORD speed; DWORD type; DWORD state; WCHAR machineName[256]; WCHAR sharedAdapterName[256]; } remote; } ICS; } data; }NLA_BLOB; printf("\n"__FUNCTION__":"); HANDLE ws_handle; WSAData data = {0}; WSAQUERYSET query_set = {0}; query_set.dwSize = sizeof(WSAQUERYSET); query_set.dwNameSpace = NS_NLA; if (0 != WSALookupServiceBegin(&query_set, LUP_RETURN_BLOB,&ws_handle)) { return UNKNOWN; } DWORD length = 0; int result = WSALookupServiceNext(ws_handle,LUP_RETURN_BLOB, &length, NULL); if (result != 0) { result = WSAGetLastError(); if (result == WSAEFAULT) { return UNKNOWN; } else if (result == WSA_E_NO_MORE || result == WSAENOMORE) { return NO; } else { return UNKNOWN; } } std::auto_ptr<char> result_buffer(new char[length]); memset(result_buffer.get(), 0, length); reinterpret_cast<WSAQUERYSET*>(result_buffer.get())->dwSize = sizeof(WSAQUERYSET); do { result = WSALookupServiceNext(ws_handle,LUP_RETURN_BLOB, &length, reinterpret_cast<WSAQUERYSET*>(result_buffer.get())); if (result == 0) { WSAQUERYSET* query_set = reinterpret_cast<WSAQUERYSET*>(result_buffer.get()); BLOB* blob = reinterpret_cast<BLOB*>(query_set->lpBlob); NLA_BLOB* nla_blob = reinterpret_cast<NLA_BLOB*>(blob->pBlobData); if (nla_blob->header.type == NLA_CONNECTIVITY) { NLA_CONNECTIVITY_TYPE t = nla_blob->data.connectivity.type; NLA_INTERNET i = nla_blob->data.connectivity.internet; if (i == NLA_INTERNET_YES) { return YES; } } else { continue; } } else { result = WSAGetLastError(); if (result == WSAEFAULT) { return UNKNOWN; } else if (result == WSA_E_NO_MORE || result == WSAENOMORE) { // There was nothing to iterate over! } else { return UNKNOWN; } } }while(result == 0); result = WSALookupServiceEnd(ws_handle); return NO; } INTERNET_STATE connection_type_with_iphlp() { printf("\n"__FUNCTION__":"); // Assume that we're online until proven otherwise. DWORD size = 0; if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW) return UNKNOWN; IP_ADAPTER_ADDRESSES* addresses = (IP_ADAPTER_ADDRESSES*)malloc(size); if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) { // We couldn't determine whether we're online or not, so assume that we are. return UNKNOWN; } PIP_ADAPTER_ADDRESSES pCurrAddresses = addresses; for (;pCurrAddresses != NULL;pCurrAddresses = pCurrAddresses->Next) { if (pCurrAddresses->IfType == MIB_IF_TYPE_LOOPBACK) continue; if (pCurrAddresses->OperStatus != IfOperStatusUp) continue; // We found an interface that was up. return YES; } // We didn't find any valid interfaces, so we must be offline. return NO; } INTERNET_STATE connection_type_with_wininet() { printf("\n"__FUNCTION__":"); DWORD state = 0; HMODULE winnet = LoadLibraryA("wininet.dll"); if (winnet == NULL) { printf("Error:%d\n", GetLastError()); return UNKNOWN; } typedef BOOL (WINAPI *NET_CONNECTED_STATE)(LPDWORD lpdwFlags, DWORD dwReserved); NET_CONNECTED_STATE net_connected_state = (NET_CONNECTED_STATE)GetProcAddress(winnet, "InternetGetConnectedState"); if (net_connected_state == NULL) { printf("Error:%d\n", GetLastError()); return UNKNOWN; } return net_connected_state(&state, 0) ? YES : NO; } INTERNET_STATE connection_type_with_nlm() { printf("\n"__FUNCTION__":"); if (!IsWindowsXPorLater()) { return UNKNOWN; } IUnknown* unknown = NULL; HRESULT r = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void **)&unknown); if (SUCCEEDED(r)) { INetworkListManager* nlm = NULL; r = unknown->QueryInterface(IID_INetworkListManager, (void **)&nlm); if (SUCCEEDED(r)) { VARIANT_BOOL t = VARIANT_FALSE; r = nlm->get_IsConnectedToInternet(&t); if (SUCCEEDED(r)) { return t == VARIANT_TRUE ? YES : NO; } } } return NO; } void connection_type_with_nlm_event() { class CNetworkListManagerEvent : public INetworkListManagerEvents { public: CNetworkListManagerEvent() { } ~CNetworkListManagerEvent() { } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { HRESULT Result = S_OK; if (IsEqualIID(riid, IID_IUnknown)) { *ppvObject = (IUnknown *)this; } else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) { *ppvObject = (INetworkListManagerEvents *)this; } else { Result = E_NOINTERFACE; } return Result; } ULONG STDMETHODCALLTYPE AddRef() { return 1; } ULONG STDMETHODCALLTYPE Release() { return 1; } virtual HRESULT STDMETHODCALLTYPE ConnectivityChanged( /* [in] */ NLM_CONNECTIVITY newConnectivity) { printf("\n"__FUNCTION__":"); if (NLM_CONNECTIVITY_IPV4_INTERNET & newConnectivity || NLM_CONNECTIVITY_IPV6_INTERNET & newConnectivity) { print_connection_type(YES); } else { print_connection_type(NO); } return S_OK; } }; CComPtr<IUnknown> unknown = NULL; HRESULT result = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void **)&unknown); if (FAILED(result)) { return; } CComPtr<INetworkListManager> nlm = NULL; result = unknown->QueryInterface(IID_INetworkListManager, (void **)&nlm); if (FAILED(result)) { return; } CComPtr<IConnectionPointContainer> container = NULL; result = nlm->QueryInterface(IID_IConnectionPointContainer, (void **)&container); if (FAILED(result)) { return; } CComPtr<IConnectionPoint> connect_point = NULL; result = container->FindConnectionPoint(IID_INetworkListManagerEvents, &connect_point); if (FAILED(result)) { return; } DWORD Cookie = NULL; std::auto_ptr<CNetworkListManagerEvent> e(new CNetworkListManagerEvent); result = connect_point->Advise(reinterpret_cast<IUnknown *>(e.get()), &Cookie); if (FAILED(result)) { return; } while(1) { Sleep(1); } connect_point->Unadvise(Cookie); return; } DWORD WINAPI loop(void* data) { INTERNET_STATE t = UNKNOWN;while(1) { print_connection_type(connection_type_with_wininet()); print_connection_type(connection_type_with_iphlp()); print_connection_type(connection_type_with_winsock()); print_connection_type(connection_type_with_nlm()); system("pause"); } return 0; } DWORD WINAPI notify_with_nlm(void* data) { while(1) { connection_type_with_nlm_event(); } } DWORD WINAPI notify_with_winsock(void* data) { while(1) { wait_for_connection_type_change_with_winsock(); print_connection_type(connection_type_with_nlm()); } } int main(int argv, char** argc) { CoInitializeEx(NULL, COINIT_MULTITHREADED); WSAData data = {0}; WSAStartup(MAKEWORD(2, 0), &data); DWORD id = 0; CloseHandle(CreateThread(NULL,0,notify_with_nlm,NULL, 0, &id)); CloseHandle(CreateThread(NULL,0,notify_with_winsock,NULL, 0, &id)); CloseHandle(CreateThread(NULL,0,loop,NULL, 0, &id)); MSG msg; while(GetMessage(&msg,NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } WSACleanup(); CoUninitialize(); return 0; }