Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

295 lines
7.6 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: A I C . C P P
//
// Contents: Notification support for active inbound ras connections.
//
// Notes:
//
// Author: shaunco 24 Feb 1998
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "aic.h"
#include "conman.h"
#include "mprapi.h"
#include "ncmisc.h"
#include "nmbase.h"
#include <raserror.h>
ASSERTDATA;
// This is the global data representing active inbound ras connections.
//
struct ACTIVE_INBOUND_RAS_CONNECTIONS
{
// This is set after calling AicInitialize.
//
BOOL fInitialized;
// This critical section protects reading and writing to members of
// this structure.
//
CRITICAL_SECTION critsec;
// This is the array and count of active ras connections.
//
// Note: (shaunco) 28 Apr 1998: RASSRVCONN is too big to keep an
// array off. We'll have to roll our own structure and keep what's
// important.
// RASSRVCONN* aRasConn;
// DWORD cRasConn;
// This is the event handle that is signled when a connection is
// connected or disconnected.
//
HANDLE hEvent;
// This is the wait handle returned from RtlRegisterWait.
//
HANDLE hWait;
// This is set after the first call to HrAicEnsureCachedAndListening.
//
BOOL fCachedAndListening;
};
ACTIVE_INBOUND_RAS_CONNECTIONS g_Aic = { 0 };
//+---------------------------------------------------------------------------
//
// Function: AicInitialize
//
// Purpose: Initialize this module for use.
//
// Arguments:
// (none)
//
// Returns: nothing
//
// Author: shaunco 24 Feb 1998
//
// Notes: This can only be called once. It must be called before
// any other Aic* API can be called.
//
VOID
AicInitialize ()
{
Assert (!g_Aic.fInitialized);
InitializeCriticalSection (&g_Aic.critsec);
g_Aic.fInitialized = TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: AicUninitialize
//
// Purpose: Uninitialize this module.
//
// Arguments:
// (none)
//
// Returns: nothing
//
// Author: shaunco 24 Feb 1998
//
// Notes: This can only be called once. It must be called after the
// last call to any other Aic* API.
//
VOID
AicUninitialize ()
{
Assert (g_Aic.fInitialized);
if (g_Aic.fCachedAndListening)
{
CExceptionSafeLock EsLock (&g_Aic.critsec);
if (g_Aic.hWait)
{
TraceTag (ttidWanCon, "AicUninitialize: calling RtlDeregisterWait");
RtlDeregisterWait (g_Aic.hWait);
g_Aic.hWait = NULL;
}
TraceTag (ttidWanCon, "AicUninitialize: closing event handle");
CloseHandle (g_Aic.hEvent);
g_Aic.hEvent = NULL;
// MemFree (g_Aic.aRasConn);
// g_Aic.aRasConn = NULL;
// g_Aic.cRasConn = 0;
g_Aic.fCachedAndListening = FALSE;
}
// We can't delete the critical section unless we can guarantee
// that no other API (like HrAicFindRasConnFromGuidId)
// will be called. (This is assumed.)
//
DeleteCriticalSection (&g_Aic.critsec);
g_Aic.fInitialized = FALSE;
}
//+---------------------------------------------------------------------------
//
// Function: AicWaitCallback
//
// Purpose: Called by the RTL thread pool for this process when
// g_Aic.hEvent is signaled. This event will be signaled by
// the RemoteAccess service when the state of an incoming
// connection changes.
//
// Arguments:
// pvContext [in] Our user data. (Not used here.)
// fTimeout [in] TRUE if we were called because of a timeout.
//
// Returns: nothing
//
// Author: shaunco 24 Feb 1998
//
// Notes: Be quick about this. We're being called on a thread provided
// by the system.
//
VOID
NTAPI
AicWaitCallback (
PVOID pvContext,
BOOLEAN fTimeout)
{
Assert (g_Aic.fInitialized);
Assert (g_Aic.fCachedAndListening);
// Let's be sure we only do work if the service state is still running.
// If we have a stop pending for example, we don't need to do anything.
//
if (SERVICE_RUNNING != _Module.DwServiceStatus ())
{
TraceTag (ttidWanCon, "AicWaitCallback called while service is not "
"in SERVICE_RUNNING state. Ignoring.");
return;
}
TraceTag (ttidWanCon, "AicWaitCallback called");
HRESULT hr = S_OK;
// Lock scope
{
// Prevent other threads from reading the data we are about to update.
//
/*
DWORD cRasConnOld = g_Arc.cRasConn;
MemFree (g_Arc.aRasConn);
hr = HrRasEnumAllActiveConnections (&g_Arc.aRasConn, &g_Arc.cRasConn);
TraceTag (ttidWanCon,
"ArcWaitCallback called: connection count: %u -> %u",
cRasConnOld,
g_Arc.cRasConn);
*/
}
// Tell the connection manager to advise it's clients that a change
// occured and re-enumeration is neccessary.
//
CConnectionManager::NotifyClientsOfChange ();
TraceHr (ttidError, FAL, hr, FALSE, "AicWaitCallback");
}
HRESULT
HrAicEnsureCachedAndListening ()
{
Assert (g_Aic.fInitialized);
if (g_Aic.fCachedAndListening)
{
return S_OK;
}
g_Aic.fCachedAndListening = TRUE;
TraceTag (ttidWanCon, "Initializing active incoming ras "
"connections cache...");
HRESULT hr = E_FAIL;
CExceptionSafeLock EsLock (&g_Aic.critsec);
// Create a auto-reset event and register it with
// MprAdminConnectionNotification.
//
g_Aic.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (g_Aic.hEvent)
{
HANDLE hMprAdmin;
DWORD dwErr = MprAdminServerConnect (NULL, &hMprAdmin);
hr = HRESULT_FROM_WIN32 (dwErr);
TraceHr (ttidError, FAL, hr, FALSE, "MprAdminServerConnect", hr);
if (SUCCEEDED(hr))
{
dwErr = MprAdminRegisterConnectionNotification (
hMprAdmin, g_Aic.hEvent);
hr = HRESULT_FROM_WIN32 (dwErr);
TraceHr (ttidError, FAL, hr, FALSE,
"MprAdminRegisterConnectionNotification", hr);
if (SUCCEEDED(hr))
{
NTSTATUS status;
status = RtlRegisterWait (&g_Aic.hWait, g_Aic.hEvent,
AicWaitCallback, NULL, INFINITE, WT_EXECUTEDEFAULT);
if (!NT_SUCCESS(status))
{
hr = HRESULT_FROM_NT (status);
TraceHr (ttidError, FAL, hr, FALSE,
"RtlRegisterWait", hr);
}
else
{
TraceTag (ttidWanCon, "Cached and listening for "
"incoming ras connection state changes...");
hr = S_OK;
}
if (FAILED(hr))
{
MprAdminDeregisterConnectionNotification (hMprAdmin,
g_Aic.hEvent);
}
}
MprAdminServerDisconnect (hMprAdmin);
}
if (FAILED(hr))
{
CloseHandle (g_Aic.hEvent);
g_Aic.hEvent = NULL;
}
}
else
{
hr = HrFromLastWin32Error ();
TraceHr (ttidError, FAL, hr, FALSE, "CreateEvent", hr);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrAicEnsureCachedAndListening");
return hr;
}