📄 netchck.cpp
字号:
HX_ASSERT(FALSE);return HXR_OK;}/************************************************************************ * Method: * IHXTCPResponse::Closed * Purpose: * This method is called to inform you that the TCP channel has * been closed by the peer or closed due to error. */STDMETHODIMP CHXNetCheck::Closed(HX_RESULT status){m_fConnected = FALSE;return HXR_OK;}//******************************************************************************//// Method: CHXNetCheck::Init//// Purpose: Sets up the CHXNetCheck object with a context.// //// Notes: n/a////******************************************************************************HX_RESULT CHXNetCheck::Init(IUnknown *pContext){ HX_RESULT result = HXR_OK; if (!pContext) return HXR_FAILED; m_pContext = pContext; m_pContext->AddRef(); return result;}//******************************************************************************//// Method: CHXNetCheck::FInternetAvailable//// Purpose: The function checks if we can attempt a connection without // being prompted to connect. // Returns true if we can, false otherwise.//// Notes: There is no single function for determining if a machine is // connected to the internet, and it is impossible to reliably // determine what is happening without side effects - such as // automatic network connections taking place.// // MSDN article - // "HOWTO: Detecting If you have a Connection to the Internet"//// "Usually the best way to determine if you have a connection // to a particular computer is to attempt the connection. If the // autodial feature of Windows is enabled then attempting the // connection may cause the default Internet dialup connectoid // to be opened, and you will be prompted with your credentials to connect.//// To avoid having the default Internet connectoid dialed, // the InternetGetConnectedState function can be used to determine // if there is a default Internet dialup connectoid configured and // whether it is currently active or not. If there is a default // Internet dialup connectoid configured and it is not currently // active then InternetGetConnectedState will return FALSE. // If InternetGetConnectedState returns TRUE then you can attempt // to connect to the Internet resource without fear of being prompted // to connect to another Internet Service Provider.//// You cannot rely solely on the fact that InternetGetConnectedState // returning TRUE means that you have a valid active Internet // connection. It is impossible for InternetGetConnectedState // to determine if the entire connection to the Internet is // functioning without sending a request to a server. This is why // you need to send a request to determine if you are really connected // or not. You can be assured however that if InternetGetConnectedState // returns TRUE, that attempting your connection will NOT cause you // to be prompted to connect to the default Internet Service Provider.//// Be aware that InternetGetConnectedState only reports the status // of the default Internet connectoid on Internet Explorer 4.x. // If a nondefault connectoid is connected, InternetGetConnectedState // always returns FALSE (unless a LAN connection is used). // With Internet Explorer 4.x configured to use a LAN connection, // InternetGetConectedState always returns TRUE.//// Internet Explorer 5 behaves differently. If you are currently dialed // into a different dial-up in Internet Explorer 5, InternetGetConnectedState // reports dial-up connection status as long as any connectoid is dialed // or an active LAN connection exists." ////******************************************************************************BOOL CHXNetCheck::FInternetAvailable(BOOL fPing, BOOL fProxy){ using namespace NetDetectLog; NetDetectLogLib logLib; BOOL fRet = FALSE; UINT16 nPort = DEF_HTTP_PORT; #ifndef _WIN16 WRITE_LOG0("FInternetAvailable fc entered..."); HKEY hKey = 0 ; DWORD fAutoDial = 0 ; DWORD regType = 0 ; DWORD cbBuf;#if !defined(WIN32_PLATFORM_PSPC) // set the error mode since we'll do some DLL loading and we want the OS to be // quiet whhen we do this UINT oldErrorMode = ::SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);#endif /* !defined(WIN32_PLATFORM_PSPC) */ // XXXSO - agreed to use InternetGetConnectedState function only. // The rest of the code should be called when this function is not available. BOOL fConnected = FALSE; if( SUCCEEDED( WinInetGetConnected( fConnected ))) { fRet = fPing ? SmartPing() : fConnected; goto Ret; }// XXXKM - agreed to remove proxy impact on net detect; instead let the following code determine// if we are connected or not - doing so will alleviate issues with proxy and dialup#if 0 if (fProxy) return TRUE;#endif WRITE_LOG0("Old algorithm entered ... "); WRITE_LOG0("Checking autodial flag ..."); // XXXKM - check this early; if autodial is set, then return FALSE temporarily // check the autodial bit in the registry. cbBuf = sizeof(fAutoDial); if (RegOpenKey(HKEY_CURRENT_USER, OS_STRING("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), &hKey) == ERROR_SUCCESS) { OSVERSIONINFO osv; memset(&osv, 0, sizeof(osv)); osv.dwOSVersionInfoSize = sizeof(osv); GetVersionEx(&osv); if (osv.dwPlatformId != VER_PLATFORM_WIN32_NT) { WRITE_LOG0("Checking Win95/98 EnableAutodial flag in HKCU/Software/Microsoft/Windows" "/Current Version/Internet Settings..."); // check for the Win95/98 flag RegQueryValueEx(hKey, OS_STRING("EnableAutodial"), NULL, ®Type, (BYTE *) &fAutoDial, &cbBuf); } else { WRITE_LOG0("Checking for the RAS key on NT."); // XXXKM - check for the RAS key on NT; only way I could find around the assert/crash in rasapi32.dll // in situations where the dll existed, but ras was disabled/removed on the machine HKEY hRasKey = 0; if (::RegOpenKey(HKEY_LOCAL_MACHINE, OS_STRING("SOFTWARE\\Microsoft\\RAS"), &hRasKey) == ERROR_SUCCESS) { // close the ras key ::RegCloseKey(hRasKey); // initialize to FALSE so this works the way it always has if something doesn't go right fAutoDial = FALSE; if (!m_hRasApiModule) m_hRasApiModule = ::LoadLibrary(OS_STRING("rasapi32.dll")); if (m_hRasApiModule) { WRITE_LOG0("rasapi32.dll loaded..."); // try and get the API to enumerate RAS devices FPRASENUMDEVICES fpRasEnumDevices = (FPRASENUMDEVICES)GetProcAddress(m_hRasApiModule, OS_STRING("RasEnumDevicesA")); if (!fpRasEnumDevices) { fpRasEnumDevices = (FPRASENUMDEVICES)GetProcAddress(m_hRasApiModule, OS_STRING("RasEnumDevicesW")); } // we use this to see if there is a RAS enabled device on this system and also to // check for initialization of the RAS subsystem since it will return an error if // RAS is disabled or fails to initialize for whatever reason // XXXKM - this was added to prevent crashing on Win NT systems in the EnumEntries call // on machines where RAS has been disabled due to hardware profiles if (fpRasEnumDevices) { WRITE_LOG0("Checking the RAS enabled devices..."); RASDEVINFO rasDevInfo[1]; rasDevInfo[0].dwSize = sizeof(rasDevInfo); DWORD bufferSize = sizeof(rasDevInfo); DWORD numEntries = 0; DWORD retVal = fpRasEnumDevices(rasDevInfo, &bufferSize, &numEntries); // check if there was actually a RAS enabled device; this API will return an error // if there are no RAS devices enabled, or if the RAS subsystem couldn't be initialized if (retVal == ERROR_BUFFER_TOO_SMALL || retVal == ERROR_SUCCESS && numEntries == 1) { // find the right entrypoint in the rasapi32.dll FPRASENUMENTRIES fpRasEnumEntries = (FPRASENUMENTRIES)GetProcAddress(m_hRasApiModule, OS_STRING("RasEnumEntriesA")); if (!fpRasEnumEntries) { fpRasEnumEntries = (FPRASENUMENTRIES)GetProcAddress(m_hRasApiModule, OS_STRING("RasEnumEntriesW")); } // if we've got the RAS entries function, then call it if (fpRasEnumEntries) { WRITE_LOG0("Calling RasEnumEntries function..."); // setup the RAS entry structure for a single dialup item RASENTRYNAME rasEntryName[1]; rasEntryName[0].dwSize = sizeof(rasEntryName); bufferSize = sizeof(rasEntryName); numEntries = 0; // call the function to see how many dialup entries there are retVal = fpRasEnumEntries(NULL, NULL, rasEntryName, &bufferSize, &numEntries); // if our buffer is too small (i.e. there are more than one phone book entries) // or we get a single item, then we have dialup, so set autodial to TRUE so // we'll tread lightly if (retVal == ERROR_BUFFER_TOO_SMALL || (numEntries == 1 && retVal == ERROR_SUCCESS)) fAutoDial = TRUE; } } } } } } // close the key when we're done with it ::RegCloseKey(hKey); } WRITE_LOG1("Checked AUTODIAL flag = %d.", fAutoDial); // XXXKM - only check netcard active status if autodial is not on; if it's on, then // assume we are doing stuff through RAS connection only and ignore netcard for now; // only temporary if (!fAutoDial && FNetCardActive()) { WRITE_LOG0("FNetCardActive fc returned TRUE. goto exit ..."); fRet = TRUE; goto Ret; } if (!fAutoDial) // if it's not set, go ahead and try the network { if (fPing) fRet = SmartPing(); else fRet = TRUE; goto Ret; } else // See if we have an active RAS connection { WRITE_LOG0("Any active RAS connection?"); DWORD cRasConns = 0; RASCONN rgRasConn[5]; DWORD cb = sizeof(rgRasConn); if (!m_hRasApiModule) m_hRasApiModule= LoadLibrary(OS_STRING("rasapi32.dll")); // add this code if this ever gets into win16; win16 will return nonnull on error from load library #if _WIN16 if (m_handle < HINSTANCE_ERROR) m_handle = NULL; #endif if (!m_hRasApiModule) // Dialup networking is not installed. { WRITE_LOG0("Dialup networking not installed ..."); if (fPing) fRet = SmartPing(); else fRet = TRUE; goto Ret; } if (!m_pRasEnumConnections) m_pRasEnumConnections = (FPRASENUMCONNECTIONS)GetProcAddress(m_hRasApiModule,OS_STRING("RasEnumConnectionsA")); if (!m_pRasEnumConnections) // Dialup networking is not installed. { WRITE_LOG0("Cannot load RasEnumConnections fc..."); if (fPing) fRet = SmartPing(); else fRet = TRUE; goto Ret; } rgRasConn[0].dwSize = sizeof(RASCONN); m_pRasEnumConnections(rgRasConn, &cb, &cRasConns); WRITE_LOG1("RasEnumConnections found %d connections...", cRasConns); if (cRasConns) { if (fPing) fRet = SmartPing(); else fRet = TRUE; goto Ret; } else { fRet = FALSE; goto Ret; } }Ret: // free up the library if loaded if (m_hRasApiModule) { ::FreeLibrary(m_hRasApiModule); m_hRasApiModule = NULL; }#if !defined(WIN32_PLATFORM_PSPC) // reset the error mode to the old value ::SetErrorMode(oldErrorMode);#endif /* !defined(WIN32_PLATFORM_PSPC) */ WRITE_LOG1("FInternetAvailable terminated with %s value...", fRet ? "TRUE" : "FALSE"); return(fRet);#else // Win16 section // =-=w16.0 for win16 always returns true, since there is no popup dialog in the way return (TRUE);#endif}//******************************************************************************//// Method: CHXNetCheck::Ping//// Purpose: Tests to see if we can open a TCP connection to the given hostname. // if fAynchronous is true, we call back a response object provided by// the caller (through Init). Otherwise we block.// //// Notes: n/a////******************************************************************************BOOL CHXNetCheck::Ping(const char *szHostName, UINT16 nPort, BOOL fAsynchronous){ ULONG32 ulStartTime, ulCurrentTime, ulElapsedTime; BOOL fRet = FALSE; // If we don't have the network services interface yet than try and get it here if (m_pContext && !m_pRmaNetServices) m_pContext->QueryInterface(IID_IHXNetworkServices, (void**)&m_pRmaNetServices); if (!m_pRmaTCPSocket && m_pRmaNetServices) m_pRmaNetServices->CreateTCPSocket(&m_pRmaTCPSocket); if (!m_pRmaTCPSocket) return FALSE; m_fFailed = m_fConnected = FALSE; m_pRmaTCPSocket->Init(this); m_pRmaTCPSocket->Connect(szHostName, nPort); ulElapsedTime = 0; // Get start time ulStartTime = HX_GET_TICKCOUNT(); while (!m_fFailed && !m_fConnected && (ulElapsedTime < m_Timeout)) { SleepWell(1000); ulCurrentTime = HX_GET_TICKCOUNT(); ulElapsedTime = CALCULATE_ELAPSED_TICKS(ulStartTime, ulCurrentTime); } fRet = m_fConnected; m_pRmaTCPSocket->Release(); m_pRmaTCPSocket = NULL; return (fRet);}//******************************************************************************//// Method: CHXNetCheck::SleepWell//// Purpose: This method sleeps but continues to pump messages. This allows us to // block properly, even under such platforms as Win16.// //// Notes: n/a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -