445 lines
12 KiB
C
445 lines
12 KiB
C
/*******************************************************************/
|
||
/* Copyright(c) 1992 Microsoft Corporation */
|
||
/*******************************************************************/
|
||
|
||
//***
|
||
//
|
||
// Filename: closehnd.c
|
||
//
|
||
// Description: This module contains auxiliary procedures for the
|
||
// supervisor's procedure-driven state machine that
|
||
// handles device closing events.
|
||
//
|
||
// Author: Stefan Solomon (stefans) June 1, 1992.
|
||
//
|
||
//***
|
||
#include "ddm.h"
|
||
#include "handlers.h"
|
||
#include "objects.h"
|
||
#include <raserror.h>
|
||
#include <ddmif.h>
|
||
#include <util.h>
|
||
#include "rasmanif.h"
|
||
#include "isdn.h"
|
||
#include "timer.h"
|
||
#include <ntlsapi.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
|
||
//***
|
||
//
|
||
// Function: DevStartClosing
|
||
//
|
||
// Descr:
|
||
//
|
||
//***
|
||
VOID
|
||
DevStartClosing(
|
||
IN PDEVICE_OBJECT pDeviceObj
|
||
)
|
||
{
|
||
PCONNECTION_OBJECT pConnObj;
|
||
|
||
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
||
"DevStartClosing: Entered, hPort=%d", pDeviceObj->hPort);
|
||
|
||
//
|
||
// Was this a failure for a BAP callback?
|
||
//
|
||
|
||
if ( pDeviceObj->fFlags & DEV_OBJ_BAP_CALLBACK )
|
||
{
|
||
PppDdmBapCallbackResult( pDeviceObj->hBapConnection,
|
||
ERROR_PORT_DISCONNECTED );
|
||
|
||
pDeviceObj->fFlags &= ~DEV_OBJ_BAP_CALLBACK;
|
||
}
|
||
|
||
//
|
||
// If not disconnected, disconnect the line.
|
||
//
|
||
|
||
if( pDeviceObj->ConnectionState != DISCONNECTED )
|
||
{
|
||
if(( gblDDMConfigInfo.pServiceStatus->dwCurrentState ==
|
||
SERVICE_STOP_PENDING) &&
|
||
(!IsPortOwned(pDeviceObj)))
|
||
{
|
||
//
|
||
// RAS service is stopping and we do not own the port
|
||
// so just mark the state as DISCONNECTED
|
||
//
|
||
|
||
pDeviceObj->ConnectionState = DISCONNECTED;
|
||
|
||
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
||
"DevStartClosing:Disconnect not posted for biplx port%d",
|
||
pDeviceObj->hPort);
|
||
}
|
||
else
|
||
{
|
||
RmDisconnect( pDeviceObj );
|
||
}
|
||
}
|
||
|
||
//
|
||
// If we are doing security dialog.
|
||
//
|
||
|
||
if ( pDeviceObj->SecurityState == DEV_OBJ_SECURITY_DIALOG_ACTIVE )
|
||
{
|
||
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
||
"DevStartClosing:Notifying sec. dll to Disconnect");
|
||
|
||
//
|
||
// If this fails then we assume that this port has been cleaned up
|
||
//
|
||
|
||
if ( (*gblDDMConfigInfo.lpfnRasEndSecurityDialog)( pDeviceObj->hPort )
|
||
!= NO_ERROR )
|
||
{
|
||
pDeviceObj->SecurityState = DEV_OBJ_SECURITY_DIALOG_INACTIVE;
|
||
}
|
||
else
|
||
{
|
||
pDeviceObj->SecurityState = DEV_OBJ_SECURITY_DIALOG_STOPPING;
|
||
}
|
||
}
|
||
|
||
//
|
||
// If authentication is active, stop it
|
||
//
|
||
pDeviceObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE);
|
||
|
||
if ( ( pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ) ) != NULL )
|
||
{
|
||
//
|
||
// If our previous state has been active, get the time the user has been
|
||
// active and log the result.
|
||
//
|
||
|
||
if (pDeviceObj->DeviceState == DEV_OBJ_ACTIVE)
|
||
{
|
||
LogConnectionEvent( pConnObj, pDeviceObj );
|
||
}
|
||
}
|
||
|
||
//
|
||
// If receive frame was active, stop it.
|
||
//
|
||
|
||
if ( pDeviceObj->fFlags & DEV_OBJ_RECEIVE_ACTIVE )
|
||
{
|
||
pDeviceObj->fFlags &= (~DEV_OBJ_RECEIVE_ACTIVE );
|
||
}
|
||
|
||
//
|
||
// Stop timers. If no timer active, StopTimer still returns OK
|
||
//
|
||
|
||
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvDiscTimeout );
|
||
|
||
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
|
||
|
||
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvSecurityTimeout );
|
||
|
||
//
|
||
// Finally, change the state to closing
|
||
//
|
||
|
||
pDeviceObj->DeviceState = DEV_OBJ_CLOSING;
|
||
|
||
//
|
||
// If any any resources are still active, closing will have to wait
|
||
// until all resources are released.
|
||
// Check if everything has closed
|
||
//
|
||
|
||
DevCloseComplete( pDeviceObj );
|
||
}
|
||
|
||
//***
|
||
//
|
||
// Function: DevCloseComplete
|
||
//
|
||
// Description: Checks if there are still resources allocated.
|
||
// If all cleaned up goes to next state
|
||
//
|
||
//***
|
||
VOID
|
||
DevCloseComplete(
|
||
IN PDEVICE_OBJECT pDeviceObj
|
||
)
|
||
{
|
||
BOOL fAuthClosed = FALSE;
|
||
BOOL fRecvClosed = FALSE;
|
||
BOOL fConnClosed = FALSE;
|
||
BOOL fSecurityClosed = FALSE;
|
||
BOOL fPppClosed = FALSE;
|
||
PCONNECTION_OBJECT pConnObj = ConnObjGetPointer( pDeviceObj->hConnection );
|
||
|
||
if ( !( pDeviceObj->fFlags & DEV_OBJ_AUTH_ACTIVE ) )
|
||
{
|
||
fAuthClosed = TRUE;
|
||
}
|
||
|
||
if ( !( pDeviceObj->fFlags & DEV_OBJ_RECEIVE_ACTIVE ) )
|
||
{
|
||
fRecvClosed = TRUE;
|
||
}
|
||
|
||
if ( !( pDeviceObj->fFlags & DEV_OBJ_PPP_IS_ACTIVE ) )
|
||
{
|
||
fPppClosed = TRUE;
|
||
}
|
||
|
||
//
|
||
// Was this is the last link in the connection
|
||
//
|
||
|
||
if (pDeviceObj->ConnectionState == DISCONNECTED )
|
||
{
|
||
fConnClosed = TRUE;
|
||
}
|
||
|
||
if (pDeviceObj->SecurityState == DEV_OBJ_SECURITY_DIALOG_INACTIVE )
|
||
{
|
||
fSecurityClosed = TRUE;
|
||
}
|
||
|
||
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
||
"DevCloseComplete:hPort=%d,Auth=%d,Rcv=%d,Conn=%d %d,Sec=%d %d,Ppp=%d",
|
||
pDeviceObj->hPort,
|
||
!fAuthClosed,
|
||
!fRecvClosed,
|
||
pConnObj ? 0 : 1,
|
||
!fConnClosed,
|
||
pDeviceObj->ConnectionState,
|
||
pDeviceObj->SecurityState,
|
||
!fPppClosed );
|
||
|
||
if ( fAuthClosed &&
|
||
fRecvClosed &&
|
||
fConnClosed &&
|
||
fSecurityClosed &&
|
||
fPppClosed )
|
||
{
|
||
//
|
||
// Was this the last link in the bundle? If it was we clean up
|
||
//
|
||
|
||
if ( pConnObj != NULL )
|
||
{
|
||
HPORT hPortConnected;
|
||
|
||
//
|
||
// Remove this link from the connection
|
||
//
|
||
|
||
ConnObjRemoveLink( pDeviceObj->hConnection, pDeviceObj );
|
||
|
||
//
|
||
// If admin module is loaded, notify it of a link disconnection
|
||
//
|
||
|
||
if ( ( pDeviceObj->fFlags & DEV_OBJ_NOTIFY_OF_DISCONNECTION ) &&
|
||
( gblDDMConfigInfo.lpfnRasAdminLinkHangupNotification != NULL))
|
||
{
|
||
RAS_PORT_0 RasPort0;
|
||
RAS_PORT_1 RasPort1;
|
||
VOID (*MprAdminLinkHangupNotification)(RAS_PORT_0 *,
|
||
RAS_PORT_1*);
|
||
|
||
if ((GetRasPort0Data(pDeviceObj,&RasPort0) == NO_ERROR)
|
||
&&
|
||
(GetRasPort1Data(pDeviceObj,&RasPort1) == NO_ERROR))
|
||
{
|
||
MprAdminLinkHangupNotification =
|
||
(VOID (*)( RAS_PORT_0 *, RAS_PORT_1 * ))
|
||
gblDDMConfigInfo.lpfnRasAdminLinkHangupNotification;
|
||
|
||
MprAdminLinkHangupNotification( &RasPort0, &RasPort1 );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Confirm with RASMAN that there are no more ports in this
|
||
// bundle. It may be that there is one but DDM has not gotten
|
||
// a NewLink message from PPP yet.
|
||
//
|
||
|
||
if ( ( RasBundleGetPort( NULL, pConnObj->hConnection,
|
||
&hPortConnected ) != NO_ERROR ) &&
|
||
( pConnObj->cActiveDevices == 0 ) )
|
||
{
|
||
//
|
||
// If admin module is loaded, notify it of disconnection
|
||
//
|
||
|
||
if ( pConnObj->fFlags & CONN_OBJ_NOTIFY_OF_DISCONNECTION )
|
||
{
|
||
ConnectionHangupNotification( pConnObj );
|
||
}
|
||
|
||
//
|
||
// Remove the interface object if it is not a full router.
|
||
//
|
||
|
||
if ( pConnObj->hDIMInterface != INVALID_HANDLE_VALUE )
|
||
{
|
||
ROUTER_INTERFACE_OBJECT * pIfObject;
|
||
|
||
EnterCriticalSection(
|
||
&(gblpInterfaceTable->CriticalSection));
|
||
|
||
pIfObject = IfObjectGetPointer( pConnObj->hDIMInterface );
|
||
|
||
if ( pIfObject != NULL )
|
||
{
|
||
IfObjectDisconnected( pIfObject );
|
||
|
||
if ( pIfObject->IfType != ROUTER_IF_TYPE_FULL_ROUTER )
|
||
{
|
||
IfObjectDeleteInterface( pIfObject );
|
||
|
||
IfObjectRemove( pConnObj->hDIMInterface );
|
||
}
|
||
}
|
||
|
||
LeaveCriticalSection(
|
||
&(gblpInterfaceTable->CriticalSection));
|
||
}
|
||
|
||
//
|
||
// Remove the Connection Object
|
||
//
|
||
|
||
ConnObjRemoveAndDeAllocate( pDeviceObj->hConnection );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Release the media (if any) used by this port
|
||
//
|
||
|
||
if ( pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE )
|
||
{
|
||
pDeviceObj->fFlags &= ~DEV_OBJ_MARKED_AS_INUSE;
|
||
|
||
gblDeviceTable.NumDevicesInUse--;
|
||
|
||
//
|
||
// Increase media count for this device
|
||
//
|
||
|
||
if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
|
||
{
|
||
MediaObjAddToTable( pDeviceObj->wchDeviceType );
|
||
}
|
||
|
||
//
|
||
// Possibly need to notify router managers of reachability
|
||
// change
|
||
//
|
||
|
||
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
|
||
IfObjectNotifyAllOfReachabilityChange( TRUE,
|
||
INTERFACE_OUT_OF_RESOURCES );
|
||
|
||
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
|
||
}
|
||
|
||
//
|
||
// Release any RasMan buffers if we have allocated them
|
||
//
|
||
|
||
if ( pDeviceObj->pRasmanSendBuffer != NULL )
|
||
{
|
||
RasFreeBuffer( pDeviceObj->pRasmanSendBuffer );
|
||
pDeviceObj->pRasmanSendBuffer = NULL;
|
||
}
|
||
|
||
if ( pDeviceObj->pRasmanRecvBuffer != NULL )
|
||
{
|
||
RasFreeBuffer( pDeviceObj->pRasmanRecvBuffer );
|
||
pDeviceObj->pRasmanRecvBuffer = NULL;
|
||
}
|
||
|
||
RasSetRouterUsage( pDeviceObj->hPort, FALSE );
|
||
|
||
//
|
||
// If we have gotten a PnP remove message, then discard this port
|
||
//
|
||
|
||
if ( pDeviceObj->fFlags & DEV_OBJ_PNP_DELETE )
|
||
{
|
||
//
|
||
// We do this in a worker thread since this thread may be
|
||
// walking the device list, hence we cannot modify it here.
|
||
//
|
||
|
||
RtlQueueWorkItem( DeviceObjRemoveFromTable,
|
||
pDeviceObj->hPort,
|
||
WT_EXECUTEDEFAULT );
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Reset fields in this port device
|
||
//
|
||
|
||
pDeviceObj->hConnection = (HCONN)INVALID_HANDLE_VALUE;
|
||
pDeviceObj->wchUserName[0] = (WCHAR)NULL;
|
||
pDeviceObj->wchDomainName[0] = (WCHAR)NULL;
|
||
pDeviceObj->wchCallbackNumber[0] = (WCHAR)NULL;
|
||
pDeviceObj->fFlags &= (~DEV_OBJ_IS_PPP);
|
||
}
|
||
|
||
//
|
||
// switch to next state (based on the present service state)
|
||
//
|
||
|
||
switch ( gblDDMConfigInfo.pServiceStatus->dwCurrentState )
|
||
{
|
||
case SERVICE_RUNNING:
|
||
case SERVICE_START_PENDING:
|
||
|
||
//
|
||
// post a listen on the device
|
||
//
|
||
|
||
pDeviceObj->DeviceState = DEV_OBJ_LISTENING;
|
||
RmListen(pDeviceObj);
|
||
break;
|
||
|
||
case SERVICE_PAUSED:
|
||
|
||
//
|
||
// wait for the service to be running again
|
||
//
|
||
|
||
pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
|
||
break;
|
||
|
||
case SERVICE_STOP_PENDING:
|
||
|
||
//
|
||
// this device has terminated. Announce the closure to
|
||
// the central stop service coordinator
|
||
//
|
||
|
||
pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
|
||
DDMServiceStopComplete();
|
||
break;
|
||
|
||
default:
|
||
|
||
RTASSERT(FALSE);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|