277 lines
6.2 KiB
C++
277 lines
6.2 KiB
C++
|
#include "precomp.h"
|
||
|
#include "ping.h"
|
||
|
#include "avutil.h" // for RtStrToInt
|
||
|
|
||
|
|
||
|
const CHAR g_cszPingData[] = "NetMeetingPing";
|
||
|
const int PING_BUFFERSIZE = 1024;
|
||
|
const DWORD PING_TIMEOUT = 4000; // 4 seconds
|
||
|
const DWORD PING_RETRIES = 4;
|
||
|
const TCHAR g_cszICMPDLLName[] = _TEXT("icmp.dll");
|
||
|
|
||
|
//
|
||
|
// CPing::Ping()
|
||
|
//
|
||
|
// Return value:
|
||
|
// E_FAIL: Function failed
|
||
|
// S_FALSE: Function succeeded, ping failed
|
||
|
// S_OK: Function succeeded, ping succeeded
|
||
|
//
|
||
|
|
||
|
HRESULT CPing::Ping(DWORD dwAddr, DWORD dwTimeout, DWORD dwRetries)
|
||
|
{
|
||
|
DebugEntry(CPing::Ping);
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
if (0 != dwAddr)
|
||
|
{
|
||
|
if (NULL == m_hICMPDLL)
|
||
|
{
|
||
|
m_hICMPDLL = ::LoadLibrary(g_cszICMPDLLName);
|
||
|
}
|
||
|
if (NULL != m_hICMPDLL)
|
||
|
{
|
||
|
m_pfnCreateFile = (PFNIcmpCreateFile)
|
||
|
::GetProcAddress(m_hICMPDLL, "IcmpCreateFile");
|
||
|
m_pfnCloseHandle = (PFNIcmpCloseHandle)
|
||
|
::GetProcAddress(m_hICMPDLL, "IcmpCloseHandle");
|
||
|
m_pfnSendEcho = (PFNIcmpSendEcho)
|
||
|
::GetProcAddress(m_hICMPDLL, "IcmpSendEcho");
|
||
|
if ((NULL != m_pfnCreateFile) &&
|
||
|
(NULL != m_pfnCloseHandle) &&
|
||
|
(NULL != m_pfnSendEcho))
|
||
|
{
|
||
|
HANDLE hPing = m_pfnCreateFile();
|
||
|
if (NULL != hPing)
|
||
|
{
|
||
|
BYTE buffer[PING_BUFFERSIZE];
|
||
|
for (DWORD dwTry = 0; dwTry < dwRetries; dwTry++)
|
||
|
{
|
||
|
DWORD dwStatus = m_pfnSendEcho( hPing,
|
||
|
dwAddr,
|
||
|
(LPVOID) g_cszPingData,
|
||
|
(WORD) CCHMAX(g_cszPingData),
|
||
|
NULL,
|
||
|
buffer,
|
||
|
sizeof(buffer),
|
||
|
dwTimeout);
|
||
|
if (0 != dwStatus)
|
||
|
{
|
||
|
if (((PICMP_ECHO_REPLY)buffer)->Status == IP_SUCCESS)
|
||
|
{
|
||
|
TRACE_OUT(("ping: %d.%d.%d.%d succeeded",
|
||
|
((LPBYTE)&dwAddr)[0],
|
||
|
((LPBYTE)&dwAddr)[1],
|
||
|
((LPBYTE)&dwAddr)[2],
|
||
|
((LPBYTE)&dwAddr)[3]));
|
||
|
hr = S_OK; // function succeeded - ping succeeded
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE_OUT(("ping: %d.%d.%d.%d failed",
|
||
|
((LPBYTE)&dwAddr)[0],
|
||
|
((LPBYTE)&dwAddr)[1],
|
||
|
((LPBYTE)&dwAddr)[2],
|
||
|
((LPBYTE)&dwAddr)[3]));
|
||
|
hr = S_FALSE; // function succeeded - ping failed
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE_OUT(("ping: %d.%d.%d.%d did not respond",
|
||
|
((LPBYTE)&dwAddr)[0],
|
||
|
((LPBYTE)&dwAddr)[1],
|
||
|
((LPBYTE)&dwAddr)[2],
|
||
|
((LPBYTE)&dwAddr)[3]));
|
||
|
}
|
||
|
}
|
||
|
m_pfnCloseHandle(hPing);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ERROR_OUT(("IcmpCreateFile() failed"));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ERROR_OUT(("Could not find icmp.dll entry points"));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ERROR_OUT(("Could not load icmp.dll"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DebugExitHRESULT(CPing::Ping, hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL CPing::IsAutodialEnabled ( VOID )
|
||
|
{
|
||
|
// Figure out the os platform if not done so
|
||
|
//
|
||
|
if (m_dwPlatformId == PLATFORM_UNKNOWN)
|
||
|
{
|
||
|
OSVERSIONINFO osvi;
|
||
|
ZeroMemory (&osvi, sizeof (osvi));
|
||
|
osvi.dwOSVersionInfoSize = sizeof (osvi);
|
||
|
if (GetVersionEx (&osvi))
|
||
|
{
|
||
|
m_dwPlatformId = osvi.dwPlatformId;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check autodial enabling for either platform
|
||
|
//
|
||
|
BOOL fEnabled;
|
||
|
switch (m_dwPlatformId)
|
||
|
{
|
||
|
case VER_PLATFORM_WIN32_WINDOWS: // 1, Windows 95
|
||
|
fEnabled = IsWin95AutodialEnabled ();
|
||
|
break;
|
||
|
case VER_PLATFORM_WIN32_NT: // 2, Windows NT
|
||
|
fEnabled = IsWinNTAutodialEnabled ();
|
||
|
break;
|
||
|
case VER_PLATFORM_WIN32s: // 0, Windows 3.1
|
||
|
default: // unknown
|
||
|
ASSERT (FALSE);
|
||
|
fEnabled = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return fEnabled;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define c_szWin95AutodialRegFolder TEXT ("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")
|
||
|
#define c_szWin95AutodialRegKey TEXT ("EnableAutodial")
|
||
|
|
||
|
BOOL CPing::IsWin95AutodialEnabled ( VOID )
|
||
|
{
|
||
|
// Always check the registry
|
||
|
//
|
||
|
BOOL fEnabled = FALSE;
|
||
|
|
||
|
// Need to check the registry setting.
|
||
|
// In case of error, report no autodial.
|
||
|
//
|
||
|
HKEY hKey;
|
||
|
if (RegOpenKeyEx ( HKEY_CURRENT_USER,
|
||
|
c_szWin95AutodialRegFolder,
|
||
|
0,
|
||
|
KEY_READ,
|
||
|
&hKey) == NOERROR)
|
||
|
{
|
||
|
TCHAR szValue[16];
|
||
|
ZeroMemory (&szValue[0], sizeof (DWORD));
|
||
|
|
||
|
ULONG cb = sizeof (szValue);
|
||
|
DWORD dwType;
|
||
|
if (RegQueryValueEx (hKey, c_szWin95AutodialRegKey, NULL,
|
||
|
&dwType, (BYTE *) &szValue[0], &cb)
|
||
|
== NOERROR)
|
||
|
{
|
||
|
switch (dwType)
|
||
|
{
|
||
|
case REG_DWORD:
|
||
|
case REG_BINARY:
|
||
|
fEnabled = (BOOL) *(LONG *) &szValue[0];
|
||
|
break;
|
||
|
#if 0 // do not need to worry about this case, IE must maintain backward compatibility
|
||
|
case REG_SZ:
|
||
|
fEnabled = (BOOL) RtStrToInt (&szValue[0]);
|
||
|
break;
|
||
|
#endif // 0
|
||
|
default:
|
||
|
ASSERT (FALSE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
}
|
||
|
|
||
|
return fEnabled;
|
||
|
}
|
||
|
|
||
|
|
||
|
// RAS only runs on NT 4.0 or later, as a result, WINVER must be 0x401 or larger
|
||
|
//
|
||
|
#if (WINVER < 0x401)
|
||
|
#undef WINVER
|
||
|
#define WINVER 0x401
|
||
|
#endif
|
||
|
|
||
|
#include <ras.h>
|
||
|
|
||
|
// DWORD APIENTRY RasGetAutodialParamA( DWORD, LPVOID, LPDWORD ); // defined in <ras.h>
|
||
|
// DWORD APIENTRY RasGetAutodialParamW( DWORD, LPVOID, LPDWORD ); // defined in <ras.h>
|
||
|
typedef DWORD (APIENTRY *PFN_RasGetAutodialParam) ( DWORD, LPVOID, LPDWORD );
|
||
|
#define c_szRasGetAutodialParam "RasGetAutodialParamW"
|
||
|
#define c_szRasApi32Dll TEXT ("rasapi32.dll")
|
||
|
|
||
|
|
||
|
BOOL CPing::IsWinNTAutodialEnabled ( VOID )
|
||
|
{
|
||
|
// Decide if we want to check autodial registry setting
|
||
|
//
|
||
|
BOOL fEnabled = FALSE;
|
||
|
if (m_fWinNTAutodialEnabled == AUTODIAL_UNKNOWN)
|
||
|
{
|
||
|
// We do not want to have initialization error
|
||
|
//
|
||
|
UINT uErrMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
||
|
|
||
|
// Load the library rasapi32.dll from the system directory
|
||
|
//
|
||
|
HINSTANCE hRasApi32Dll = LoadLibrary (c_szRasApi32Dll);
|
||
|
if (hRasApi32Dll != NULL)
|
||
|
{
|
||
|
// Get the proc address for RasGetAutodialParam()
|
||
|
//
|
||
|
PFN_RasGetAutodialParam pfn = (PFN_RasGetAutodialParam)
|
||
|
GetProcAddress (hRasApi32Dll, c_szRasGetAutodialParam);
|
||
|
if (pfn != NULL)
|
||
|
{
|
||
|
// Query RAS if it disables autodial
|
||
|
//
|
||
|
DWORD dwVal, dwSize = sizeof (DWORD);
|
||
|
DWORD dwErr = (*pfn) (RASADP_LoginSessionDisable, &dwVal, &dwSize);
|
||
|
if (dwErr == 0)
|
||
|
{
|
||
|
// Set the autodial flag only when everything succeeds
|
||
|
//
|
||
|
fEnabled = (dwVal == 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FreeLibrary (hRasApi32Dll);
|
||
|
}
|
||
|
|
||
|
// Restore error mode
|
||
|
//
|
||
|
SetErrorMode (uErrMode);
|
||
|
|
||
|
m_fWinNTAutodialEnabled = fEnabled;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Do not need to check the registry setting.
|
||
|
// Simply use the cached one.
|
||
|
//
|
||
|
fEnabled = m_fWinNTAutodialEnabled;
|
||
|
}
|
||
|
|
||
|
return fEnabled;
|
||
|
}
|
||
|
|
||
|
|