976 lines
22 KiB
C
976 lines
22 KiB
C
/*******************************************************************/
|
||
/* Copyright(c) 1992 Microsoft Corporation */
|
||
/*******************************************************************/
|
||
|
||
|
||
//***
|
||
//
|
||
// Filename: timehand.c
|
||
//
|
||
// Description: This module contains the procedures for the supervisor's
|
||
// procedure-driven state machine that handles timer events.
|
||
//
|
||
// Author: Stefan Solomon (stefans) May 26, 1992.
|
||
//
|
||
//
|
||
//***
|
||
#include "ddm.h"
|
||
#include "handlers.h"
|
||
#include "timer.h"
|
||
#include "objects.h"
|
||
#include "util.h"
|
||
#include "routerif.h"
|
||
#include "rasapiif.h"
|
||
#include <raserror.h>
|
||
#include <serial.h>
|
||
#include "rasmanif.h"
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <memory.h>
|
||
|
||
//
|
||
// Defines a list of blocks of time.
|
||
//
|
||
// The time block is expressed as a pair as follows:
|
||
// <offset from midnight sunday, length>
|
||
//
|
||
// For example, the block of time from 7:00a to 8:30a on Monday
|
||
// would be
|
||
// <24*60+7*60, 90> or <1860, 90>
|
||
//
|
||
//
|
||
typedef struct _MPR_TIME_BLOCK
|
||
{
|
||
DWORD dwTime; // Time of day expressed as # of mins since 12:00a
|
||
DWORD dwLen; // # of minutes in this time block
|
||
} MPR_TIME_BLOCK;
|
||
|
||
//
|
||
// Amount by which resizable array grows in TbCreateList
|
||
//
|
||
#define TB_GROW 30
|
||
#define TBDIGIT(_x) ((_x) - L'0')
|
||
|
||
//
|
||
// Local prototypes
|
||
//
|
||
PVOID
|
||
TbAlloc(
|
||
IN DWORD dwSize,
|
||
IN BOOL bZero);
|
||
|
||
VOID
|
||
TbFree(
|
||
IN PVOID pvData);
|
||
|
||
DWORD
|
||
TbCreateList(
|
||
IN PWCHAR pszBlocks,
|
||
OUT MPR_TIME_BLOCK** ppBlocks,
|
||
OUT LPDWORD lpdwCount);
|
||
|
||
DWORD
|
||
TbCleanupList(
|
||
IN MPR_TIME_BLOCK* pList);
|
||
|
||
DWORD
|
||
TbBlockFromString(
|
||
IN PWCHAR pszBlock,
|
||
IN DWORD dwDay,
|
||
OUT MPR_TIME_BLOCK* pBlock);
|
||
|
||
DWORD
|
||
TbPrintBlock(
|
||
IN MPR_TIME_BLOCK* pBlock);
|
||
|
||
//
|
||
// Common allocation for Tb* functions. Will zero
|
||
// memory if bZero is set.
|
||
//
|
||
PVOID
|
||
TbAlloc(
|
||
IN DWORD dwSize,
|
||
IN BOOL bZero)
|
||
{
|
||
return LOCAL_ALLOC(0, dwSize);
|
||
}
|
||
|
||
//
|
||
// Common free for Tb* functions
|
||
//
|
||
VOID
|
||
TbFree(
|
||
IN PVOID pvData)
|
||
{
|
||
LOCAL_FREE(pvData);
|
||
}
|
||
|
||
//
|
||
// Translates a multi-sz string containing time blocks into
|
||
// a MPR_TIME_BLOCK_LIST
|
||
//
|
||
DWORD
|
||
TbCreateList(
|
||
IN PWCHAR pszBlocks,
|
||
OUT MPR_TIME_BLOCK** ppBlocks,
|
||
OUT LPDWORD lpdwCount)
|
||
{
|
||
DWORD dwErr = NO_ERROR, dwDay = 0, i = 0, dwTot = 0;
|
||
MPR_TIME_BLOCK* pBlocks = NULL, *pTemp = NULL;
|
||
PWCHAR pszCurBlock = NULL, pszStart, pszEnd;
|
||
|
||
// Initailze
|
||
//
|
||
*ppBlocks = NULL;
|
||
*lpdwCount = 0;
|
||
pszCurBlock = pszBlocks;
|
||
|
||
while (pszCurBlock && *pszCurBlock)
|
||
{
|
||
// Calculate the day indicated in the current block
|
||
//
|
||
// pszCurBlock = "d hh:mm-hh:mm hh:mm-hh:mm ..."
|
||
//
|
||
if (! iswdigit(*pszCurBlock))
|
||
{
|
||
dwErr = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
}
|
||
dwDay = *pszCurBlock - L'0';
|
||
|
||
// Advance past the day portion of the line to the
|
||
// timeblock portion
|
||
//
|
||
if (pszStart = wcsstr(pszCurBlock, L" "))
|
||
{
|
||
pszStart++;
|
||
|
||
// Loop through the blocks in this line (separated by spaces).
|
||
//
|
||
// pszStart = "hh:mm-hh:mm hh:mm-hh:mm ..."
|
||
//
|
||
while (TRUE)
|
||
{
|
||
// Parse out the current time block
|
||
// hh:mm-hh:mm
|
||
//
|
||
pszEnd = wcsstr(pszStart, L" ");
|
||
if (pszEnd)
|
||
{
|
||
*pszEnd = L'\0';
|
||
}
|
||
|
||
// Resize the array if needed
|
||
//
|
||
if (i >= dwTot)
|
||
{
|
||
dwTot += TB_GROW;
|
||
pTemp = (MPR_TIME_BLOCK*)
|
||
TbAlloc(dwTot * sizeof(MPR_TIME_BLOCK), TRUE);
|
||
if (pTemp == NULL)
|
||
{
|
||
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
break;
|
||
}
|
||
if (dwTot - TB_GROW != 0)
|
||
{
|
||
CopyMemory(
|
||
pTemp,
|
||
pBlocks,
|
||
sizeof(MPR_TIME_BLOCK) * (dwTot - TB_GROW));
|
||
}
|
||
|
||
TbFree(pBlocks);
|
||
pBlocks = pTemp;
|
||
}
|
||
|
||
// Generate the current time block
|
||
//
|
||
dwErr = TbBlockFromString(pszStart, dwDay, &pBlocks[i++]);
|
||
if (dwErr != NO_ERROR)
|
||
{
|
||
break;
|
||
}
|
||
|
||
// Undo any changes made to the string and
|
||
// advance to the next time block
|
||
//
|
||
if (pszEnd)
|
||
{
|
||
*pszEnd = L' ';
|
||
pszStart = pszEnd + 1;
|
||
}
|
||
else
|
||
{
|
||
// Exit the loop successfully
|
||
break;
|
||
}
|
||
}
|
||
if (dwErr != NO_ERROR)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dwErr = ERROR_INVALID_PARAMETER;
|
||
break;
|
||
}
|
||
|
||
// Increment the block of time in the multi-sz
|
||
//
|
||
pszCurBlock += wcslen(pszCurBlock) + 1;
|
||
}
|
||
|
||
// Cleanup
|
||
{
|
||
if (dwErr != NO_ERROR)
|
||
{
|
||
TbCleanupList(*ppBlocks);
|
||
*ppBlocks = NULL;
|
||
}
|
||
else
|
||
{
|
||
*ppBlocks = pBlocks;
|
||
*lpdwCount = i;
|
||
}
|
||
}
|
||
|
||
return dwErr;
|
||
}
|
||
|
||
//
|
||
// Cleans up the given series of time blocks.
|
||
//
|
||
DWORD
|
||
TbCleanupList(
|
||
IN MPR_TIME_BLOCK* pList)
|
||
{
|
||
TbFree(pList);
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
//
|
||
// Creates a time block based on a string which must
|
||
// be in the form "hh:mm-hh:mm".
|
||
//
|
||
DWORD
|
||
TbBlockFromString(
|
||
IN PWCHAR pszBlock,
|
||
IN DWORD dwDay,
|
||
OUT MPR_TIME_BLOCK* pBlock)
|
||
{
|
||
DWORD dwErr = NO_ERROR, dwEndTime = 0;
|
||
|
||
// Block must be in format:
|
||
// "hh:mm-hh:mm"
|
||
//
|
||
if ((wcslen(pszBlock) != 11) ||
|
||
(! iswdigit(pszBlock[0])) ||
|
||
(! iswdigit(pszBlock[1])) ||
|
||
(pszBlock[2] != L':') ||
|
||
(! iswdigit(pszBlock[3])) ||
|
||
(! iswdigit(pszBlock[4])) ||
|
||
(pszBlock[5] != L'-') ||
|
||
(! iswdigit(pszBlock[6])) ||
|
||
(! iswdigit(pszBlock[7])) ||
|
||
(pszBlock[8] != L':') ||
|
||
(! iswdigit(pszBlock[9])) ||
|
||
(! iswdigit(pszBlock[10]))
|
||
)
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
// Assign the time values to the block
|
||
//
|
||
pBlock->dwTime =
|
||
(((TBDIGIT(pszBlock[0]) * 10) + TBDIGIT(pszBlock[1])) * 60) + // hrs
|
||
((TBDIGIT(pszBlock[3]) * 10) + TBDIGIT(pszBlock[4])) + // mns
|
||
(dwDay * 24 * 60); // dys
|
||
|
||
dwEndTime =
|
||
(((TBDIGIT(pszBlock[6]) * 10) + TBDIGIT(pszBlock[7])) * 60) + // hrs
|
||
((TBDIGIT(pszBlock[9]) * 10) + TBDIGIT(pszBlock[10])) + // mns
|
||
(dwDay * 24 * 60); // dys
|
||
|
||
pBlock ->dwLen = dwEndTime - pBlock->dwTime;
|
||
|
||
return dwErr;
|
||
}
|
||
|
||
//
|
||
// Finds a time block that matches the given time.
|
||
//
|
||
// Parameters:
|
||
// pList = list of time blocks to search
|
||
// dwTime = time to search for (mins since midnight sunday)
|
||
// ppBlock = the block that matched
|
||
// pbFound = returned TRUE if dwTime lies within ppBlock.
|
||
// returned FALSE if ppBlock is the next time block in pList
|
||
// that occurs after dwTime.
|
||
//
|
||
DWORD
|
||
TbSearchList(
|
||
IN MPR_TIME_BLOCK* pList,
|
||
IN DWORD dwCount,
|
||
IN DWORD dwTime,
|
||
OUT MPR_TIME_BLOCK** ppBlock,
|
||
OUT PBOOL pbFound)
|
||
{
|
||
DWORD dwErr = NO_ERROR;
|
||
DWORD i = 0;
|
||
|
||
// Initialize
|
||
//
|
||
*pbFound = FALSE;
|
||
*ppBlock = NULL;
|
||
|
||
// Loop through the list looking for a block with
|
||
// a time less than ours.
|
||
//
|
||
for (i = 0; (i < dwCount) && (dwTime >= pList[i].dwTime); i++);
|
||
i--;
|
||
|
||
// If we fall within the current block then we're
|
||
// done.
|
||
//
|
||
if ((dwTime >= pList[i].dwTime) &&
|
||
(dwTime - pList[i].dwTime <= pList[i].dwLen))
|
||
{
|
||
*pbFound = TRUE;
|
||
*ppBlock = &pList[i];
|
||
}
|
||
|
||
// Otherwise, we don't fall within any block. Show the next block
|
||
// that we qualify for (wrapping around as needed)
|
||
//
|
||
else
|
||
{
|
||
*pbFound = FALSE;
|
||
*ppBlock = &pList[(i == dwCount-1) ? 0 : i+1];
|
||
}
|
||
|
||
return dwErr;
|
||
}
|
||
|
||
//
|
||
// Traces a block for debugging purposes
|
||
//
|
||
DWORD
|
||
TbTraceBlock(
|
||
IN MPR_TIME_BLOCK* pBlock)
|
||
{
|
||
DWORD dwTime, dwDay;
|
||
|
||
dwDay = pBlock->dwTime / (24*60);
|
||
dwTime = pBlock->dwTime - (dwDay * (24*60));
|
||
DDMTRACE5(
|
||
"Time Block: %d, %02d:%02d-%02d:%02d\n",
|
||
dwDay,
|
||
dwTime / 60,
|
||
dwTime % 60,
|
||
(dwTime + pBlock->dwLen) / 60,
|
||
(dwTime + pBlock->dwLen) % 60);
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
|
||
//***
|
||
//
|
||
// Function: TimerHandler
|
||
//
|
||
// Descr:
|
||
//
|
||
//***
|
||
VOID
|
||
TimerHandler(
|
||
VOID
|
||
)
|
||
{
|
||
//
|
||
// call our timer
|
||
//
|
||
|
||
TimerQTick();
|
||
|
||
//
|
||
// increment the system timer
|
||
//
|
||
|
||
gblDDMConfigInfo.dwSystemTime++;
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AnnouncePresenceHandler
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description:
|
||
//
|
||
/*
|
||
VOID
|
||
AnnouncePresenceHandler(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
AnnouncePresence();
|
||
|
||
TimerQInsert( NULL,
|
||
gblDDMConfigInfo.dwAnnouncePresenceTimer,
|
||
AnnouncePresenceHandler );
|
||
}
|
||
*/
|
||
|
||
//***
|
||
//
|
||
// Function: SvHwErrDelayCompleted
|
||
//
|
||
// Descr: Tries to repost a listen on the specified port.
|
||
//
|
||
//***
|
||
VOID
|
||
SvHwErrDelayCompleted(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
PDEVICE_OBJECT pDeviceObj;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
|
||
|
||
if ( pDeviceObj == NULL )
|
||
{
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
return;
|
||
}
|
||
|
||
if (pDeviceObj->DeviceState == DEV_OBJ_HW_FAILURE)
|
||
{
|
||
DDMTRACE1( "SvHwErrDelayCompleted: reposting listen for hPort%d\n",
|
||
pDeviceObj->hPort);
|
||
|
||
pDeviceObj->DeviceState = DEV_OBJ_LISTENING;
|
||
|
||
RmListen(pDeviceObj);
|
||
}
|
||
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: SvCbDelayCompleted
|
||
//
|
||
// Descr: Tries to connect on the specified port.
|
||
//
|
||
//***
|
||
VOID
|
||
SvCbDelayCompleted(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
CHAR chCallbackNumber[MAX_PHONE_NUMBER_LEN+1];
|
||
PDEVICE_OBJECT pDeviceObj;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
|
||
|
||
if ( pDeviceObj == NULL )
|
||
{
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
return;
|
||
}
|
||
|
||
WideCharToMultiByte( CP_ACP,
|
||
0,
|
||
pDeviceObj->wchCallbackNumber,
|
||
-1,
|
||
chCallbackNumber,
|
||
sizeof( chCallbackNumber ),
|
||
NULL,
|
||
NULL );
|
||
|
||
DDMTRACE1( "SvCbDelayCmpleted:Entered, hPort=%d\n",pDeviceObj->hPort );
|
||
|
||
if (pDeviceObj->DeviceState == DEV_OBJ_CALLBACK_DISCONNECTED)
|
||
{
|
||
pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_CONNECTING;
|
||
RmConnect(pDeviceObj, chCallbackNumber);
|
||
}
|
||
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: SvAuthTimeout
|
||
//
|
||
// Descr: Disconnects the remote client and stops the authentication
|
||
//
|
||
//
|
||
VOID
|
||
SvAuthTimeout(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
LPWSTR portnamep;
|
||
PDEVICE_OBJECT pDeviceObj;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
|
||
|
||
if ( pDeviceObj == NULL )
|
||
{
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
return;
|
||
}
|
||
|
||
DDMTRACE1( "SvAuthTimeout: Entered, hPort=%d", pDeviceObj->hPort);
|
||
|
||
portnamep = pDeviceObj->wchPortName;
|
||
|
||
DDMLogWarning( ROUTERLOG_AUTH_TIMEOUT, 1, &portnamep );
|
||
|
||
//
|
||
// stop everything and go closing
|
||
//
|
||
|
||
DevStartClosing( pDeviceObj );
|
||
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: SvDiscTimeout
|
||
//
|
||
// Descr: disconnects remote client if it has not done it itself
|
||
//
|
||
//
|
||
VOID
|
||
SvDiscTimeout(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
PDEVICE_OBJECT pDeviceObj;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
|
||
|
||
if ( pDeviceObj == NULL )
|
||
{
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
return;
|
||
}
|
||
|
||
DDMTRACE1( "SvDiscTimeout: Entered, hPort=%d", pDeviceObj->hPort );
|
||
|
||
switch (pDeviceObj->DeviceState)
|
||
{
|
||
case DEV_OBJ_CALLBACK_DISCONNECTING:
|
||
|
||
RmDisconnect(pDeviceObj);
|
||
break;
|
||
|
||
case DEV_OBJ_AUTH_IS_ACTIVE:
|
||
|
||
DevStartClosing(pDeviceObj);
|
||
break;
|
||
|
||
default:
|
||
|
||
break;
|
||
}
|
||
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: SvSecurityTimeout
|
||
//
|
||
// Descr: disconnects the connection because the 3rd party security DLL
|
||
// did not complete in time.
|
||
//
|
||
//***
|
||
VOID
|
||
SvSecurityTimeout(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
LPWSTR portnamep;
|
||
PDEVICE_OBJECT pDeviceObj;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
pDeviceObj = DeviceObjGetPointer( (HPORT)hObject );
|
||
|
||
if ( pDeviceObj == NULL )
|
||
{
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
return;
|
||
}
|
||
|
||
DDMTRACE1( "SvSecurityTimeout: Entered,hPort=%d",pDeviceObj->hPort);
|
||
|
||
portnamep = pDeviceObj->wchPortName;
|
||
|
||
DDMLogWarning( ROUTERLOG_AUTH_TIMEOUT, 1, &portnamep );
|
||
|
||
//
|
||
// stop everything and go closing
|
||
//
|
||
|
||
DevStartClosing(pDeviceObj);
|
||
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: ReConnectInterface
|
||
//
|
||
// Description: Will try to reconnect an interface.
|
||
//
|
||
//***
|
||
VOID
|
||
ReConnectInterface(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
ROUTER_INTERFACE_OBJECT * pIfObject;
|
||
DWORD dwRetCode = NO_ERROR;
|
||
|
||
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
do
|
||
{
|
||
pIfObject = IfObjectGetPointer( hObject );
|
||
|
||
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
|
||
{
|
||
break;
|
||
}
|
||
|
||
if ( pIfObject->State != RISTATE_CONNECTING )
|
||
{
|
||
break;
|
||
}
|
||
|
||
dwRetCode = RasConnectionInitiate( pIfObject, TRUE );
|
||
|
||
DDMTRACE2( "ReConnectInterface: To interface %ws returned %d",
|
||
pIfObject->lpwsInterfaceName, dwRetCode );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
IfObjectDisconnected( pIfObject );
|
||
}
|
||
|
||
}while( FALSE );
|
||
|
||
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
||
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
LPWSTR lpwsAudit[1];
|
||
|
||
lpwsAudit[0] = pIfObject->lpwsInterfaceName;
|
||
|
||
DDMLogErrorString(ROUTERLOG_CONNECTION_FAILURE,1,lpwsAudit,dwRetCode,1);
|
||
}
|
||
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: MarkInterfaceAsReachable
|
||
//
|
||
// Description: Will mark an interface as reachable.
|
||
//
|
||
//***
|
||
VOID
|
||
MarkInterfaceAsReachable(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
ROUTER_INTERFACE_OBJECT * pIfObject;
|
||
|
||
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
do
|
||
{
|
||
pIfObject = IfObjectGetPointer( hObject );
|
||
|
||
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
|
||
{
|
||
break;
|
||
}
|
||
|
||
pIfObject->fFlags &= ~IFFLAG_CONNECTION_FAILURE;
|
||
|
||
IfObjectNotifyOfReachabilityChange( pIfObject,
|
||
TRUE,
|
||
INTERFACE_CONNECTION_FAILURE );
|
||
|
||
pIfObject->dwLastError = NO_ERROR;
|
||
|
||
}while( FALSE );
|
||
|
||
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: ReConnectPersistentInterface
|
||
//
|
||
// Returns: None
|
||
//
|
||
// Description: Will insert an event in the timer Q that will reconnect this
|
||
// interface.
|
||
//
|
||
VOID
|
||
ReConnectPersistentInterface(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
ROUTER_INTERFACE_OBJECT * pIfObject;
|
||
DWORD dwRetCode;
|
||
|
||
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
do
|
||
{
|
||
pIfObject = IfObjectGetPointer( hObject );
|
||
|
||
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
|
||
{
|
||
break;
|
||
}
|
||
|
||
if ( pIfObject->State != RISTATE_DISCONNECTED )
|
||
{
|
||
break;
|
||
}
|
||
|
||
dwRetCode = RasConnectionInitiate( pIfObject, FALSE );
|
||
|
||
DDMTRACE2( "ReConnect to persistent interface %ws returned %d",
|
||
pIfObject->lpwsInterfaceName, dwRetCode );
|
||
|
||
}while( FALSE );
|
||
|
||
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: SetDialoutHoursRestriction
|
||
//
|
||
// Returns: NO_ERROR - Success
|
||
// Non-zero returns - Failure
|
||
//
|
||
// Description:
|
||
//
|
||
VOID
|
||
SetDialoutHoursRestriction(
|
||
IN HANDLE hObject
|
||
)
|
||
{
|
||
ROUTER_INTERFACE_OBJECT * pIfObject;
|
||
SYSTEMTIME CurrentTime;
|
||
MPR_TIME_BLOCK* pBlocks = NULL, *pTimeBlock = NULL;
|
||
DWORD dwRetCode = NO_ERROR, dwCount, dwTime;
|
||
DWORD dwTimer, dwBlDay;
|
||
BOOL bFound = FALSE;
|
||
|
||
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
do
|
||
{
|
||
pIfObject = IfObjectGetPointer( hObject );
|
||
|
||
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
|
||
{
|
||
dwRetCode = ERROR_CAN_NOT_COMPLETE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Null dialout hours restriction is interpreted as
|
||
// 'always allow'.
|
||
//
|
||
|
||
if (pIfObject->lpwsDialoutHoursRestriction == NULL)
|
||
{
|
||
pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
|
||
DDMTRACE("Dialout hours restriction off forever.");
|
||
dwRetCode = NO_ERROR;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Generate the list of time blocks based on the current
|
||
// multisz
|
||
//
|
||
|
||
dwRetCode = TbCreateList(
|
||
pIfObject->lpwsDialoutHoursRestriction,
|
||
&pBlocks,
|
||
&dwCount);
|
||
if (dwRetCode != NO_ERROR)
|
||
{
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If an empty list was created, then all hours were
|
||
// specified as deny. Mark the interface unreachable
|
||
// and set ourselves to wake up and check things later.
|
||
//
|
||
|
||
if ((dwCount == 0) || (pBlocks == NULL))
|
||
{
|
||
pIfObject->fFlags |= IFFLAG_DIALOUT_HOURS_RESTRICTION;
|
||
DDMTRACE("Dialout hours restriction on forever.");
|
||
dwRetCode = NO_ERROR;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Get the current time
|
||
//
|
||
|
||
GetLocalTime( &CurrentTime );
|
||
|
||
//
|
||
// Convert the current time into an offset in
|
||
// minutes from midnight, sunday.
|
||
//
|
||
|
||
dwTime = (DWORD)
|
||
( ( CurrentTime.wDayOfWeek * 24 * 60 ) +
|
||
( CurrentTime.wHour * 60 ) +
|
||
CurrentTime.wMinute );
|
||
|
||
//
|
||
// Search for the current time in the list of available times.
|
||
//
|
||
|
||
dwRetCode = TbSearchList(
|
||
pBlocks,
|
||
dwCount,
|
||
dwTime,
|
||
&pTimeBlock,
|
||
&bFound);
|
||
if (dwRetCode != NO_ERROR)
|
||
{
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If we fell within one of the blocks, set the timer
|
||
// to go off after this block completes.
|
||
//
|
||
|
||
if (bFound)
|
||
{
|
||
dwTimer = ((pTimeBlock->dwTime + pTimeBlock->dwLen) - dwTime) + 1;
|
||
|
||
pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
|
||
|
||
DDMTRACE1("Dialout hours restriction off for %d mins", dwTimer);
|
||
TbTraceBlock(pTimeBlock);
|
||
}
|
||
|
||
//
|
||
// If we didn't fall within one of the blocks, set the timer
|
||
// to go off when the next block begins
|
||
//
|
||
|
||
else
|
||
{
|
||
//
|
||
// Check for week wrap around (i.e. today is saturday, next
|
||
// block is sunday).
|
||
//
|
||
|
||
dwBlDay = (pTimeBlock->dwTime / (24*60));
|
||
|
||
//
|
||
// If there's no week wrap around, calculation of timer
|
||
// is trivial.
|
||
//
|
||
|
||
if ((DWORD)CurrentTime.wDayOfWeek <= dwBlDay)
|
||
{
|
||
dwTimer = pTimeBlock->dwTime - dwTime;
|
||
}
|
||
|
||
//
|
||
// Otherwise, calculate the timer by adding one week to the
|
||
// start of the next time block.
|
||
//
|
||
|
||
else
|
||
{
|
||
dwTimer = (pTimeBlock->dwTime + (7*24*60)) - dwTime;
|
||
}
|
||
|
||
pIfObject->fFlags |= IFFLAG_DIALOUT_HOURS_RESTRICTION;
|
||
|
||
DDMTRACE1("Dialout hours restriction on for %d mins", dwTimer);
|
||
TbTraceBlock(pTimeBlock);
|
||
}
|
||
|
||
//
|
||
// Set the timer
|
||
//
|
||
|
||
TimerQInsert(
|
||
pIfObject->hDIMInterface,
|
||
dwTimer * 60,
|
||
SetDialoutHoursRestriction );
|
||
|
||
} while (FALSE);
|
||
|
||
if (pIfObject)
|
||
{
|
||
if ( dwRetCode != NO_ERROR )
|
||
{
|
||
//
|
||
// Do not set any restriction if the string is invalid
|
||
//
|
||
|
||
pIfObject->fFlags &= ~IFFLAG_DIALOUT_HOURS_RESTRICTION;
|
||
}
|
||
|
||
IfObjectNotifyOfReachabilityChange(
|
||
pIfObject,
|
||
!( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ),
|
||
INTERFACE_DIALOUT_HOURS_RESTRICTION );
|
||
}
|
||
|
||
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
// Cleanup
|
||
if (pBlocks)
|
||
{
|
||
TbCleanupList(pBlocks);
|
||
}
|
||
}
|
||
|
||
|