357 lines
7.4 KiB
C
357 lines
7.4 KiB
C
|
//==========================================================================
|
||
|
// Copyright (c) 1995, Microsoft Corporation
|
||
|
//
|
||
|
// File: entry.c
|
||
|
//
|
||
|
// History:
|
||
|
// t-abolag 06-21-95 Created.
|
||
|
//
|
||
|
// entry point for Routing Table API set
|
||
|
//==========================================================================
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <time.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#ifndef CHICAGO
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <winsock.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <errno.h>
|
||
|
#include <process.h>
|
||
|
#include <malloc.h>
|
||
|
#include <io.h>
|
||
|
#include <winsvc.h>
|
||
|
|
||
|
#include "ipinfo.h"
|
||
|
#include "llinfo.h"
|
||
|
#include "ntddtcp.h"
|
||
|
#include "tdiinfo.h"
|
||
|
#include "dhcpcapi.h"
|
||
|
|
||
|
#include "routetab.h"
|
||
|
#include "rtdefs.h"
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
LIBMAIN(
|
||
|
IN HINSTANCE hInstance,
|
||
|
IN DWORD dwReason,
|
||
|
IN LPVOID lpvUnused
|
||
|
)
|
||
|
{
|
||
|
|
||
|
BOOL bError = TRUE;
|
||
|
|
||
|
switch(dwReason) {
|
||
|
|
||
|
case DLL_PROCESS_ATTACH: {
|
||
|
|
||
|
DEBUG_PRINT(("LIBMAIN: DLL_PROCESS_ATTACH\n"));
|
||
|
|
||
|
//
|
||
|
// we have no per-thread initialization,
|
||
|
// so disable DLL_THREAD_{ATTACH,DETACH} calls
|
||
|
//
|
||
|
|
||
|
DisableThreadLibraryCalls(hInstance);
|
||
|
|
||
|
|
||
|
//
|
||
|
// initialize globals and background thread
|
||
|
//
|
||
|
|
||
|
bError = RTStartup((HMODULE)hInstance);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case DLL_PROCESS_DETACH: {
|
||
|
|
||
|
//
|
||
|
// if the background thread is around, tell it to clean up;
|
||
|
// otherwise clean up ourselves
|
||
|
//
|
||
|
|
||
|
bError = RTShutdown((HMODULE)hInstance);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEBUG_PRINT(("LIBMAIN: <= %d\n", bError ));
|
||
|
|
||
|
return bError;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function: RTStartup
|
||
|
//
|
||
|
// Handles initialization for DLL-wide data
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL
|
||
|
RTStartup(
|
||
|
HMODULE hmodule
|
||
|
)
|
||
|
{
|
||
|
|
||
|
HANDLE hThread;
|
||
|
DWORD dwErr, dwThread;
|
||
|
SECURITY_ATTRIBUTES saAttr;
|
||
|
SECURITY_DESCRIPTOR sdDesc;
|
||
|
CHAR szModule[MAX_PATH + 1];
|
||
|
|
||
|
g_prtcfg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*g_prtcfg));
|
||
|
|
||
|
if (g_prtcfg == NULL){
|
||
|
DEBUG_PRINT(("RTStartup: !HeapAlloc \n"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
|
||
|
//
|
||
|
// We do a loadlibrary to increment the reference count
|
||
|
// on this library, so that when the library is unloaded
|
||
|
// by the application, our address-space doesn't disappear.
|
||
|
// Instead, we signal the thread and then we cleanup
|
||
|
// and call FreeLibraryAndExitThread to unload the DLL completely
|
||
|
//
|
||
|
|
||
|
GetModuleFileName(hmodule, szModule, MAX_PATH);
|
||
|
|
||
|
hmodule = LoadLibrary(szModule);
|
||
|
|
||
|
if (!hmodule) {
|
||
|
DEBUG_PRINT(("RTStartup: !loadlibrary %s\n", szModule ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the event signalled to tell the update thread to exit
|
||
|
//
|
||
|
|
||
|
g_rtCfg.hUpdateThreadExit = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
|
|
||
|
if (g_rtCfg.hUpdateThreadExit == NULL) {
|
||
|
DEBUG_PRINT(("RTStartup: !CreateEvent \n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the mutex which protects our tables
|
||
|
//
|
||
|
|
||
|
g_rtCfg.hRTMutex = CreateMutex(NULL, FALSE, NULL);
|
||
|
|
||
|
if (g_rtCfg.hRTMutex == NULL) { break; }
|
||
|
|
||
|
|
||
|
//
|
||
|
// Load interface table now before any API functions are called
|
||
|
//
|
||
|
|
||
|
dwErr = RTGetTables(
|
||
|
&g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
|
||
|
&g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount
|
||
|
);
|
||
|
|
||
|
if (dwErr != 0) {
|
||
|
DEBUG_PRINT(("RTStartup: !RTGetTables \n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Try to create the DHCP event in case DHCP service or DHCP API
|
||
|
// has not created it; use the security attributes struct
|
||
|
// because DHCP will. Omitting this code will cause DHCP
|
||
|
// to fail to open the event if the interfaces are statically
|
||
|
// configured (in which case the DHCP client would not be running);
|
||
|
//
|
||
|
|
||
|
#if (WINVER >= 0x500)
|
||
|
g_rtCfg.hDHCPEvent = DhcpOpenGlobalEvent();
|
||
|
#else
|
||
|
saAttr.nLength = sizeof(saAttr);
|
||
|
saAttr.bInheritHandle = FALSE;
|
||
|
|
||
|
InitializeSecurityDescriptor(&sdDesc, SECURITY_DESCRIPTOR_REVISION);
|
||
|
|
||
|
if (SetSecurityDescriptorDacl(&sdDesc, TRUE, NULL, FALSE)) {
|
||
|
saAttr.lpSecurityDescriptor = &sdDesc;
|
||
|
}
|
||
|
else {
|
||
|
saAttr.lpSecurityDescriptor = NULL;
|
||
|
}
|
||
|
|
||
|
g_rtCfg.hDHCPEvent =
|
||
|
CreateEvent(&saAttr, TRUE, FALSE, STR_DHCPNEWIPADDR);
|
||
|
#endif
|
||
|
|
||
|
if (g_rtCfg.hDHCPEvent != NULL) {
|
||
|
|
||
|
//
|
||
|
// Start up the thread which updates the interface table
|
||
|
// if IP addresses are changed
|
||
|
//
|
||
|
|
||
|
hThread = CreateThread(
|
||
|
NULL, 0, (LPTHREAD_START_ROUTINE)RTUpdateThread,
|
||
|
(LPVOID)hmodule, 0, &dwThread
|
||
|
);
|
||
|
|
||
|
if (hThread == NULL) {
|
||
|
DEBUG_PRINT(("RTStartup: !CreateThread \n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
g_rtCfg.dwUpdateThreadStarted = 1;
|
||
|
|
||
|
CloseHandle(hThread);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
} while(FALSE);
|
||
|
|
||
|
|
||
|
//
|
||
|
// If we reach here, something went wrong;
|
||
|
// clean up and decrement the DLL reference count.
|
||
|
//
|
||
|
|
||
|
RTCleanUp();
|
||
|
|
||
|
if (hmodule) {
|
||
|
FreeLibrary(hmodule);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function: RTShutdown
|
||
|
//
|
||
|
// Handles DLL-unload-time cleanup.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL
|
||
|
RTShutdown(
|
||
|
HMODULE hmodule
|
||
|
)
|
||
|
{
|
||
|
|
||
|
|
||
|
//
|
||
|
// If the background thread exists, allow it to clean up;
|
||
|
// otherwise, handle cleanup ourselves.
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.dwUpdateThreadStarted) {
|
||
|
|
||
|
//
|
||
|
// Tell the thread to exit
|
||
|
//
|
||
|
|
||
|
SetEvent(g_rtCfg.hUpdateThreadExit);
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// Do the cleanup ourselves
|
||
|
//
|
||
|
|
||
|
RTCleanUp();
|
||
|
|
||
|
FreeLibrary(hmodule);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Function: RTCleanUp
|
||
|
//
|
||
|
// This is called to free up resources used by the DLL.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
RTCleanUp(
|
||
|
)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Free memory for the interface table
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.lpIfTable != NULL) {
|
||
|
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Free memory for the address table
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.lpIPAddressTable != NULL) {
|
||
|
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Close the event on which we receive IP-address-change notifications
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.hDHCPEvent != NULL) { CloseHandle(g_rtCfg.hDHCPEvent); }
|
||
|
|
||
|
|
||
|
//
|
||
|
// Close the mutex protecting our tables
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.hRTMutex != NULL) { CloseHandle(g_rtCfg.hRTMutex); }
|
||
|
|
||
|
|
||
|
//
|
||
|
// Close the handle signalled to tell the update-thread to exit
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.hUpdateThreadExit != NULL) {
|
||
|
CloseHandle(g_rtCfg.hUpdateThreadExit);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Close our handle to the TCP/IP driver
|
||
|
//
|
||
|
|
||
|
if (g_rtCfg.hTCPHandle != NULL) { CloseHandle(g_rtCfg.hTCPHandle); }
|
||
|
|
||
|
|
||
|
HeapFree(GetProcessHeap(), 0, g_prtcfg);
|
||
|
}
|
||
|
|
||
|
|
||
|
|