497 lines
9.1 KiB
C
497 lines
9.1 KiB
C
/*++
|
||
|
||
Copyright (c) 2000-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
dll.c
|
||
|
||
Abstract:
|
||
|
||
Domain Name System (DNS) API
|
||
|
||
Dnsapi.dll basic DLL infrastructure (init, shutdown, etc)
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) April 2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
|
||
//
|
||
// Global Definitions
|
||
//
|
||
|
||
HINSTANCE g_hInstanceDll;
|
||
|
||
//
|
||
// Initialization level
|
||
//
|
||
|
||
DWORD g_InitLevel = 0;
|
||
|
||
//
|
||
// General purpose CS
|
||
// Protects init and any other small scale uses
|
||
//
|
||
|
||
CRITICAL_SECTION g_GeneralCS;
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// Initialization and cleanup
|
||
//
|
||
|
||
BOOL
|
||
startInit(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Minimum DLL init at process attach.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful.
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// DCR_PERF: simplified init -- simple Interlock
|
||
// then all external calls, must test the flag
|
||
// if not set do the real init (then set flag)
|
||
//
|
||
// note: init function itself must have a dumb
|
||
// wait to avoid race; this can be as simple
|
||
// as sleep\test loop
|
||
//
|
||
// multilevel init:
|
||
// have a bunch of levels of init
|
||
// - query (registry stuff)
|
||
// - update
|
||
// - secure update
|
||
//
|
||
// call would add the init for the level required
|
||
// this would need to be done under a lock to
|
||
// test, take lock, retest
|
||
//
|
||
// could either take one CS on all inits (simple)
|
||
// or init only brings stuff on line
|
||
//
|
||
|
||
InitializeCriticalSection( &g_GeneralCS );
|
||
|
||
// for debug, note that we've gotten this far
|
||
|
||
g_InitLevel = INITLEVEL_BASE;
|
||
|
||
|
||
// tracing init
|
||
|
||
Trace_Initialize();
|
||
|
||
//
|
||
// DCR_PERF: fast DLL init
|
||
//
|
||
// currently initializing everything -- like we did before
|
||
// once we get init routines (macro'd) in interfaces we
|
||
// can drop this
|
||
//
|
||
|
||
return DnsApiInit( INITLEVEL_ALL );
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
DnsApiInit(
|
||
IN DWORD InitLevel
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the DLL for some level of use.
|
||
|
||
The idea here is to avoid all the init and registry
|
||
reading for processes that don't need it.
|
||
Only insure initialization to the level required.
|
||
|
||
Arguments:
|
||
|
||
InitLevel -- level of initialization required.
|
||
|
||
Return Value:
|
||
|
||
TRUE if desired initialization is successful.
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// DCR_PERF: simplified init -- simple Interlock
|
||
// then all external calls, must test the flag
|
||
// if not set do the real init (then set flag)
|
||
//
|
||
// note: init function itself must have a dumb
|
||
// wait to avoid race; this can be as simple
|
||
// as sleep\test loop
|
||
//
|
||
// multilevel init:
|
||
// have a bunch of levels of init
|
||
// - query (registry stuff)
|
||
// - update
|
||
// - secure update
|
||
//
|
||
// call would add the init for the level required
|
||
// this would need to be done under a lock to
|
||
// test, take lock, retest
|
||
//
|
||
// could either take one CS on all inits (simple)
|
||
// or init only brings stuff on line
|
||
//
|
||
|
||
|
||
//
|
||
// check if already initialized to required level
|
||
// => if there we're done
|
||
//
|
||
// note: could check after lock for MT, but not
|
||
// unlikely and not much perf benefit over
|
||
// individual checks
|
||
//
|
||
|
||
if ( (g_InitLevel & InitLevel) == InitLevel )
|
||
{
|
||
return( TRUE );
|
||
}
|
||
|
||
EnterCriticalSection( &g_GeneralCS );
|
||
|
||
//
|
||
// heap
|
||
//
|
||
|
||
Heap_Initialize();
|
||
|
||
|
||
#if DBG
|
||
//
|
||
// init debug logging
|
||
// - do for any process beyond simple attach
|
||
//
|
||
// start logging with log filename generated to be
|
||
// unique for this process
|
||
//
|
||
// do NOT put drive specification in the file path
|
||
// do NOT set the debug flag -- the flag is read from the dnsapi.flag file
|
||
//
|
||
|
||
if ( !(g_InitLevel & INITLEVEL_DEBUG) )
|
||
{
|
||
CHAR szlogFileName[ 30 ];
|
||
|
||
sprintf(
|
||
szlogFileName,
|
||
"dnsapi.%d.log",
|
||
GetCurrentProcessId() );
|
||
|
||
Dns_StartDebug(
|
||
0,
|
||
"dnsapi.flag",
|
||
NULL,
|
||
szlogFileName,
|
||
0 );
|
||
|
||
g_InitLevel = INITLEVEL_DEBUG;
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// general query service
|
||
// - need registry info
|
||
// - need adapter list info (servlist.c)
|
||
//
|
||
// DCR: even query level doesn't need full registry info
|
||
// if either queries through cache OR gets netinfo from cache
|
||
//
|
||
// note: do NOT initialize winsock here
|
||
// WSAStartup() in dll init routine is strictly verboten
|
||
//
|
||
|
||
if ( (InitLevel & INITLEVEL_QUERY) &&
|
||
!(g_InitLevel & INITLEVEL_QUERY) )
|
||
{
|
||
DNS_STATUS status;
|
||
|
||
//
|
||
// Init registry lookup
|
||
//
|
||
|
||
status = Reg_ReadGlobalsEx( 0, NULL );
|
||
if ( status != ERROR_SUCCESS )
|
||
{
|
||
ASSERT( FALSE );
|
||
goto Failed;
|
||
}
|
||
|
||
//
|
||
// net failure caching
|
||
//
|
||
|
||
InitializeCriticalSection( &g_NetFailureCS );
|
||
g_NetFailureTime = 0;
|
||
g_NetFailureStatus = ERROR_SUCCESS;
|
||
|
||
//
|
||
// init CS to protect adapter list global
|
||
//
|
||
|
||
InitNetworkInfo();
|
||
|
||
//
|
||
// set the query timeouts
|
||
//
|
||
|
||
Dns_InitQueryTimeouts();
|
||
|
||
|
||
// indicate query init complete
|
||
|
||
g_InitLevel |= INITLEVEL_QUERY;
|
||
|
||
DNSDBG( INIT, ( "Query\\Config init is complete.\n" ));
|
||
}
|
||
|
||
//
|
||
// registration services
|
||
//
|
||
|
||
if ( (InitLevel & INITLEVEL_REGISTRATION) &&
|
||
!(g_InitLevel & INITLEVEL_REGISTRATION) )
|
||
{
|
||
InitializeCriticalSection( &g_RegistrationListCS );
|
||
InitializeCriticalSection( &g_QueueCS );
|
||
InitializeCriticalSection( &g_RegistrationThreadCS );
|
||
|
||
g_InitLevel |= INITLEVEL_REGISTRATION;
|
||
|
||
DNSDBG( INIT, ( "Registration init is complete.\n" ));
|
||
}
|
||
|
||
//
|
||
// secure update?
|
||
// - init security CS
|
||
// note, this already has built in protection -- it doesn't init
|
||
// the package, just the CS, which protects package init
|
||
//
|
||
|
||
if ( (InitLevel & INITLEVEL_SECURE_UPDATE) &&
|
||
!(g_InitLevel & INITLEVEL_SECURE_UPDATE ) )
|
||
{
|
||
Dns_StartSecurity( TRUE );
|
||
g_InitLevel |= INITLEVEL_SECURE_UPDATE;
|
||
|
||
DNSDBG( INIT, ( "Secure update init is complete.\n" ));
|
||
}
|
||
|
||
//
|
||
// clear global CS
|
||
//
|
||
|
||
LeaveCriticalSection( &g_GeneralCS );
|
||
|
||
return( TRUE );
|
||
|
||
Failed:
|
||
|
||
LeaveCriticalSection( &g_GeneralCS );
|
||
|
||
return( FALSE );
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
cleanupForExit(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Cleanup for DLL unload.
|
||
Cleanup memory and handles dnsapi.dll allocated.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// unload security packages used by secure dynamic update.
|
||
//
|
||
|
||
if ( g_InitLevel & INITLEVEL_SECURE_UPDATE )
|
||
{
|
||
Dns_TerminateSecurityPackage();
|
||
}
|
||
|
||
//
|
||
// registration stuff
|
||
//
|
||
|
||
if ( g_InitLevel & INITLEVEL_REGISTRATION )
|
||
{
|
||
DeleteCriticalSection( &g_QueueCS );
|
||
DeleteCriticalSection( &g_RegistrationListCS );
|
||
DeleteCriticalSection( &g_RegistrationThreadCS );
|
||
}
|
||
|
||
//
|
||
// query stuff
|
||
//
|
||
|
||
if ( g_InitLevel & INITLEVEL_QUERY )
|
||
{
|
||
//
|
||
// clean up Server/Net Adapter lists
|
||
//
|
||
|
||
CleanupNetworkInfo();
|
||
|
||
Dns_CacheSocketCleanup();
|
||
|
||
Dns_CleanupWinsock();
|
||
|
||
if ( g_pwsRemoteResolver )
|
||
{
|
||
FREE_HEAP( g_pwsRemoteResolver );
|
||
}
|
||
|
||
DeleteCriticalSection( &g_NetFailureCS );
|
||
}
|
||
|
||
//
|
||
// unload IP Help
|
||
//
|
||
|
||
IpHelp_Cleanup();
|
||
|
||
//
|
||
// tracing
|
||
//
|
||
|
||
Trace_Cleanup();
|
||
|
||
//
|
||
// cleanup heap
|
||
//
|
||
|
||
Heap_Cleanup();
|
||
|
||
//
|
||
// kill general CS
|
||
//
|
||
|
||
DeleteCriticalSection( &g_GeneralCS );
|
||
|
||
g_InitLevel = 0;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Main dnsapi.dll routines
|
||
//
|
||
|
||
__declspec(dllexport)
|
||
BOOL
|
||
WINAPI
|
||
DnsDllInit(
|
||
IN HINSTANCE hInstance,
|
||
IN DWORD Reason,
|
||
IN PVOID pReserved
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dll attach entry point.
|
||
|
||
Arguments:
|
||
|
||
hinstDll -- instance handle of attach
|
||
|
||
Reason -- reason for attach
|
||
DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, etc.
|
||
|
||
Reserved -- unused
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful.
|
||
FALSE on error.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// on process attach
|
||
// - disable thread notifications
|
||
// - save instance handle
|
||
// - do minimum DLL initialization
|
||
//
|
||
|
||
if ( Reason == DLL_PROCESS_ATTACH )
|
||
{
|
||
if ( ! DisableThreadLibraryCalls( hInstance ) )
|
||
{
|
||
return( FALSE );
|
||
}
|
||
g_hInstanceDll = hInstance;
|
||
|
||
return startInit();
|
||
}
|
||
|
||
//
|
||
// on process detach
|
||
// - cleanup IF pReserved==NULL which indicates detach due
|
||
// to FreeLibrary
|
||
// - if process is exiting do nothing
|
||
//
|
||
|
||
if ( Reason == DLL_PROCESS_DETACH
|
||
&&
|
||
pReserved == NULL )
|
||
{
|
||
cleanupForExit();
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// End dll.c
|
||
//
|