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