netchck.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:36k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hlxclib/windows.h"
- #include "prefdefs.h"
- #include "netchck.h"
- #include "hxtick.h"
- #include "hxassert.h"
- #include "hxver.h"
- #include <raserror.h> // for ras error codes
- #define DEF_DNS_PORT 53 //tcp
- #define DIALOG_CLASS "#32770"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- // Comment out this definition for release versions that shouldn't have
- // logging code compiled in.
- #define USE_NETDETECT_LOG 1
- #ifdef USE_NETDETECT_LOG
- #include "hlxclib/fcntl.h" // for file constants
- #include "chxdataf.h" // CHXDataFile
- #include "hlxclib/time.h"
- #include "pref.h" // CPref
- #include "ihxpckts.h" // IHXBuffer
- #endif
- namespace NetDetectLog
- {
- #ifndef USE_NETDETECT_LOG
- #define WRITE_LOG0(format) do {;} while(0)
- #define WRITE_LOG1(format, x1) do {;} while(0)
- #define INITIALIZE_LOG() do {;} while(0)
- #define CLOSE_LOG() do {;} while(0)
- #define WRITE_LOG_WINET(result, flags) do {;} while(0)
- #else
- #define STR_EOL "rn"
-
- const char* const kszNetdetectLogFileName = "netdtlog.txt";
- const char* const kszNetdetectLogPrefKey = "netdetectlog";
- static CHXDataFile* g_pLogFile = NULL;
- HX_RESULT InitializeLog();
- HX_RESULT CloseLog();
- HX_RESULT WriteToLog(const CHXString& msg);
- HX_RESULT WriteToLogWinInetGetConnected(BOOL result, DWORD flags);
- #define INITIALIZE_LOG() do { InitializeLog(); } while(0)
- #define CLOSE_LOG() do { CloseLog(); } while(0)
- #define WRITE_LOG0(format)
- WriteToLog(format);
- #define WRITE_LOG1(format, x1){
- CHXString strFormat;
- strFormat.Format(format, x1);
- WriteToLog(strFormat);}
- #define WRITE_LOG_WINET(result, flags)
- WriteToLogWinInetGetConnected(result, flags)
- HX_RESULT WriteToLogWinInetGetConnected(BOOL result, DWORD flags)
- {
- // Flags for InternetGetConnectedState
- #define INTERNET_CONNECTION_MODEM 0x01
- #define INTERNET_CONNECTION_LAN 0x02
- #define INTERNET_CONNECTION_PROXY 0x04
- #define INTERNET_CONNECTION_MODEM_BUSY 0x08 /* no longer used */
- #define INTERNET_RAS_INSTALLED 0x10
- #define INTERNET_CONNECTION_OFFLINE 0x20
- #define INTERNET_CONNECTION_CONFIGURED 0x40
- CHXString strFormat;
- if(result)
- {
- CHXString format("InternetGetConnectedState returned TRUE; flag = %s");
- if(flags & INTERNET_CONNECTION_MODEM)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_MODEM");
- }
- else if(flags & INTERNET_CONNECTION_LAN)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_LAN");
- }
- else if(flags & INTERNET_CONNECTION_PROXY)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_PROXY");
- }
- else if(flags & INTERNET_CONNECTION_MODEM_BUSY)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_MODEM_BUSY");
- }
- else if(flags & INTERNET_RAS_INSTALLED)
- {
- strFormat.Format(format, "INTERNET_RAS_INSTALLED");
- }
- else if(flags & INTERNET_CONNECTION_OFFLINE)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_OFFLINE");
- }
- else if(flags & INTERNET_CONNECTION_CONFIGURED)
- {
- strFormat.Format(format, "INTERNET_CONNECTION_CONFIGURED");
- }
- }
- else
- {
- strFormat = "InternetGetConnectedState returned FALSE";
- }
- return WriteToLog(strFormat);
- }
- HX_RESULT InitializeLog()
- {
- HX_RESULT res = HXR_FAIL;
-
- BOOL bShouldWriteLogFile = FALSE;
- // Read from the preferences to see if we should write a log file.
- CPref* pPreferences = CPref::open_shared_pref( HXVER_COMMUNITY );
- if( pPreferences )
- {
- IHXBuffer* pBuffer = NULL;
- if( SUCCEEDED( pPreferences->read_pref( kszNetdetectLogPrefKey, pBuffer )))
- {
- bShouldWriteLogFile =
- ( atoi( reinterpret_cast<const char*>(pBuffer->GetBuffer())) == 1 );
- HX_RELEASE(pBuffer);
- }
- HX_DELETE( pPreferences );
- }
- if( !bShouldWriteLogFile )
- {
- return res;
- }
- // First try to open the file for appending. If that doesn't work,
- // then just create a new one.
- g_pLogFile = CHXDataFile::Construct();
- if (g_pLogFile)
- {
- res = g_pLogFile->Open(kszNetdetectLogFileName,
- O_BINARY | O_WRONLY | O_APPEND, TRUE);
- if (FAILED(res))
- {
- res = g_pLogFile->Open(kszNetdetectLogFileName,
- O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, TRUE);
- }
- if( SUCCEEDED( res ))
- {
- CHXString strMsg;
- strMsg.Format("%s################################################"
- "##############################%s",
- STR_EOL, STR_EOL);
- g_pLogFile->Write(strMsg, strMsg.GetLength());
- }
- else
- {
- HX_DELETE(g_pLogFile);
- }
- }
- return res;
- }
- HX_RESULT CloseLog()
- {
- if (g_pLogFile)
- {
- g_pLogFile->Close();
- HX_DELETE(g_pLogFile);
- }
- return HXR_OK;
- }
- HX_RESULT WriteToLog(const CHXString& msg)
- {
- HX_RESULT res = HXR_FAIL;
- if (g_pLogFile)
- {
- time_t now = time(NULL);
- struct tm* date = localtime(&now);
-
- char szTime[20] = { 0 }; /* Flawfinder: ignore */
- #if !defined(WIN32_PLATFORM_PSPC)
- if(date)
- {
- strftime(szTime, 19, "%X", date);
- }
- #endif /* !defined(WIN32_PLATFORM_PSPC) */
- CHXString newMsg;
- newMsg.Format("%s: %s%s", szTime, (const char*)msg, STR_EOL);
- res = (g_pLogFile->Write(newMsg, newMsg.GetLength())
- == newMsg.GetLength()) ? HXR_OK : HXR_FAIL;
- }
- return res;
- }
- #endif // USE_NETDETECT_LOG
- // "resource aquisition is init" - Init/ Close log file
- class NetDetectLogLib
- {
- public:
- NetDetectLogLib() { INITIALIZE_LOG(); }
- ~NetDetectLogLib() { CLOSE_LOG(); }
- };
- } //NetDetectLog namespace
- CHXNetCheck::CHXNetCheck(UINT32 timeout) :
- XHXNetCheck(timeout)
- ,m_pRmaNetServices(0)
- , m_pRmaTCPSocket(0)
- , m_pContext(0)
- , m_fConnected(FALSE)
- , m_fFailed(FALSE)
- , m_lRefCount(0)
- #ifndef _WIN16
- , m_hRasApiModule(0)
- , m_pRasEnumConnections(0)
- #endif
-
- {
- }
- CHXNetCheck::~CHXNetCheck()
- {
- if (m_pContext)
- m_pContext->Release();
- m_pContext = NULL;
- if (m_pRmaNetServices)
- m_pRmaNetServices->Release();
- m_pRmaNetServices = NULL;
- if (m_pRmaTCPSocket)
- m_pRmaTCPSocket->Release();
- m_pRmaTCPSocket = NULL;
-
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::QueryInterface
- // Purpose:
- // Implement this to export the interfaces supported by your
- // object.
- //
- STDMETHODIMP CHXNetCheck::QueryInterface(REFIID riid, void** ppvObj)
- {
- if (IsEqualIID(riid, IID_IUnknown))
- {
- AddRef();
- *ppvObj = this;
- return HXR_OK;
- }
- if (IsEqualIID(riid, IID_IHXTCPResponse))
- {
- AddRef();
- *ppvObj = (IHXTCPResponse*)this;
- return HXR_OK;
- }
- *ppvObj = NULL;
- return HXR_NOINTERFACE;
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::AddRef
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(UINT32) CHXNetCheck::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(UINT32) CHXNetCheck::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- /*
- * IHXTCPResponse methods
- */
- /************************************************************************
- * Method:
- * IHXTCPResponse::ConnectDone
- * Purpose:
- * A Connect operation has been completed or an error has occurred.
- */
- STDMETHODIMP CHXNetCheck::ConnectDone (HX_RESULT status)
- {
- HX_ASSERT(m_fConnected == FALSE); // We shouldn't be getting called if
- // we aren't expecting it.
- if (status == HXR_OK)
- m_fConnected = TRUE;
- else
- m_fFailed = TRUE;
- return HXR_OK;
- }
- /************************************************************************
- * Method:
- * IHXTCPResponse::ReadDone
- * Purpose:
- * A Read operation has been completed or an error has occurred.
- * The data is returned in the IHXBuffer.
- */
- STDMETHODIMP CHXNetCheck::ReadDone (HX_RESULT status,
- IHXBuffer* pBuffer)
- {
- HX_ASSERT(FALSE);
- return HXR_OK;
- }
- /************************************************************************
- * Method:
- * IHXTCPResponse::WriteReady
- * Purpose:
- * This is the response method for WantWrite.
- * If HX_RESULT is ok, then the TCP channel is ok to Write to.
- */
- STDMETHODIMP CHXNetCheck::WriteReady (HX_RESULT status)
- {
- 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
- //
- //******************************************************************************
- void CHXNetCheck::SleepWell(ULONG32 ulInterval)
- {
- ULONG32 ulStartTime, ulCurrentTime;
- MSG msg;
- char szClassName[16] = ""; /* Flawfinder: ignore */
- HWND hActiveWindow = NULL;
-
- // Get start time
- ulStartTime = HX_GET_TICKCOUNT();
- do
- {
- // Keep pumping messages
- if(PeekMessage(&msg, NULL,0,0,PM_REMOVE))
- {
- if(msg.message == WM_QUIT)
- {
- PostQuitMessage(0);
- break;
- }
- else
- {
- // XXXJDL Since we are pumping messages through here while we block elsewhere in the calling code
- // we need to get the free dialog navigation support from windows for modeless dialog boxes. Modal dialog
- // boxes are fine since they will not go through this message loop. I have been using this method
- // in the main player application and it seems to work ok. Let me know if this causes pain for anyone.
- // Basically if the active window is a dialog box class then we are assuming it is a modeless dialog box
- // and calling IsDialogMessage with this handle. If the active window is neither a dialog class or
- // doesn't process the dialog message then we do the normal message dispatching
- hActiveWindow = ::GetActiveWindow();
- szClassName[0] = ' ';
- ::GetClassName(hActiveWindow,
- OS_STRING2(szClassName,sizeof(szClassName)),
- sizeof(szClassName));
- if (strcmp(szClassName,DIALOG_CLASS) || !IsDialogMessage(hActiveWindow, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
- // If we have waited ulInterval time then drop out
- ulCurrentTime = HX_GET_TICKCOUNT();
- } while (CALCULATE_ELAPSED_TICKS(ulStartTime, ulCurrentTime) < ulInterval);
- }
- //******************************************************************************
- //
- // Method: CHXNetCheck::GetDNSAddress
- //
- // Purpose: Determines the IP address of the user's primary DNS server.
- //
- // Notes: Returns IP address in numeric form, in a CHXString. An empty
- // string is returned when the IP address cannot be determined.
- //
- //******************************************************************************
- void CHXNetCheck::GetDNSAddress(CHXString& strDNS)
- {
- #ifndef _WIN16
- strDNS.Empty();
- HKEY hKey = 0;
- // Win95/98 likes it here
- RegOpenKey(HKEY_LOCAL_MACHINE, "System\CurrentControlSet\Services\VxD\MSTCP\Parameters",
- &hKey);
- if (hKey != NULL)
- {
- GetNameServerKey(hKey, "NameServer", strDNS);
- if (strDNS.IsEmpty())
- GetNameServerKey(hKey, "DhcpNameServer", strDNS);
- RegCloseKey(hKey);
- }
- // Some Win 95/98 machines put it here..
- if (strDNS.IsEmpty())
- {
- RegOpenKey(HKEY_LOCAL_MACHINE, OS_STRING("System\CurrentControlSet\Services\VxD\MSTCP"),
- &hKey);
-
- if (hKey != NULL)
- {
- GetNameServerKey(hKey, "NameServer", strDNS);
- if (strDNS.IsEmpty())
- GetNameServerKey(hKey, "DhcpNameServer", strDNS);
- RegCloseKey(hKey);
- }
- }
- // Try WinNT registry location.
- if (strDNS.IsEmpty())
- {
- RegOpenKey(HKEY_LOCAL_MACHINE, OS_STRING("System\CurrentControlSet\Services\Tcpip\Parameters"),
- &hKey);
-
- if (hKey != NULL)
- {
- GetNameServerKey(hKey, "NameServer", strDNS);
- if (strDNS.IsEmpty())
- GetNameServerKey(hKey, "DhcpNameServer", strDNS);
- RegCloseKey(hKey);
- }
- }
- // Another WinNT registry location.
- if (strDNS.IsEmpty())
- {
- RegOpenKey(HKEY_LOCAL_MACHINE, OS_STRING("System\CurrentControlSet\Services\Tcpip"),
- &hKey);
- if (hKey != NULL)
- {
- GetNameServerKey(hKey, "NameServer", strDNS);
- if (strDNS.IsEmpty())
- GetNameServerKey(hKey, "DhcpNameServer", strDNS);
- RegCloseKey(hKey);
- }
- }
- // I want to make sure this technique of getting DNS address works. Email bpitzel
- // if it fails.
- HX_ASSERT( !strDNS.IsEmpty() );
- #endif
- }
- #ifndef _WIN16
- void CHXNetCheck::GetNameServerKey(HKEY hKey, const char* szKeyName, CHXString& strDNS)
- {
- char szDNS[MAX_PATH]; /* Flawfinder: ignore */
- DWORD regType = 0 ;
- DWORD cbuf;
- cbuf = sizeof(szDNS);
- if (ERROR_SUCCESS == RegQueryValueEx(hKey, OS_STRING(szKeyName), NULL, ®Type, (BYTE *) szDNS, &cbuf))
- {
- strDNS = szDNS;
-
- // Win95/98 separate multiple DNS addresses with ","
- // WinNT separate multiple DNS addresses with ","
- // We will grab the first IP address in the list
- strDNS = strDNS.SpanExcluding(" ,");
- strDNS.TrimLeft();
- strDNS.TrimRight();
- }
- }
- #endif /* _WIN16 */
- BOOL
- CHXNetCheck::SmartPing()
- {
- using namespace NetDetectLog;
- WRITE_LOG0("SmartPing fc entered ...");
- UINT16 nPort = DEF_HTTP_PORT;
- // try to get DNS address to ping.
- CHXString strPingAddr;
- GetDNSAddress(strPingAddr);
- nPort = DEF_DNS_PORT;
-
- // No DNS address? Default to a known web server.
- // XXXBJP pinging video.real.com, used in Beta 1, should be
- // changed for Beta 2!!
- if (strPingAddr.IsEmpty())
- {
- strPingAddr = "209.66.98.23"; // video.real.com .. UGHHHH!!
- nPort = DEF_HTTP_PORT;
- }
- return (Ping(strPingAddr, nPort, FALSE));
- }
- BOOL
- CHXNetCheck::FNetCardActive()
- {
- #if defined(_WIN16) || defined(WIN32_PLATFORM_PSPC)
- return TRUE;
- #else
- char szEnum_Name[ENUM_MAX][20] = {REGSTR_KEY_ROOTENUM, REGSTR_KEY_BIOSENUM, /* Flawfinder: ignore */
- REGSTR_KEY_PCIENUM, REGSTR_KEY_ISAENUM, REGSTR_KEY_EISAENUM,
- REGSTR_KEY_PCMCIAENUM};
- using namespace NetDetectLog;
- WRITE_LOG0("FNetCardActive entered ...");
- char szClass[64]; /* Flawfinder: ignore */
- ULONG ulType;
- ULONG32 cbData;
- CHXString sCurrentKey;
- CHXString sCurrentFiles;
- CHXString sDeviceID;
- char szCurrentDeviceNode[STRINGSIZE]; /* Flawfinder: ignore */
- char szCurrentDevice[STRINGSIZE]; /* Flawfinder: ignore */
- char szSoftwareKey[STRINGSIZE]; /* Flawfinder: ignore */
- BOOL bFoundKey = FALSE;
- int i;
- OSVERSIONINFO osv;
- memset(&osv, 0, sizeof(osv));
- osv.dwOSVersionInfoSize = sizeof(osv);
- GetVersionEx(&osv);
- if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
- return FALSE;
- using namespace NetDetectLog;
- WRITE_LOG0("Win95/98 : Looking for devices of the Net class...");
- // we want to look through the ENUMBIOS, ENUMISAPNP, and ENUMPCI
- // trees for devices of the Net class. For each display device
- // we find we will ask the Device manager if it is active.
- for (i = 0; i < ENUM_MAX && !bFoundKey; i++)
- {
- HKEY hBusKey = 0;
- sCurrentKey = (CHXString)REGSTR_KEY_ENUM + BACKSLASH + szEnum_Name[i];
- // Start reading the devices
- if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, OS_STRING(sCurrentKey), 0, KEY_READ, &hBusKey))
- {
- cbData = sizeof(szCurrentDeviceNode);
- ULONG32 dwDevNodeEnumIndex = 0;
- HKEY hDeviceNodeKey;
- // Enumerate all of the devices on the bus
- while (!bFoundKey &&
- !RegEnumKeyEx(hBusKey, dwDevNodeEnumIndex,
- OS_STRING2(szCurrentDeviceNode, cbData),
- &cbData, NULL, NULL, NULL, NULL))
- {
- // get the registry key for the current device node
- hDeviceNodeKey = 0;
- sCurrentKey = (CHXString)REGSTR_KEY_ENUM + BACKSLASH + szEnum_Name[i] + BACKSLASH + (CHXString)szCurrentDeviceNode;
- if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, OS_STRING(sCurrentKey), 0, KEY_READ, &hDeviceNodeKey))
- {
- cbData = sizeof(szCurrentDevice);
- ULONG32 dwHWDeviceEnumIndex = 0;
- HKEY hHWDeviceKey;
- // enumerate all of the hardware devices in this Device Node
- while (!bFoundKey &&
- !RegEnumKeyEx(hDeviceNodeKey, dwHWDeviceEnumIndex,
- OS_STRING2(szCurrentDevice, cbData),
- &cbData, NULL, NULL, NULL, NULL))
- {
- // get the registry key for the current hardware device
- int nBaseKeyLength = sCurrentKey.GetLength();
- hHWDeviceKey = 0;
- sCurrentKey += BACKSLASH + (CHXString) szCurrentDevice;
- if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, OS_STRING(sCurrentKey), 0, KEY_READ, &hHWDeviceKey))
- {
- // Ask if this device is a "Net" device by checking it's class
- cbData = sizeof(szClass);
- szClass[0] = 0;
- if (!RegQueryValueEx(hHWDeviceKey, OS_STRING("Class"), 0, &ulType, (LPBYTE) szClass, &cbData)
- && !stricmp(szClass, "Net"))
- {
- // if it is a display device then we want to find out if it is
- // the active device for this class.
- cbData = sizeof(szSoftwareKey);
- sDeviceID = (CHXString) szEnum_Name[i] + BACKSLASH + (CHXString)szCurrentDeviceNode
- + BACKSLASH + (CHXString) szCurrentDevice;
- // get the registry key name for the software key for the device, if it is not
- // null and this is the active device then we are done.
- if (!RegQueryValueEx(hHWDeviceKey, OS_STRING("Driver"), 0, &ulType, (LPBYTE) szSoftwareKey, &cbData)
- && szSoftwareKey[0] != '0'
- && DevNodeIsActive((sDeviceID))) // Call Config Manager in 16-bit code
- {
- bFoundKey = TRUE;
- WRITE_LOG1("Found active node %s...", (char const*) sDeviceID);
- }
- }
- }
- // reset the key to the base for the next time through the loop
- sCurrentKey = sCurrentKey.Left(nBaseKeyLength);
- if (hHWDeviceKey)
- {
- RegCloseKey(hHWDeviceKey);
- hHWDeviceKey = 0;
- }
- // move to next device key
- dwHWDeviceEnumIndex++;
- // reset size to szCurrentDevice size
- cbData = sizeof(szCurrentDevice);
- }
- }
- if (hDeviceNodeKey)
- {
- RegCloseKey(hDeviceNodeKey);
- hDeviceNodeKey = 0;
- }
- // move to the next device node
- dwDevNodeEnumIndex++;
- // reset the size to szCurrentDeviceNode size
- cbData = sizeof(szCurrentDeviceNode);
- }
- }
- if (hBusKey)
- {
- RegCloseKey(hBusKey);
- hBusKey = 0;
- }
- }
- return bFoundKey;
- #endif
- }
- BOOL
- CHXNetCheck::DevNodeIsActive(const char *szDeviceID)
- {
- #ifdef _WIN16
- HX_ASSERT (FALSE); // should never get called in win16
- return TRUE;
- #else
- HINSTANCE hDevNodeInst;
- DWORD dwStatus;
- DWORD dwProblemNumber;
- DWORD cr;
- DWORD (WINAPI * pGetDevNodeStatus32Call) (const char *, LPDWORD, LPDWORD);
- // 10 is a magic number for the configuration manager api
- // that eventually gets called in the 16 bit dll.
- dwStatus = dwProblemNumber = cr = 10;
- pGetDevNodeStatus32Call = 0;
- hDevNodeInst = LoadLibrary(OS_STRING(_32BIT_DLLNAME));
- // 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 (hDevNodeInst)
- {
- (FARPROC &) pGetDevNodeStatus32Call = GetProcAddress(hDevNodeInst, OS_STRING("GetDevNodeStatus32Call"));
- if (pGetDevNodeStatus32Call)
- {
- cr = pGetDevNodeStatus32Call(szDeviceID, &dwStatus, &dwProblemNumber);
- }
- FreeLibrary(hDevNodeInst);
- }
- if (cr == 0
- && dwProblemNumber == 0)
- return TRUE;
- else
- return FALSE;
- #endif
- }
- HX_RESULT CHXNetCheck::WinInetGetConnected(BOOL& bConnected)
- {
- using namespace NetDetectLog;
- WRITE_LOG0("WinInetGetConnected fc entered...");
- HINSTANCE hWinInet;
- BOOL (WINAPI * pInternetGetConnectedState) (LPDWORD lpdwFlags, DWORD dwReserved);
- hWinInet= LoadLibrary(OS_STRING(WININET_DLL));
- if (!hWinInet)
- {
- WRITE_LOG0("WinInet not present ...");
- return HXR_FAIL;
- }
- (FARPROC &) pInternetGetConnectedState = GetProcAddress(hWinInet, OS_STRING("InternetGetConnectedState"));
- if (!pInternetGetConnectedState )
- {
- WRITE_LOG0("InternetGetConnectedState fc cannot be loaded ...");
-
- FreeLibrary(hWinInet);
- return HXR_FAIL;
- }
- DWORD dwFlags;
- bConnected = pInternetGetConnectedState(&dwFlags, 0);
- FreeLibrary(hWinInet);
-
- WRITE_LOG_WINET(bConnected, dwFlags);
-
- return HXR_OK;
- }