|
|
/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
wan.cxx
Abstract:
This is the source file relating to the WAN-specific routines of the Connectivity APIs implementation.
Author:
Gopal Parupudi <GopalP>
[Notes:]
optional-notes
Revision History:
GopalP 10/11/1997 Start.
--*/
#include <precomp.hxx>
//
// Typedefs
//
typedef DWORD (APIENTRY *LPFN_RAS_ENUM)(LPRASCONN, LPDWORD, LPDWORD); typedef BOOL (APIENTRY *LPFN_DO_CONNECTOIDS_EXIST)(void); typedef DWORD (APIENTRY *LPFN_RAS_CONNECTION_NOTIFICATION)(HRASCONN, HANDLE, DWORD); typedef DWORD (APIENTRY *LPFN_RAS_GET_CONNECT_STATUS)(HRASCONN, LPRASCONNSTATUS);
//
// Constants
//
#define RAS_DLL SENS_STRING("RasApi32.dll")
#define WININET_DLL SENS_STRING("Wininet.dll")
#if !defined(SENS_CHICAGO)
#define RAS_ENUM "RasEnumConnectionsW"
#define RAS_CONNECTION_NOTIFICATION "RasConnectionNotificationW"
#else // SENS_CHICAGO
#define RAS_ENUM "RasEnumConnectionsA"
#define RAS_CONNECTION_NOTIFICATION "RasConnectionNotificationA"
#define RAS_GET_CONNECT_STATUS "RasGetConnectStatusA"
#define DO_CONNECTOIDS_EXIST (LPCSTR) 101 // Ordinal 101
#endif // SENS_CHICAGO
#if (WINVER < 0x401)
#define RASCN_Connection 0x00000001
#define RASCN_Disconnection 0x00000002
#endif // WINVER < 0x401
//
// Globals
//
// Common
long gdwLastWANTime; long gdwWANState; BOOL gbIsRasInstalled; LPFN_RAS_ENUM glpfnRasEnumConnections; LPFN_RAS_CONNECTION_NOTIFICATION glpfnRasConnectionNotification;
// IE5-specific
#if !defined(SENS_NT5)
HANDLE ghRasEvents[2]; HANDLE ghConnectWait; HANDLE ghDisconnectWait; #endif // SENS_NT5
// Win9x-specific
#if defined(SENS_CHICAGO)
LPFN_RAS_GET_CONNECT_STATUS glpfnRasGetConnectStatus; #endif // SENS_CHICAGO
inline void LoadRasIfNecessary( void ) /*++
Routine Description:
Load RAS DLL, if necessary.
Arguments:
None.
Return Value:
None.
--*/ { HMODULE hDLL;
//
// See if RAS DLL is already loaded.
//
if (NULL != glpfnRasEnumConnections) { return; }
//
// Do the necessary work.
//
hDLL = LoadLibrary(RAS_DLL); if (hDLL != NULL) { glpfnRasEnumConnections = (LPFN_RAS_ENUM) GetProcAddress(hDLL, RAS_ENUM); glpfnRasConnectionNotification = (LPFN_RAS_CONNECTION_NOTIFICATION) GetProcAddress(hDLL, RAS_CONNECTION_NOTIFICATION); #if defined(SENS_CHICAGO)
glpfnRasGetConnectStatus = (LPFN_RAS_GET_CONNECT_STATUS) GetProcAddress(hDLL, RAS_GET_CONNECT_STATUS); #endif // SENS_CHICAGO
if ( (NULL == glpfnRasEnumConnections) #if defined(SENS_CHICAGO)
&& (NULL == glpfnRasGetConnectStatus) #endif // SENS_CHICAGO
) { // Both entrypoints are NULL. Can't do much with RAS now.
FreeLibrary(hDLL); } }
SensPrintA(SENS_INFO, ("[SENS] LoadRasIfNecessary(): RAS DLL is %spresent.\n", (glpfnRasEnumConnections ? "" : "NOT ")));
}
BOOL DoWanSetup( void ) /*++
Routine Description:
Do minimal WAN Setup.
Arguments:
None.
Return Value:
TRUE, if successful.
FALSE, otherwise.
--*/ { DWORD dwLastError; DWORD dwCurrentRasState; BOOL bStatus;
dwLastError = 0; dwCurrentRasState = 0; bStatus = FALSE; glpfnRasEnumConnections = NULL; glpfnRasConnectionNotification = NULL; gbIsRasInstalled = FALSE; bStatus = TRUE;
Cleanup: //
// Cleanup
//
return bStatus; }
BOOL IsRasInstalled( OUT LPDWORD lpdwState, OUT LPDWORD lpdwLastError ) /*++
Routine Description:
Check to see if RAS is installed. If so, return it's current state.
Arguments:
lpdwState - If Ras is installed, this parameter contains the current state of the RasMan service.
lpdwLastError - If RAS is not active or installed, it retuns the GLE.
Return Value:
TRUE, if Ras is installed.
FALSE, otherwise.
--*/ { if (TRUE == gbIsRasInstalled) { *lpdwState = SERVICE_RUNNING; // For NT
*lpdwLastError = ERROR_SUCCESS;
return TRUE; }
static SC_HANDLE hSCM; // Cache the handle.
static SC_HANDLE hRasMan; // Cache the handle.
BOOL bRetValue; SERVICE_STATUS ServiceStatus;
bRetValue = FALSE; *lpdwState = 0; *lpdwLastError = ERROR_SUCCESS;
if (NULL == hSCM) { hSCM = OpenSCManager( NULL, // Local machine
NULL, // Default database - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS // NOTE: Only for Administrators
); if (NULL == hSCM) { SensPrintA(SENS_ERR, ("OpenSCManager() returned %d\n", *lpdwLastError)); goto Cleanup; } }
if (hRasMan == NULL) { hRasMan = OpenService( hSCM, // Handle to SCM database
RAS_MANAGER, // Name of the service to start
SERVICE_QUERY_STATUS // Type of access requested
); if (NULL == hRasMan) { SensPrintA(SENS_ERR, ("OpenService() returned %d\n", *lpdwLastError)); goto Cleanup; } }
memset(&ServiceStatus, 0, sizeof(SERVICE_STATUS));
bRetValue = QueryServiceStatus( hRasMan, &ServiceStatus ); ASSERT(bRetValue == TRUE);
if (FALSE == bRetValue) { goto Cleanup; }
*lpdwState = ServiceStatus.dwCurrentState;
gbIsRasInstalled = TRUE;
SensPrintA(SENS_ERR, ("IsRasInstalled(): RASMAN state is %d\n", *lpdwState));
return TRUE;
Cleanup: //
// Cleanup
//
*lpdwLastError = GetLastError();
if (hSCM) { CloseServiceHandle(hSCM); hSCM = NULL; } if (hRasMan) { CloseServiceHandle(hRasMan); hRasMan = NULL; }
return FALSE; }
BOOL WINAPI EvaluateWanConnectivity( OUT LPDWORD lpdwLastError ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { BOOL bWanAlive; BOOL bRasInstalled; DWORD dwNow; DWORD dwCurrentRasState; SERVICE_STATUS ServiceStatus; PWCHAR szEntryName; DWORD dwLocalLastError;
dwNow = GetTickCount(); bWanAlive = FALSE; dwCurrentRasState = 0; dwLocalLastError = ERROR_NO_NETWORK;
if (lpdwLastError) { *lpdwLastError = dwLocalLastError; } else { lpdwLastError = &dwLocalLastError; }
szEntryName = new WCHAR[RAS_MaxEntryName + 1]; if (!szEntryName ) { *lpdwLastError = ERROR_OUTOFMEMORY; return FALSE; }
wcscpy(szEntryName, DEFAULT_WAN_CONNECTION_NAME);
//
// If RasManager is running, it implies that there "might" be one or more
// active RAS connections.
//
bRasInstalled = IsRasInstalled(&dwCurrentRasState, lpdwLastError);
if (TRUE == bRasInstalled) { LoadRasIfNecessary(); }
if ( (bRasInstalled) && (dwCurrentRasState == SERVICE_RUNNING) && (glpfnRasEnumConnections != NULL)) { DWORD dwRasStatus; DWORD cBytes; DWORD cBytesOld; DWORD cConnections; RASCONN *pRasConn;
dwRasStatus = 0x0; cConnections = 0;
//
// Start with loop with a single structure. Will loop and realloc if we need
// a larger buffer.
//
cBytesOld = 0; cBytes = sizeof(RASCONN); pRasConn = NULL; dwRasStatus = ERROR_BUFFER_TOO_SMALL;
//
// Loop till RasEnumConnections() succeeds or returns with an error
// other than ERROR_BUFFER_TOO_SMALL.
//
while (ERROR_BUFFER_TOO_SMALL == dwRasStatus) { ASSERT(cBytes > cBytesOld); ASSERT(pRasConn == NULL);
// Allocate the buffer
pRasConn = (RASCONN *) new char[cBytes]; if (pRasConn == NULL) { delete szEntryName; *lpdwLastError = ERROR_OUTOFMEMORY; return FALSE; }
pRasConn[0].dwSize = sizeof(RASCONN); cBytesOld = cBytes;
dwRasStatus = (*glpfnRasEnumConnections)( pRasConn, &cBytes, &cConnections );
// Free the too small buffer.
if (ERROR_BUFFER_TOO_SMALL == dwRasStatus) { delete pRasConn; pRasConn = NULL; SensPrintA(SENS_WARN, ("RasEnumConnections(): reallocing buffer to be %d bytes\n", cBytes)); } }
if ((0 == dwRasStatus) && (cConnections > 0)) { bWanAlive = TRUE; SensPrintA(SENS_INFO, ("RasEnumConnections(%d) successful connections (%d)\n", cBytes, cConnections));
// P3 BUG: we're only dealing with one RAS connection for now
SensPrintA(SENS_INFO, ("\tConnection name: %s\n", pRasConn->szEntryName));
wcscpy(szEntryName, pRasConn->szEntryName); } else { if (dwRasStatus != 0) { *lpdwLastError = dwRasStatus; } SensPrintA(SENS_ERR, ("RasEnumConnections() returned %d - " "connections (%d)\n", dwRasStatus, cConnections)); }
// Delete the RASCONN structure.
delete pRasConn;
} // if (bRasInstalled)
SensPrintA(SENS_INFO, ("EvaluateWanConnectivity() returning %s, GLE of %d\n", bWanAlive ? "TRUE" : "FALSE", *lpdwLastError));
if (InterlockedExchange(&gdwWANState, bWanAlive) != bWanAlive) { //
// WAN Connectivity state changed.
//
BOOL bSuccess; DWORD dwActiveWanInterfaceSpeed; DWORD dwLastError; SENSEVENT_NETALIVE Data;
dwLastError = ERROR_SUCCESS; dwActiveWanInterfaceSpeed = 0x0;
if (bWanAlive) { bSuccess = GetActiveWanInterfaceStatistics( &dwLastError, &dwActiveWanInterfaceSpeed ); #ifdef SENS_NT5
// Will always fire on NT4/Win9x (due to bugs). Can fire on NT5.
SensPrintA(SENS_WARN, ("GetActiveWanInterfaceStatistics() returned" " FALSE, using defaults!\n")); #endif // SENS_NT5
}
Data.eType = SENS_EVENT_NETALIVE; Data.bAlive = bWanAlive; memset(&Data.QocInfo, 0x0, sizeof(QOCINFO)); Data.QocInfo.dwSize = sizeof(QOCINFO); Data.QocInfo.dwFlags = NETWORK_ALIVE_WAN; Data.QocInfo.dwInSpeed = dwActiveWanInterfaceSpeed; Data.QocInfo.dwOutSpeed = dwActiveWanInterfaceSpeed; Data.strConnection = szEntryName;
UpdateSensCache(WAN);
SensFireEvent((PVOID)&Data); }
if (bWanAlive) { InterlockedExchange(&gdwLastWANTime, dwNow); } else { InterlockedExchange(&gdwLastWANTime, 0x0); }
SensPrintA(SENS_INFO, ("RasEventNotifyRoutine(%d) - WAN Time is %d msec\n", dwNow, gdwLastWANTime));
delete szEntryName;
return bWanAlive; }
|