296 lines
7.6 KiB
C++
296 lines
7.6 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|