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
|
|||
|
//
|