/*++ 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")); } }