760 lines
17 KiB
C
760 lines
17 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999, Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
sample\configurationentry.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
The file contains functions to deal with the configuration entry.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pchsample.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
DisplayEventEntry (
|
||
|
IN PQUEUE_ENTRY pqeEntry)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Displays an EVENT_ENTRY object.
|
||
|
|
||
|
Locks
|
||
|
None
|
||
|
|
||
|
Arguments
|
||
|
|
||
|
pqeEntry address of the 'leEventQueueLink' field
|
||
|
|
||
|
Return Value
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EE_Display(CONTAINING_RECORD(pqeEntry, EVENT_ENTRY, qeEventQueueLink));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
FreeEventEntry (
|
||
|
IN PQUEUE_ENTRY pqeEntry)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Frees an EVENT_ENTRY object.
|
||
|
|
||
|
Locks
|
||
|
None
|
||
|
|
||
|
Arguments
|
||
|
|
||
|
pqeEntry address of the 'leEventQueueLink' field
|
||
|
|
||
|
Return Value
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EE_Destroy(CONTAINING_RECORD(pqeEntry, EVENT_ENTRY, qeEventQueueLink));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EE_Create (
|
||
|
IN ROUTING_PROTOCOL_EVENTS rpeEvent,
|
||
|
IN MESSAGE mMessage,
|
||
|
OUT PEVENT_ENTRY *ppeeEventEntry)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Creates an event entry.
|
||
|
|
||
|
Locks
|
||
|
None
|
||
|
|
||
|
Arguments
|
||
|
rpeEvent
|
||
|
mMessage
|
||
|
ppEventEntry pointer to the event entry address
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR if success
|
||
|
Failure code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
PEVENT_ENTRY peeEntry; // scratch
|
||
|
|
||
|
// validate parameters
|
||
|
if (!ppeeEventEntry)
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
|
||
|
*ppeeEventEntry = NULL;
|
||
|
|
||
|
// allocate the interface entry structure
|
||
|
MALLOC(&peeEntry, sizeof(EVENT_ENTRY), &dwErr);
|
||
|
if (dwErr != NO_ERROR)
|
||
|
return dwErr;
|
||
|
|
||
|
// initialize various fields
|
||
|
InitializeQueueHead(&(peeEntry->qeEventQueueLink));
|
||
|
|
||
|
peeEntry->rpeEvent = rpeEvent;
|
||
|
peeEntry->mMessage = mMessage;
|
||
|
|
||
|
*ppeeEventEntry = peeEntry;
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EE_Destroy (
|
||
|
IN PEVENT_ENTRY peeEventEntry)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Destroys an event entry.
|
||
|
|
||
|
Locks
|
||
|
None.
|
||
|
|
||
|
Arguments
|
||
|
peeEventEntry pointer to the event entry
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR always
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if (!peeEventEntry)
|
||
|
return NO_ERROR;
|
||
|
|
||
|
FREE(peeEventEntry);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
DWORD
|
||
|
EE_Display (
|
||
|
IN PEVENT_ENTRY peeEventEntry)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Displays an event entry.
|
||
|
|
||
|
Locks
|
||
|
None.
|
||
|
|
||
|
Arguments
|
||
|
peeEventEntry pointer to the event entry
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR always
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if (!peeEventEntry)
|
||
|
return NO_ERROR;
|
||
|
|
||
|
TRACE1(CONFIGURATION,
|
||
|
"Event %u",
|
||
|
peeEventEntry->rpeEvent);
|
||
|
|
||
|
if (peeEventEntry->rpeEvent is SAVE_INTERFACE_CONFIG_INFO)
|
||
|
TRACE1(CONFIGURATION,
|
||
|
"Index %u",
|
||
|
(peeEventEntry->mMessage).InterfaceIndex);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
#endif // DEBUG
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EnqueueEvent(
|
||
|
IN ROUTING_PROTOCOL_EVENTS rpeEvent,
|
||
|
IN MESSAGE mMessage)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Queues an event entry in g_ce.lqEventQueue.
|
||
|
|
||
|
Locks
|
||
|
Locks and unlocks the locked queue g_ce.lqEventQueue.
|
||
|
|
||
|
Arguments
|
||
|
rpeEvent
|
||
|
mMessage
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
Error Code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
PEVENT_ENTRY peeEntry = NULL;
|
||
|
|
||
|
dwErr = EE_Create(rpeEvent, mMessage, &peeEntry);
|
||
|
// destroyed in EE_DequeueEvent
|
||
|
|
||
|
if (dwErr is NO_ERROR)
|
||
|
{
|
||
|
ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
|
||
|
|
||
|
Enqueue(&(g_ce.lqEventQueue.head), &(peeEntry->qeEventQueueLink));
|
||
|
|
||
|
RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
DequeueEvent(
|
||
|
OUT ROUTING_PROTOCOL_EVENTS *prpeEvent,
|
||
|
OUT MESSAGE *pmMessage)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Dequeues an event entry from g_ce.lqEventQueue.
|
||
|
|
||
|
Locks
|
||
|
Locks and unlocks the locked queue g_ce.lqEventQueue.
|
||
|
|
||
|
Arguments
|
||
|
prpeEvent
|
||
|
pmMessage
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR success
|
||
|
ERROR_NO_MORE_ITEMS o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
PQUEUE_ENTRY pqe = NULL;
|
||
|
PEVENT_ENTRY pee = NULL;
|
||
|
|
||
|
ACQUIRE_QUEUE_LOCK(&(g_ce.lqEventQueue));
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
if (IsQueueEmpty(&(g_ce.lqEventQueue.head)))
|
||
|
{
|
||
|
dwErr = ERROR_NO_MORE_ITEMS;
|
||
|
TRACE0(CONFIGURATION, "Error no events in the queue");
|
||
|
LOGWARN0(EVENT_QUEUE_EMPTY, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pqe = Dequeue(&(g_ce.lqEventQueue.head));
|
||
|
|
||
|
pee = CONTAINING_RECORD(pqe, EVENT_ENTRY, qeEventQueueLink);
|
||
|
*(prpeEvent) = pee->rpeEvent;
|
||
|
*(pmMessage) = pee->mMessage;
|
||
|
|
||
|
// created in EE_EnqueueEvent
|
||
|
EE_Destroy(pee);
|
||
|
pee = NULL;
|
||
|
} while (FALSE);
|
||
|
|
||
|
RELEASE_QUEUE_LOCK(&(g_ce.lqEventQueue));
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CE_Create (
|
||
|
IN PCONFIGURATION_ENTRY pce)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Creates a configuration entry on DLL_PROCESS_ATTACH.
|
||
|
|
||
|
Locks
|
||
|
None
|
||
|
|
||
|
Arguments
|
||
|
pce pointer to the configuration entry
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR if success
|
||
|
Failure code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
// initialize to default values
|
||
|
ZeroMemory(pce, sizeof(CONFIGURATION_ENTRY));
|
||
|
pce->dwTraceID = INVALID_TRACEID;
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// initialize the read-write lock
|
||
|
CREATE_READ_WRITE_LOCK(&(pce->rwlLock));
|
||
|
if (!READ_WRITE_LOCK_CREATED(&(pce->rwlLock)))
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
|
||
|
TRACE1(CONFIGURATION, "Error %u creating read-write-lock", dwErr);
|
||
|
LOGERR0(CREATE_RWL_FAILED, dwErr);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// initialize the global heap
|
||
|
pce->hGlobalHeap = HeapCreate(0, 0, 0);
|
||
|
if (pce->hGlobalHeap is NULL)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
TRACE1(CONFIGURATION, "Error %u creating global heap", dwErr);
|
||
|
LOGERR0(HEAP_CREATE_FAILED, dwErr);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// initialize the count of threads that are active in IPSAMPLE
|
||
|
// create the semaphore released by each thread when it is done
|
||
|
// required for clean stop to the protocol
|
||
|
//
|
||
|
pce->ulActivityCount = 0;
|
||
|
pce->hActivitySemaphore = CreateSemaphore(NULL, 0, 0xfffffff, NULL);
|
||
|
if (pce->hActivitySemaphore is NULL)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
TRACE1(CONFIGURATION, "Error %u creating semaphore", dwErr);
|
||
|
LOGERR0(CREATE_SEMAPHORE_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Logging & Tracing Information
|
||
|
pce->dwLogLevel = IPSAMPLE_LOGGING_INFO;
|
||
|
pce->hLogHandle = RouterLogRegister("IPSAMPLE");
|
||
|
pce->dwTraceID = TraceRegister("IPSAMPLE");
|
||
|
|
||
|
// Event Queue
|
||
|
INITIALIZE_LOCKED_QUEUE(&(pce->lqEventQueue));
|
||
|
if (!LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue)))
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
TRACE1(CONFIGURATION, "Error %u initializing locked queue", dwErr);
|
||
|
LOGERR0(INIT_CRITSEC_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Protocol State
|
||
|
pce->iscStatus = IPSAMPLE_STATUS_STOPPED;
|
||
|
|
||
|
|
||
|
// Store of Dynamic Locks
|
||
|
// pce->dlsDynamicLocksStore zero'ed out
|
||
|
|
||
|
// Timer Entry
|
||
|
// pce->hTimerQueue = NULL;
|
||
|
|
||
|
// Router Manager Information (later)
|
||
|
// pce->hMgrNotificationEvent = NULL
|
||
|
// pce->sfSupportFunctions zero'ed out
|
||
|
|
||
|
// RTMv2 Information
|
||
|
// pce->reiRtmEntity zero'ed out
|
||
|
// pce->rrpRtmProfile zero'ed out
|
||
|
// pce->hRtmHandle = NULL
|
||
|
// pce->hRtmNotificationHandle = NULL
|
||
|
|
||
|
// MGM Information
|
||
|
// pce->hMgmHandle = NULL
|
||
|
|
||
|
// Network Entry
|
||
|
// pce->pneNetworkEntry = NULL;
|
||
|
|
||
|
// Global Statistics
|
||
|
// pce->igsStats zero'ed out
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (dwErr != NO_ERROR)
|
||
|
{
|
||
|
// something went wrong, so cleanup.
|
||
|
TRACE0(CONFIGURATION, "Failed to create configuration entry");
|
||
|
CE_Destroy(pce);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CE_Destroy (
|
||
|
IN PCONFIGURATION_ENTRY pce)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Destroys a configuration entry on DLL_PROCESS_DEATTACH
|
||
|
|
||
|
Locks
|
||
|
Assumes exclusive access to rwlLock with no waiting thread.
|
||
|
|
||
|
Arguments
|
||
|
pce pointer to the configuration entry
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR always
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
// Network Entry
|
||
|
|
||
|
// MGM Information
|
||
|
|
||
|
// RTMv2 Information
|
||
|
|
||
|
// Router Manager Information
|
||
|
|
||
|
// Timer Entry
|
||
|
|
||
|
// Store of Dynamic Locks
|
||
|
|
||
|
// protocol state should be such...
|
||
|
RTASSERT(pce->iscStatus is IPSAMPLE_STATUS_STOPPED);
|
||
|
|
||
|
// Event Queue
|
||
|
if (LOCKED_QUEUE_INITIALIZED(&(pce->lqEventQueue)))
|
||
|
DELETE_LOCKED_QUEUE((&(pce->lqEventQueue)), FreeEventEntry);
|
||
|
|
||
|
// Logging & Tracing Information
|
||
|
if (pce->dwTraceID != INVALID_TRACEID)
|
||
|
{
|
||
|
TraceDeregister(pce->dwTraceID);
|
||
|
pce->dwTraceID = INVALID_TRACEID;
|
||
|
}
|
||
|
if (pce->hLogHandle != NULL)
|
||
|
{
|
||
|
RouterLogDeregister(pce->hLogHandle);
|
||
|
pce->hLogHandle = NULL;
|
||
|
}
|
||
|
|
||
|
// destroy the semaphore released by each thread when it is done
|
||
|
if (pce->hActivitySemaphore != NULL)
|
||
|
{
|
||
|
CloseHandle(pce->hActivitySemaphore);
|
||
|
pce->hActivitySemaphore = NULL;
|
||
|
}
|
||
|
|
||
|
if (pce->hGlobalHeap != NULL)
|
||
|
{
|
||
|
HeapDestroy(pce->hGlobalHeap);
|
||
|
pce->hGlobalHeap = NULL;
|
||
|
}
|
||
|
|
||
|
// delete the read-write lock
|
||
|
if (READ_WRITE_LOCK_CREATED(&(pce->rwlLock)))
|
||
|
DELETE_READ_WRITE_LOCK(&(pce->rwlLock));
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CE_Initialize (
|
||
|
IN PCONFIGURATION_ENTRY pce,
|
||
|
IN HANDLE hMgrNotificationEvent,
|
||
|
IN PSUPPORT_FUNCTIONS psfSupportFunctions,
|
||
|
IN PIPSAMPLE_GLOBAL_CONFIG pigc)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Initializes a configuration entry on StartProtocol.
|
||
|
|
||
|
Locks
|
||
|
Assumes exclusive access to pce->rwlLock
|
||
|
|
||
|
Arguments
|
||
|
pce pointer to the configuration entry
|
||
|
hMgrNotificationEvent event used to notify ip router manager
|
||
|
psfSupportFunctions functions exported by ip router manager
|
||
|
pigc global configuration set in registry
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR if success
|
||
|
Failure code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
WORD wVersionRequested = MAKEWORD(1,1);
|
||
|
WSADATA wsaData;
|
||
|
BOOL bCleanupWinsock = FALSE;
|
||
|
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
// validate environment
|
||
|
RTASSERT(pce->ulActivityCount is 0);
|
||
|
RTASSERT(pce->iscStatus is IPSAMPLE_STATUS_STOPPED);
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
pce->ulActivityCount = 0;
|
||
|
pce->dwLogLevel = pigc->dwLoggingLevel;
|
||
|
|
||
|
|
||
|
dwErr = (DWORD) WSAStartup(wVersionRequested, &wsaData);
|
||
|
if (dwErr != 0)
|
||
|
{
|
||
|
TRACE1(CONFIGURATION, "Error %u starting windows sockets", dwErr);
|
||
|
LOGERR0(WSASTARTUP_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
bCleanupWinsock = TRUE;
|
||
|
|
||
|
// Store of Dynamic Locks
|
||
|
dwErr = InitializeDynamicLocksStore(&(pce->dlsDynamicLocksStore),
|
||
|
GLOBAL_HEAP);
|
||
|
if (dwErr != NO_ERROR)
|
||
|
{
|
||
|
TRACE1(CONFIGURATION, "Error %u initializing locks store", dwErr);
|
||
|
LOGERR0(INIT_CRITSEC_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Timer Entry
|
||
|
pce->hTimerQueue = CreateTimerQueue();
|
||
|
if (!pce->hTimerQueue)
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
TRACE1(CONFIGURATION, "Error %u registering timer queue", dwErr);
|
||
|
LOGERR0(CREATE_TIMER_QUEUE_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Router Manager Information
|
||
|
pce->hMgrNotificationEvent = hMgrNotificationEvent;
|
||
|
if (psfSupportFunctions)
|
||
|
pce->sfSupportFunctions = *psfSupportFunctions;
|
||
|
|
||
|
|
||
|
// RTMv2 Information
|
||
|
pce->reiRtmEntity.RtmInstanceId = 0;
|
||
|
pce->reiRtmEntity.AddressFamily = AF_INET;
|
||
|
pce->reiRtmEntity.EntityId.EntityProtocolId = PROTO_IP_SAMPLE;
|
||
|
pce->reiRtmEntity.EntityId.EntityInstanceId = 0;
|
||
|
|
||
|
dwErr = RTM_RegisterEntity(
|
||
|
&pce->reiRtmEntity, // IN my RTM_ENTITY_INFO
|
||
|
NULL, // IN my exported methods
|
||
|
RTM_CallbackEvent, // IN my callback function
|
||
|
TRUE, // IN reserve opaque pointer?
|
||
|
&pce->rrpRtmProfile, // OUT my RTM_REGN_PROFILE
|
||
|
&pce->hRtmHandle); // OUT my RTMv2 handle
|
||
|
if (dwErr != NO_ERROR)
|
||
|
{
|
||
|
TRACE1(CONFIGURATION, "Error %u registering with RTM", dwErr);
|
||
|
LOGERR0(RTM_REGISTER_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwErr = RTM_RegisterForChangeNotification(
|
||
|
pce->hRtmHandle, // IN my RTMv2 handle
|
||
|
RTM_VIEW_MASK_MCAST, // IN route table views relevant to moi
|
||
|
RTM_CHANGE_TYPE_BEST, // IN change types interesting to moi
|
||
|
NULL, // IN context in callback function
|
||
|
&pce->hRtmNotificationHandle); // OUT my notification handle
|
||
|
if (dwErr != NO_ERROR)
|
||
|
{
|
||
|
TRACE1(CONFIGURATION,
|
||
|
"Error %u registering for change with RTM", dwErr);
|
||
|
LOGERR0(RTM_REGISTER_FAILED, dwErr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
// MGM Information
|
||
|
// pce->hMgmHandle (later)
|
||
|
|
||
|
|
||
|
// Network Entry
|
||
|
dwErr = NE_Create(&(pce->pneNetworkEntry));
|
||
|
if (dwErr != NO_ERROR)
|
||
|
break;
|
||
|
|
||
|
|
||
|
// Global Statistics
|
||
|
ZeroMemory(&(pce->igsStats), sizeof(IPSAMPLE_GLOBAL_STATS));
|
||
|
|
||
|
|
||
|
pce->iscStatus = IPSAMPLE_STATUS_RUNNING;
|
||
|
} while (FALSE);
|
||
|
|
||
|
// something went wrong, cleanup
|
||
|
if (dwErr != NO_ERROR)
|
||
|
CE_Cleanup(pce, bCleanupWinsock);
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CE_Cleanup (
|
||
|
IN PCONFIGURATION_ENTRY pce,
|
||
|
IN BOOL bCleanupWinsock)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Cleans up a configuration entry on StopProtocol.
|
||
|
|
||
|
Locks
|
||
|
Exclusive access to pce->rwlLock by virtue of no competing threads.
|
||
|
|
||
|
NOTE: However, pce->rwlLock should NOT actually be held! The call to
|
||
|
DeleteTimerQueueEx blocks till all queued callbacks finish execution.
|
||
|
These callbacks may acquire pce->rwlLock, causing deadlock.
|
||
|
|
||
|
Arguments
|
||
|
pce pointer to the configuration entry
|
||
|
bCleanupWinsock
|
||
|
Return Value
|
||
|
NO_ERROR always
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
|
||
|
|
||
|
// Network Entry
|
||
|
NE_Destroy(pce->pneNetworkEntry);
|
||
|
pce->pneNetworkEntry = NULL;
|
||
|
|
||
|
|
||
|
// MGM Information (later)
|
||
|
pce->hMgmHandle = NULL;
|
||
|
|
||
|
|
||
|
// RTMv2 Information
|
||
|
if (pce->hRtmNotificationHandle)
|
||
|
{
|
||
|
dwErr = RTM_DeregisterFromChangeNotification(
|
||
|
pce->hRtmHandle,
|
||
|
pce->hRtmNotificationHandle);
|
||
|
|
||
|
if (dwErr != NO_ERROR)
|
||
|
TRACE1(CONFIGURATION,
|
||
|
"Error %u deregistering for change from RTM", dwErr);
|
||
|
}
|
||
|
pce->hRtmNotificationHandle = NULL;
|
||
|
|
||
|
if (pce->hRtmHandle)
|
||
|
{
|
||
|
dwErr = RTM_DeregisterEntity(pce->hRtmHandle);
|
||
|
|
||
|
if (dwErr != NO_ERROR)
|
||
|
TRACE1(CONFIGURATION,
|
||
|
"Error %u deregistering from RTM", dwErr);
|
||
|
}
|
||
|
pce->hRtmHandle = NULL;
|
||
|
|
||
|
|
||
|
// Router Manager Information
|
||
|
// valid till overwritten, needed to signal the ip router manager
|
||
|
// pce->hMgrNotificationEvent
|
||
|
// pce->sfSupportFunctions
|
||
|
|
||
|
|
||
|
// Timer Entry
|
||
|
if (pce->hTimerQueue)
|
||
|
DeleteTimerQueueEx(pce->hTimerQueue, INVALID_HANDLE_VALUE);
|
||
|
pce->hTimerQueue = NULL;
|
||
|
|
||
|
|
||
|
// Store of Dynamic Locks
|
||
|
if (DYNAMIC_LOCKS_STORE_INITIALIZED(&(pce->dlsDynamicLocksStore)))
|
||
|
{
|
||
|
dwErr = DeInitializeDynamicLocksStore(&(pce->dlsDynamicLocksStore));
|
||
|
|
||
|
// all dynamic locks should have been free
|
||
|
RTASSERT(dwErr is NO_ERROR);
|
||
|
}
|
||
|
|
||
|
if (bCleanupWinsock)
|
||
|
WSACleanup();
|
||
|
|
||
|
// protocol state
|
||
|
pce->iscStatus = IPSAMPLE_STATUS_STOPPED;
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
DWORD
|
||
|
CE_Display (
|
||
|
IN PCONFIGURATION_ENTRY pce)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
Displays a configuration entry.
|
||
|
|
||
|
Locks
|
||
|
Acquires shared pce->rwlLock
|
||
|
Releases pce->rwlLock
|
||
|
|
||
|
Arguments
|
||
|
pce pointer to the configuration entry to be displayed
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR always
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if (!pce)
|
||
|
return NO_ERROR;
|
||
|
|
||
|
|
||
|
ACQUIRE_READ_LOCK(&(pce->rwlLock));
|
||
|
|
||
|
TRACE0(CONFIGURATION, "Configuration Entry...");
|
||
|
|
||
|
TRACE3(CONFIGURATION,
|
||
|
"ActivityCount %u, LogLevel %u, NumInterfaces %u",
|
||
|
pce->ulActivityCount,
|
||
|
pce->dwLogLevel,
|
||
|
pce->igsStats.ulNumInterfaces);
|
||
|
|
||
|
NE_Display(pce->pneNetworkEntry);
|
||
|
|
||
|
RELEASE_READ_LOCK(&(pce->rwlLock));
|
||
|
|
||
|
TRACE0(CONFIGURATION, "EventQueue...");
|
||
|
ACQUIRE_QUEUE_LOCK(&(pce->lqEventQueue));
|
||
|
MapCarQueue(&((pce->lqEventQueue).head), DisplayEventEntry);
|
||
|
RELEASE_QUEUE_LOCK(&(pce->lqEventQueue));
|
||
|
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
#endif // DEBUG
|