|
|
/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
apiproc.cxx
Abstract:
This file contains the implementations of all the RPC Server Manager routines exported by SENS.
Author:
Gopal Parupudi <GopalP>
[Notes:]
optional-notes
Revision History:
GopalP 10/11/1997 Start.
--*/
#include <precomp.hxx>
#include <notify.h>
error_status_t RPC_IsNetworkAlive( IN handle_t hRpc, OUT LPDWORD lpdwFlags, OUT LPBOOL lpbAlive, OUT LPDWORD lpdwLastError ) /*++
Routine Description:
Get the current Network State that is maintained by this service. If either WAN or LAN connectivity is not present, we try to re-evaluate and update the state, if possible.
Arguments:
hRpc - The RPC Binding handle.
lpdwFlags - The flags indicating which type of network connectivity is present. The possible values are NETWORK_ALIVE_WAN NETWORK_ALIVE_LAN
lpbAlive - Boolean indicating whether the network is alive or not.
lpdwLastError - The out parameter that holds the error code returned from GetLastError() when there is no network connectivity.
Return Value:
RPC_S_OK, normally.
RPC Error, if there is an RPC-related problem.
--*/ { DWORD dwNow; DWORD fNetNature; BOOL bNetAlive; BOOL bLanAlive; BOOL bWanAlive; DWORD dwWanLastError; DWORD dwLanLastError; DWORD dwNetState;
//
// Some basic argument checks
//
if (NULL == lpdwLastError) { return RPC_S_INVALID_ARG; }
if ( (NULL == lpdwFlags) || (NULL == lpbAlive)) { *lpdwLastError = ERROR_INVALID_PARAMETER; return RPC_S_OK; }
*lpdwFlags = 0x0; *lpbAlive = FALSE; *lpdwLastError = ERROR_SUCCESS;
dwNow = GetTickCount(); fNetNature = 0x0; dwNetState = 0; bLanAlive = FALSE; bWanAlive = FALSE; bNetAlive = FALSE;
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
SensPrintA(SENS_INFO, ("RPC_IsNetworkAlive() - Current Statistics" "\n\tLAN State (%s), LAN (%d sec)," "\n\tWAN State (%s) WAN Time (%d sec)\n", gdwLANState ? "TRUE" : "FALSE", (dwNow - gdwLastLANTime)/1000, gdwWANState ? "TRUE" : "FALSE", (dwNow - gdwLastWANTime)/1000) );
#if defined(AOL_PLATFORM)
SensPrintA(SENS_INFO, ("" "\n\tAOL State (%s) AOL Time (%d sec)\n", gdwAOLState ? "TRUE" : "FALSE", (dwNow - gdwLastWANTime)/1000)); #endif // AOL_PLATFORM
//
// First, get information about the WAN
//
if ((dwNow - gdwLastWANTime) > MAX_WAN_INTERVAL) { SensPrintA(SENS_INFO, ("WAN State information expired. Trying again.\n"));
// WAN state is stale, refresh it.
bWanAlive = EvaluateWanConnectivity(&dwWanLastError);
if (bWanAlive) { fNetNature |= NETWORK_ALIVE_WAN; bNetAlive = TRUE; } else { *lpdwLastError = MapLastError(dwWanLastError); } } else { // Return the WAN state.
if (gdwWANState) { fNetNature |= NETWORK_ALIVE_WAN; bNetAlive = TRUE; bWanAlive = TRUE; } }
#if defined(AOL_PLATFORM)
if (bWanAlive && gdwAOLState) { fNetNature |= NETWORK_ALIVE_AOL; } #endif // AOL_PLATFORM
//
// If we can determine both types of connectivity at this stage, return.
//
if ( ((dwNow - gdwLastLANTime) <= MAX_LAN_INTERVAL) && (gdwLANState == TRUE)) { fNetNature |= NETWORK_ALIVE_LAN; bNetAlive = TRUE;
*lpdwFlags = fNetNature; *lpbAlive = bNetAlive; *lpdwLastError = ERROR_SUCCESS;
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
return (RPC_S_OK); }
//
// One of the following is TRUE at this stage.
//
// a. Information about LAN is stale.
// b. Information about LAN is current but there is no LAN connectivity.
// So, we go and check for it again.
//
if (gdwLANState == FALSE) { SensPrintA(SENS_INFO, ("LAN State either stale or there is no connectivity. Trying again.\n")); } else { SensPrintA(SENS_INFO, ("LAN State information expired. Trying again.\n")); }
bLanAlive = EvaluateLanConnectivity(&dwLanLastError); if (bLanAlive) { fNetNature |= NETWORK_ALIVE_LAN; bNetAlive = TRUE; } else { *lpdwLastError = MapLastError(dwLanLastError); }
*lpdwFlags = fNetNature; *lpbAlive = bNetAlive;
if (bNetAlive) { *lpdwLastError = ERROR_SUCCESS; }
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
return (RPC_S_OK); }
error_status_t RPC_IsDestinationReachableW( IN handle_t h, IN wchar_t * lpszDestination, IN OUT LPQOCINFO lpQOCInfo, OUT LPBOOL lpbReachable, OUT LPDWORD lpdwLastError ) /*++
Routine Description:
Check to see if the given destination is reachable. If so, return Quality Of Connection (QOC) information, if necessary.
Arguments:
hRpc - The RPC Binding handle.
lpszDestination - The destination whose reachability is of interest.
lpQOCInfo - Pointer to a buffer that will receive Quality of Connection (QOC) Information. Can be NULL if QOC is not desired.
lpbReachable - Boolean indicating whether the destination is reachable or not.
lpdwLastError - The out parameter that holds the error code returned from GetLastError() when the destination is not reachable.
Notes:
This function does nothing on Win9x platforms. It should never be called on Win9x platforms.
Return Value:
RPC_S_OK, normally.
RPC Error, if there is an RPC-related problem.
--*/ { BOOL bPingStatus; BOOL bFound; DWORD dwStatus; DWORD dwIpAddress; DWORD dwReachGLE; ULONG ulRTT; size_t uiLength;
#if !defined(SENS_CHICAGO)
//
// Some basic argument checks
//
if (NULL == lpdwLastError) { return RPC_S_INVALID_ARG; }
if ( (NULL == lpszDestination) || (NULL == lpbReachable)) { // Not likely.
*lpdwLastError = ERROR_INVALID_PARAMETER; return RPC_S_OK; }
uiLength = wcslen(lpszDestination); if ( (uiLength > MAX_DESTINATION_LENGTH) || (uiLength == 0)) { *lpbReachable = FALSE; *lpdwLastError = ERROR_INVALID_PARAMETER; return RPC_S_OK; }
*lpdwLastError = ERROR_SUCCESS; *lpbReachable = FALSE;
ulRTT = 0; dwStatus = 0; dwIpAddress = 0; dwReachGLE = ERROR_SUCCESS; bPingStatus = FALSE; bFound = FALSE;
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
SensPrint(SENS_INFO, (SENS_STRING("RPC_IsDestinationReachableW(%s, 0x%x) called.\n"), lpszDestination, lpQOCInfo));
dwStatus = ResolveName(lpszDestination, &dwIpAddress);
if (dwStatus) { *lpdwLastError = MapLastError(dwStatus); *lpbReachable = FALSE;
SensPrint(SENS_INFO, (SENS_STRING("The Destination %s cannot be resolved - %d\n"), lpszDestination, dwStatus)); SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
return RPC_S_OK; }
SensPrint(SENS_INFO, (SENS_STRING("Destination \"%s\" is resolved as 0x%x\n"), lpszDestination, dwIpAddress));
bFound = CheckForReachability( dwIpAddress, lpQOCInfo, &dwReachGLE );
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
*lpbReachable = bFound; *lpdwLastError = MapLastError(dwReachGLE);
#endif // SENS_CHICAGO
return RPC_S_OK; }
error_status_t RPC_IsDestinationReachableA( IN handle_t h, IN char * lpszDestination, IN OUT LPQOCINFO lpQOCInfo, OUT LPBOOL lpbReachable, OUT LPDWORD lpdwLastError ) /*++
Routine Description:
Check to see if the given destination is reachable. If so, return Quality Of Connection (QOC) information, if necessary.
Arguments:
hRpc - The RPC Binding handle.
lpszDestination - The destination whose reachability is of interest.
lpQOCInfo - Pointer to a buffer that will receive Quality of Connection (QOC) Information. Can be NULL if QOC is not desired.
lpbReachable - Boolean indicating whether the destination is reachable or not.
lpdwLastError - The out parameter that holds the error code returned from GetLastError() when the destination is not reachable.
Notes:
This function does nothing on NT platforms. It should never be called on NT platforms.
Return Value:
RPC_S_OK, normally.
RPC Error, if there is an RPC-related problem.
--*/ { BOOL bPingStatus; BOOL bFound; DWORD dwStatus; DWORD dwIpAddress; DWORD dwReachGLE; ULONG ulRTT; size_t uiLength;
#if defined(SENS_CHICAGO)
//
// Some basic argument checks
//
if (NULL == lpdwLastError) { return RPC_S_INVALID_ARG; }
if ( (NULL == lpszDestination) || (NULL == lpbReachable)) { // Not likely.
*lpdwLastError = ERROR_INVALID_PARAMETER; return RPC_S_OK; }
uiLength = strlen(lpszDestination); if ( (uiLength > MAX_DESTINATION_LENGTH) || (uiLength == 0)) { *lpbReachable = FALSE; *lpdwLastError = ERROR_INVALID_PARAMETER; return RPC_S_OK; }
*lpdwLastError = ERROR_SUCCESS; *lpbReachable = FALSE;
ulRTT = 0; dwStatus = 0; dwIpAddress = 0; dwReachGLE = ERROR_SUCCESS; bPingStatus = FALSE; bFound = FALSE;
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
SensPrint(SENS_INFO, (SENS_STRING("RPC_IsDestinationReachableA(%s, 0x%x) called.\n"), lpszDestination, lpQOCInfo));
dwStatus = ResolveName(lpszDestination, &dwIpAddress);
if (dwStatus) { *lpdwLastError = MapLastError(dwStatus); *lpbReachable = FALSE;
SensPrint(SENS_INFO, (SENS_STRING("The Destination %s cannot be resolved - %d\n"), lpszDestination, dwStatus)); SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
return RPC_S_OK; }
SensPrint(SENS_INFO, (SENS_STRING("Destination \"%s\" is resolved as 0x%x\n"), lpszDestination, dwIpAddress));
bFound = CheckForReachability( dwIpAddress, lpQOCInfo, &dwReachGLE );
SensPrintA(SENS_INFO, ("--------------------------------------------------------------\n"));
*lpbReachable = bFound; *lpdwLastError = MapLastError(dwReachGLE);
#endif // SENS_CHICAGO
return RPC_S_OK; }
error_status_t RPC_SensNotifyWinlogonEvent( handle_t h, PSENS_NOTIFY_WINLOGON pEvent ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { SENSEVENT_WINLOGON Data;
switch (pEvent->eType) { case SENS_NOTIFY_WINLOGON_LOGON: Data.eType = SENS_EVENT_LOGON; break;
case SENS_NOTIFY_WINLOGON_LOGOFF: Data.eType = SENS_EVENT_LOGOFF; break;
case SENS_NOTIFY_WINLOGON_STARTSHELL: Data.eType = SENS_EVENT_STARTSHELL; break;
case SENS_NOTIFY_WINLOGON_POSTSHELL: Data.eType = SENS_EVENT_POSTSHELL; break;
case SENS_NOTIFY_WINLOGON_SESSION_DISCONNECT: Data.eType = SENS_EVENT_SESSION_DISCONNECT; break;
case SENS_NOTIFY_WINLOGON_SESSION_RECONNECT: Data.eType = SENS_EVENT_SESSION_RECONNECT; break;
case SENS_NOTIFY_WINLOGON_LOCK:
// If already locked, there is nothing to do.
if (TRUE == gdwLocked) { return RPC_S_OK; }
// Update info in cache.
gdwLocked = TRUE; UpdateSensCache(LOCK);
Data.eType = SENS_EVENT_LOCK; break;
case SENS_NOTIFY_WINLOGON_UNLOCK:
// If already unlocked, there is nothing to do.
if (FALSE == gdwLocked) { return RPC_S_OK; }
// Update info in cache.
gdwLocked = FALSE; UpdateSensCache(LOCK);
Data.eType = SENS_EVENT_UNLOCK; break;
case SENS_NOTIFY_WINLOGON_STARTSCREENSAVER: Data.eType = SENS_EVENT_STARTSCREENSAVER; break;
case SENS_NOTIFY_WINLOGON_STOPSCREENSAVER: Data.eType = SENS_EVENT_STOPSCREENSAVER; break;
default: SensPrintA(SENS_WARN, ("BOGUS WINLOGON EVENT\n")); ASSERT(0 && "BOGUS WINLOGON EVENT"); return RPC_S_OK; }
memcpy(&Data.Info, &pEvent->Info, sizeof(WINLOGON_INFO));
//
// PERFORMANCE NOTE:
//
// o We want the Logoff event to be synchronous. That is, until all
// the subscribers to this event are done handling this event,
// System Logoff should not occur.
// o As of today, LCE fires events to the subscribers on the publishers
// thread. If we fire on a threadpool thread, it will release the
// publisher thread which will go and allow System Logoff to continue.
// o This has performance implications. We need to make sure that we
// don't impact System Logoff time when there are no subscriptions
// to this event.
//
if (SENS_EVENT_LOGOFF != Data.eType) { // Queue workitem to threadpool
SensFireEvent(&Data); } else { PVOID pAllocatedData;
pAllocatedData = AllocateEventData(&Data); if (NULL == pAllocatedData) { SensPrintA(SENS_ERR, ("RPC_NotifyWinlogonEvent(): Failed to allocate Event Data!\n")); return (RPC_S_OUT_OF_MEMORY); }
// Synchronously call LCE and then free allocated Data.
SensFireEventHelper(pAllocatedData); }
return (RPC_S_OK); }
error_status_t RPC_SensNotifyRasEvent( handle_t h, PSENS_NOTIFY_RAS pEvent ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { DWORD dwIgnore; SENSEVENT_RAS Data;
switch (pEvent->eType) { case SENS_NOTIFY_RAS_STARTED: Data.eType = SENS_EVENT_RAS_STARTED; break;
case SENS_NOTIFY_RAS_STOPPED: Data.eType = SENS_EVENT_RAS_STOPPED; break;
case SENS_NOTIFY_RAS_CONNECT: Data.eType = SENS_EVENT_RAS_CONNECT; break;
case SENS_NOTIFY_RAS_DISCONNECT: Data.eType = SENS_EVENT_RAS_DISCONNECT; break;
case SENS_NOTIFY_RAS_DISCONNECT_PENDING: Data.eType = SENS_EVENT_RAS_DISCONNECT_PENDING; break;
default: SensPrintA(SENS_WARN, ("\t| BOGUS RAS EVENT - Type is %d\n", pEvent->eType)); return RPC_S_OK; }
Data.hConnection = pEvent->hConnection;
SensFireEvent(&Data);
EvaluateConnectivity(TYPE_WAN);
return (RPC_S_OK); }
error_status_t RPC_SensNotifyNetconEvent( handle_t h, PSENS_NOTIFY_NETCON_P pEvent ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { SENSEVENT_LAN Data;
switch (pEvent->eType) { case SENS_NOTIFY_LAN_CONNECT: Data.eType = SENS_EVENT_LAN_CONNECT; break;
case SENS_NOTIFY_LAN_DISCONNECT: Data.eType = SENS_EVENT_LAN_DISCONNECT; break;
default: SensPrintA(SENS_WARN, ("\t| BOGUS LAN EVENT - Type is %d\n", pEvent->eType)); return RPC_S_OK; }
Data.Name = pEvent->Name; Data.Status = pEvent->Status; Data.Type = pEvent->Type;
// Force a recalculation of LAN Connectivity
gdwLastLANTime -= (MAX_LAN_INTERVAL + 1);
SensFireEvent(&Data);
EvaluateConnectivity(TYPE_LAN);
return (RPC_S_OK); }
DWORD MapLastError( DWORD dwInGLE ) /*++
Routine Description:
This rountine maps the GLEs returned by the SENS Connecitivity engine to GLEs that describe the failure of the SENS APIs more accurately.
Arguments:
dwInGLE - The GLE that needs to be mapped
Return Value:
The mapped (and better) GLE.
--*/ { DWORD dwOutGLE;
switch (dwInGLE) { //
// When IP stack is not present, we typically get these errors.
//
case ERROR_INVALID_FUNCTION: case ERROR_NOT_SUPPORTED: dwOutGLE = ERROR_NO_NETWORK; break;
//
// No mapping by default.
//
default: dwOutGLE = dwInGLE; break;
} // switch
return dwOutGLE; }
|