548 lines
11 KiB
C
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"));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|