windows-nt/Source/XPSP1/NT/net/qos/tc/dll/init.c
2020-09-26 16:20:57 +08:00

548 lines
11 KiB
C

/*++
Copyright (c) 1996-1997 Microsoft Corporation
Module Name:
init.c
Abstract:
This module contains initialization code for traffic.DLL.
Author:
Jim Stewart ( jstew ) July 28, 1996
Revision History:
Ofer Bar (oferbar) Oct 1, 1997
--*/
#include "precomp.h"
//#pragma hdrstop
//#include "oscode.h"
//
// global data
//
ULONG DebugMask = 0;
BOOL NTPlatform = FALSE;
//LPWSCONTROL WsCtrl = NULL;
PGLOBAL_STRUC pGlobals = NULL;
DWORD InitializationStatus = NO_ERROR;
static BOOL _init_rpc = FALSE;
static PUSHORT _RpcStringBinding;
//
// 258218 changes
//
TRAFFIC_LOCK NotificationListLock;
LIST_ENTRY NotificationListHead;
TRAFFIC_LOCK ClientRegDeregLock;
HANDLE GpcCancelEvent = INVALID_HANDLE_VALUE;
PVOID hinstTrafficDll;
VOID
CloseAll(VOID);
#if DBG
TCHAR *TC_States[] = {
TEXT("INVALID"),
TEXT("INSTALLING"), // structures were allocated.
TEXT("OPEN"), // Open for business
TEXT("USERCLOSED_KERNELCLOSEPENDING"), // the user component has closed it, we are awaiting a kernel close
TEXT("FORCED_KERNELCLOSE"), // the kernel component has forced a close.
TEXT("KERNELCOSED_USERCLEANUP"), // Kernel has closed it, we are ready to delete this obj.
TEXT("REMOVED"), // Its gone (being freed - remember that the handle has to be freed before removing)
TEXT("EXIT_CLEANUP"), // We are going away and need to be cleanedup
TEXT("MAX_STATES")
};
#endif
BOOL
Initialize (
IN PVOID DllHandle,
IN ULONG Reason,
IN PVOID Context OPTIONAL
)
/*++
Description:
This is the DLL entry point, called when a process
attaches or a thread is created
Arguments:
DllHandle - a handle to the DLL
Reason - why the dll entry point is being called
Context - additional information about call reason
Return Value:
TRUE or FALSE
--*/
{
HANDLE Handle;
DWORD Error;
//
// On a thread detach, set up the context param so that all
// necessary deallocations will occur. On a FreeLibrary call Context
// will be NULL and that is the case that we DO want to cleanup.
//
if ( Reason == DLL_THREAD_DETACH ) {
Context = NULL;
}
switch ( Reason ) {
case DLL_PROCESS_ATTACH:
// Save the DLL handle as it is used to change ref count on this DLL
hinstTrafficDll = DllHandle;
//
// disable the DLL_THREAD_ATTACH event
//
DisableThreadLibraryCalls( DllHandle );
SETUP_DEBUG_INFO();
IF_DEBUG(INIT) {
WSPRINT(( "Initialize: DLL Process Attach \n" ));
}
INIT_DBG_MEMORY();
if (!InitializeGlobalData()) {
CLOSE_DEBUG();
return FALSE;
}
IF_DEBUG(INIT) {
WSPRINT(("traffic.dll Version %d\n", CURRENT_TCI_VERSION));
}
InitializationStatus = InitializeOsSpecific();
if (ERROR_FAILED(InitializationStatus)) {
WSPRINT(("\tInitialize: Failed OS specific initialization!\n"));
CLOSE_DEBUG();
//
// we return TRUE to succedd DLL loading into the process
// all other TCI calls will check this and fail...
//
return TRUE;
} else {
#if 0
InitializeWmi();
//
// call to internally enumerate the interfaces
//
EnumAllInterfaces();
#endif
}
//InitializeIpRouteTab();
break;
case DLL_PROCESS_DETACH:
if ( Context )
{
// As per MSDN a non-zero Context means process is
// terminating. Do not do any cleanup
break;
}
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "Shutdown: Process Detach, Context = %X\n",Context ));
}
//DUMP_MEM_ALLOCATIONS();
//
// Only clean up resources if we're being called because of a
// FreeLibrary(). If this is because of process termination,
// do not clean up, as the system will do it for us. However
// we must still clear all flows and filters with the kernel
// since the system will not clean these up on termination.
//
//
// don't want to get WMI notifications
//
DeInitializeWmi();
//
// close all flows and filters with the kernel and deregister from GPC
//
CloseAll();
//
// close the kernel file handle
//
DeInitializeOsSpecific();
//
// release all allocated resources
//
DeInitializeGlobalData();
//
// dump allocated memory, before and after we cleanup to
// help track any leaks
DUMP_MEM_ALLOCATIONS();
DEINIT_DBG_MEMORY();
CLOSE_DEBUG();
break;
case DLL_THREAD_DETACH:
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "Shutdown: thread detach\n" ));
}
break;
case DLL_THREAD_ATTACH:
break;
default:
ASSERT( FALSE );
break;
}
return TRUE;
}
VOID
CloseAll()
/*++
Description:
Close all interfaces, all flows and all filters.
Also deregister GPC clients and release all TC ineterfaces.
Arguments:
none
Return Value:
none
--*/
{
DWORD Status;
PLIST_ENTRY pEntry;
PINTERFACE_STRUC pInterface;
PCLIENT_STRUC pClient;
PGPC_CLIENT pGpcClient;
PTC_IFC pTcIfc;
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Attempting to close any open interface\n" ));
}
while (!IsListEmpty( &pGlobals->ClientList )) {
pClient = CONTAINING_RECORD( pGlobals->ClientList.Flink,
CLIENT_STRUC,
Linkage );
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Closing client=0x%X\n",
PtrToUlong(pClient)));
}
while (!IsListEmpty( &pClient->InterfaceList )) {
pInterface = CONTAINING_RECORD( pClient->InterfaceList.Flink,
INTERFACE_STRUC,
Linkage );
//
// remove all flows/filters and close the interface
//
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Closing interface=0x%X\n",
PtrToUlong(pInterface)));
}
MarkAllNodesForClosing(pInterface, EXIT_CLEANUP);
CloseInterface(pInterface, TRUE);
}
//
// deregister the client
//
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Deregistring TC client\n"));
}
TcDeregisterClient(pClient->ClHandle);
}
//
// Deregister GPC clients
//
while (!IsListEmpty( &pGlobals->GpcClientList )) {
pEntry = pGlobals->GpcClientList.Flink;
pGpcClient = CONTAINING_RECORD( pEntry,
GPC_CLIENT,
Linkage );
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Deregistring GPC client\n"));
}
IoDeregisterClient(pGpcClient);
RemoveEntryList(pEntry);
FreeMem(pGpcClient);
}
//
// Remove TC interfaces
//
while (!IsListEmpty( &pGlobals->TcIfcList )) {
pEntry = pGlobals->TcIfcList.Flink;
pTcIfc = CONTAINING_RECORD( pEntry,
TC_IFC,
Linkage );
ASSERT( IsListEmpty( &pTcIfc->ClIfcList ) );
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "CloseAll: Remove TC (%x) interface from list\n", pTcIfc));
}
REFDEL(&pTcIfc->RefCount, 'KIFC');
}
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "<==CloseAll: exit...\n"));
}
}
DWORD
InitializeGlobalData(VOID)
/*++
Description:
This routine initializes the global data.
Arguments:
none
Return Value:
none
--*/
{
DWORD Status;
//
// allocate memory for the globals
//
AllocMem(&pGlobals, sizeof(GLOBAL_STRUC));
if (pGlobals == NULL) {
return FALSE;
}
RtlZeroMemory(pGlobals, sizeof(GLOBAL_STRUC));
__try {
InitLock( pGlobals->Lock );
InitLock( NotificationListLock);
InitLock( ClientRegDeregLock );
} __except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
IF_DEBUG(ERRORS) {
WSPRINT(("TcRegisterClient: Exception Error: = 0x%X\n", Status ));
}
FreeMem(pGlobals);
return FALSE;
}
//
// initialize the handle table
//
NEW_HandleFactory(pGlobals->pHandleTbl);
if (pGlobals->pHandleTbl == NULL) {
FreeMem(pGlobals);
return FALSE;
}
if (constructHandleFactory(pGlobals->pHandleTbl) != 0) {
//
// failed to construct the handle table, exit
//
FreeHandleFactory(pGlobals->pHandleTbl);
FreeMem(pGlobals);
return FALSE;
}
InitializeListHead( &pGlobals->ClientList );
InitializeListHead( &pGlobals->TcIfcList );
InitializeListHead( &pGlobals->GpcClientList );
InitializeListHead( &NotificationListHead ); // 258218
ASSERT(sizeof(IP_PATTERN) == sizeof(GPC_IP_PATTERN));
ASSERT(FIELD_OFFSET(IP_PATTERN,SrcAddr) ==
FIELD_OFFSET(GPC_IP_PATTERN,SrcAddr));
ASSERT(FIELD_OFFSET(IP_PATTERN,ProtocolId) ==
FIELD_OFFSET(GPC_IP_PATTERN,ProtocolId));
return TRUE;
}
VOID
DeInitializeGlobalData(VOID)
/*++
Description:
This routine de-initializes the global data.
Arguments:
none
Return Value:
none
--*/
{
PLIST_ENTRY pEntry;
PTC_IFC pTcIfc;
PNOTIFICATION_ELEMENT pNotifyElem;
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "DeInitializeGlobalData: cleanup global data\n"));
}
destructHandleFactory(pGlobals->pHandleTbl);
FreeHandleFactory(pGlobals->pHandleTbl);
#if 0
//
// clear the TC interface structures
//
while (!IsListEmpty(&pGlobals->TcIfcList)) {
pEntry = RemoveHeadList(&pGlobals->TcIfcList);
pTcIfc = (PTC_IFC)CONTAINING_RECORD(pEntry, TC_IFC, Linkage);
FreeMem(pTcIfc);
}
#endif
DeleteLock( pGlobals->Lock );
//
// Free the notification elements (258218)
//
while (!IsListEmpty(&NotificationListHead)) {
pEntry = RemoveHeadList(&NotificationListHead);
pNotifyElem = (PNOTIFICATION_ELEMENT)CONTAINING_RECORD(pEntry, NOTIFICATION_ELEMENT, Linkage.Flink);
FreeMem(pNotifyElem);
}
DeleteLock( NotificationListLock);
DeleteLock( ClientRegDeregLock );
FreeMem(pGlobals);
IF_DEBUG(SHUTDOWN) {
WSPRINT(( "<==DeInitializeGlobalData: exit\n"));
}
}