///////////////////////////////////////////////////////////////////////////////////////////////// // // MAINDLL.CPP // // Purpose: Contains DLL entry points. Also has code that controls // when the DLL can be unloaded by tracking the number of // objects and locks as well as routines that support // self registration. // // Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved // ///////////////////////////////////////////////////////////////////////////////////////////////// #include "precomp.h" #include #include #include "wdmdefs.h" #include #include #include HMODULE ghModule; CWMIEvent * g_pBinaryMofEvent = NULL; CCriticalSection g_EventCs; CCriticalSection g_SharedLocalEventsCs; CCriticalSection g_ListCs; CCriticalSection g_LoadUnloadCs; CCriticalSection *g_pEventCs = &g_EventCs; // pointer for backward comp CCriticalSection *g_pSharedLocalEventsCs = &g_SharedLocalEventsCs; // pointer for backward comp CCriticalSection *g_pListCs = &g_ListCs; // pointer for backward comp CCriticalSection *g_pLoadUnloadCs = &g_LoadUnloadCs; // pointer for backward comp //Count number of objects and number of locks. long g_cObj=0; long g_cLock=0; long glInits = 0; long glProvObj = 0; long glEventsRegistered = 0; #include "wmiguard.h" WmiGuard * pGuard = NULL; ///////////////////////////////////////////////////////////////////////////////////////////////// // // LibMain32 // // Purpose: Entry point for DLL. Good place for initialization. // Return: TRUE if OK. // ///////////////////////////////////////////////////////////////////////////////////////////////// BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { SetStructuredExceptionHandler seh; BOOL fRc = TRUE; try { switch( ulReason ) { case DLL_PROCESS_DETACH: { // // release binary mof changes worker // SAFE_DELETE_PTR(g_pBinaryMofEvent); if ( pGuard ) { delete pGuard; pGuard = NULL; if( g_ListCs.IsValid() ) { g_ListCs.Delete(); } if( g_EventCs.IsValid() ) { g_EventCs.Delete(); } if( g_SharedLocalEventsCs.IsValid() ) { g_SharedLocalEventsCs.Delete(); } if( g_LoadUnloadCs.IsValid() ) { g_LoadUnloadCs.Delete(); } } } break; case DLL_PROCESS_ATTACH: { if ( ( pGuard = new WmiGuard ( ) ) == NULL ) { fRc = FALSE; } else { g_LoadUnloadCs.Init(); g_SharedLocalEventsCs.Init(); g_EventCs.Init(); g_ListCs.Init(); fRc = ( g_LoadUnloadCs.IsValid() && g_SharedLocalEventsCs.IsValid() && g_EventCs.IsValid() && g_ListCs.IsValid() ) ? TRUE : FALSE ; if ( fRc ) { fRc = pGuard->Init ( g_pSharedLocalEventsCs ); if ( fRc ) { // // instantiate worker for driver's // classes addition and deletion // fRc = FALSE; HRESULT hr = WBEM_S_NO_ERROR ; try { g_pBinaryMofEvent = (CWMIEvent *)new CWMIEvent(INTERNAL_EVENT); // This is the global guy that catches events of new drivers being added at runtime. if(g_pBinaryMofEvent) { if ( g_pBinaryMofEvent->Initialized () ) { fRc = TRUE ; } else { delete g_pBinaryMofEvent ; g_pBinaryMofEvent = NULL ; } } else { } } STANDARD_CATCH } } } ghModule = hInstance; if (!DisableThreadLibraryCalls(ghModule)) { ERRORTRACE((THISPROVIDER, "DisableThreadLibraryCalls failed\n" )); } } break; } } catch(Structured_Exception e_SE) { fRc = FALSE; } catch(Heap_Exception e_HE) { fRc = FALSE; } catch(...) { fRc = FALSE; } return fRc; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // DllGetClassObject // // Purpose: Called by Ole when some client wants a a class factory. Return // one only if it is the sort of class this DLL supports. // ///////////////////////////////////////////////////////////////////////////////////////////////// STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PPVOID ppv) { HRESULT hr = CLASS_E_CLASSNOTAVAILABLE ; CProvFactory *pFactory = NULL; SetStructuredExceptionHandler seh; try { //============================================================================ // Verify the caller is asking for our type of object. //============================================================================ if((CLSID_WMIProvider != rclsid) && (CLSID_WMIEventProvider != rclsid) && (CLSID_WMIHiPerfProvider != rclsid) ) { hr = E_FAIL; } else { //============================================================================ // Check that we can provide the interface. //============================================================================ if (IID_IUnknown != riid && IID_IClassFactory != riid) { hr = E_NOINTERFACE; } else { CAutoBlock block (g_pLoadUnloadCs); //============================================================================ // Get a new class factory. //============================================================================ pFactory=new CProvFactory(rclsid); if (NULL!=pFactory) { //============================================================================ // Verify we can get an instance. //============================================================================ hr = pFactory->QueryInterface(riid, ppv); if ( FAILED ( hr ) ) { SAFE_DELETE_PTR(pFactory); } else { // // it is safe to check if this is 1st object like this // as there is no way any provider or class factory is // incrementing global refrence count // if ( 1 == g_cObj ) { // // GlobalInterfaceTable // hr = CoCreateInstance ( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void**)&g_pGIT ); // // bail out every resource // if ( FAILED ( hr ) ) { SAFE_DELETE_PTR(pFactory); SAFE_RELEASE_PTR(g_pGIT); } } } } } } } STANDARD_CATCH return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // DllCanUnloadNow // // Purpose: Called periodically by Ole in order to determine if the // DLL can be freed.// // Return: TRUE if there are no objects in use and the class factory // isn't locked. ///////////////////////////////////////////////////////////////////////////////////////////////// STDAPI DllCanUnloadNow(void) { HRESULT sc = S_FALSE ; try { CAutoBlock block (g_pLoadUnloadCs); //============================================================================ // It is OK to unload if there are no objects or locks on the // class factory. //============================================================================ if ( 0L == g_cObj && 0L == g_cLock ) { sc = S_OK ; SAFE_RELEASE_PTR(g_pGIT); } } catch ( ... ) { } return sc; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // CreateKey // // Purpose: Function to create a key // // Return: NOERROR if registration successful, error otherwise. // ///////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CreateKey(TCHAR * szCLSID, TCHAR * szName) { HKEY hKey1, hKey2; HRESULT hr = S_OK; #ifdef LOCALSERVER HKEY hKey; TCHAR szProviderCLSIDAppID[128]; if ( SUCCEEDED ( hr = StringCchPrintf ( szProviderCLSIDAppID, 128, _T("SOFTWARE\\CLASSES\\APPID\\%s"), szName ) ) ) { hr = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, szProviderCLSIDAppID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL ); if( ERROR_SUCCESS == hr ) { RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)szName, (_tcsclen(szName) + 1) * sizeof(TCHAR)); CloseHandle(hKey); } else { hr = HRESULT_FROM_WIN32 ( hr ); } } #endif if( S_OK == hr ) { hr = RegCreateKeyEx ( HKEY_CLASSES_ROOT, szCLSID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey1, NULL ); if( ERROR_SUCCESS == hr ) { DWORD dwLen; dwLen = (_tcsclen(szName)+1) * sizeof(TCHAR); hr = RegSetValueEx(hKey1, NULL, 0, REG_SZ, (CONST BYTE *)szName, dwLen); if( ERROR_SUCCESS == hr ) { #ifdef LOCALSERVER hr = RegCreateKeyEx ( hKey1, _T("LocalServer32"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey2, NULL ); #else hr = RegCreateKeyEx ( hKey1, _T("InprocServer32"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey2, NULL ); #endif if( ERROR_SUCCESS == hr ) { TCHAR szModule [MAX_PATH+1]; szModule [MAX_PATH] = 0; if ( GetModuleFileName(ghModule, szModule, MAX_PATH) ) { dwLen = (_tcsclen(szModule)+1) * sizeof(TCHAR); hr = RegSetValueEx(hKey2, NULL, 0, REG_SZ, (CONST BYTE *)szModule, dwLen ); if( ERROR_SUCCESS == hr ) { dwLen = (_tcsclen(_T("Both"))+1) * sizeof(TCHAR); hr = RegSetValueEx(hKey2, _T("ThreadingModel"), 0, REG_SZ,(CONST BYTE *)_T("Both"), dwLen); } else { hr = HRESULT_FROM_WIN32 ( hr ); } } else { hr = HRESULT_FROM_WIN32 ( ::GetLastError () ); } CloseHandle(hKey2); } else { hr = HRESULT_FROM_WIN32 ( hr ); } } CloseHandle(hKey1); } else { hr = HRESULT_FROM_WIN32 ( hr ); } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// #ifdef _X86_ BOOL IsReallyWOW64( void ) { // Environment variable should only exist on WOW64 return ( GetEnvironmentVariable( L"PROCESSOR_ARCHITEW6432", 0L, NULL ) != 0L ); } #endif STDAPI DllRegisterServer(void) { WCHAR wcID[128]; TCHAR szCLSID[128]; HRESULT hr = WBEM_E_FAILED; SetStructuredExceptionHandler seh; try{ #ifdef _X86 if (!IsReallyWOW64()) { // on 32-bit builds, we want to register everything if we are not really running in syswow64 #endif //============================================== // Create keys for WDM Instance Provider. //============================================== StringFromGUID2(CLSID_WMIProvider, wcID, 128); StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID); hr = CreateKey(szCLSID,_T("WDM Instance Provider")); if( ERROR_SUCCESS == hr ) { //============================================== // Create keys for WDM Event Provider. //============================================== StringFromGUID2(CLSID_WMIEventProvider, wcID, 128); StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID); hr = CreateKey(szCLSID,_T("WDM Event Provider")); if( ERROR_SUCCESS == hr ) { //============================================== // Create keys for WDM HiPerf Provider. //============================================== StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128); StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID); hr = CreateKey(szCLSID,_T("WDM HiPerf Provider")); } } #ifdef _X86 } else { // on 32-bit builds, we want to register only the HiPerf Provider if we are really running in syswow64 //============================================== // Create keys for WDM HiPerf Provider. //============================================== StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128); StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID); hr = CreateKey(szCLSID,_T("WDM HiPerf Provider")); } #endif } STANDARD_CATCH return hr; } ///////////////////////////////////////////////////////////////////////////////////// // // DeleteKey // // Purpose: Called when it is time to remove the registry entries. // // Return: NOERROR if registration successful, error otherwise. // ///////////////////////////////////////////////////////////////////////////////////// HRESULT DeleteKey(TCHAR * pCLSID, TCHAR * pID) { HKEY hKey; HRESULT hr = S_OK; #ifdef LOCALSERVER TCHAR szTmp[MAX_PATH]; StringCchPrintf(szTmp, MAX_PATH, _T("SOFTWARE\\CLASSES\\APPID\\%s"), pID); //Delete entries under APPID hr = RegDeleteKey(HKEY_LOCAL_MACHINE, szTmp); if( ERROR_SUCCESS == hr ) { StringCchPrintf(szTmp, MAX_PATH, _T("%s\\LocalServer32"), pCLSID); hr = RegDeleteKey(HKEY_CLASSES_ROOT, szTemp); } #endif hr = RegOpenKey(HKEY_CLASSES_ROOT, pCLSID, &hKey); if(NO_ERROR == hr) { hr = RegDeleteKey(hKey,_T("InprocServer32")); CloseHandle(hKey); } hr = RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKey); if(NO_ERROR == hr) { hr = RegDeleteKey(hKey,pID); CloseHandle(hKey); } return hr; } ///////////////////////////////////////////////////////////////////// STDAPI DllUnregisterServer(void) { WCHAR wcID[128]; TCHAR strCLSID[MAX_PATH]; HRESULT hr = WBEM_E_FAILED; try { #ifdef _X86 if (!IsReallyWOW64()) { // on 32-bit builds, we want to unregister everything if we are not really running in syswow64 #endif //=============================================== // Delete the WMI Instance Provider //=============================================== StringFromGUID2(CLSID_WMIProvider, wcID, 128); StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID); hr = DeleteKey(strCLSID, wcID); if( ERROR_SUCCESS == hr ) { //========================================== // Delete the WMI Event Provider //========================================== StringFromGUID2(CLSID_WMIEventProvider, wcID, 128); StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID); hr = DeleteKey(strCLSID,wcID); if( ERROR_SUCCESS == hr ) { //========================================== // Delete the WMI HiPerf Provider //========================================== StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128); StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID); hr = DeleteKey(strCLSID,wcID); } } #ifdef _X86 } else { // on 32-bit builds, we need to unregister only the HiPerf provider if we are really running in syswow64 //========================================== // Delete the WMI HiPerf Provider //========================================== StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128); StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID); hr = DeleteKey(strCLSID,wcID); } #endif } STANDARD_CATCH return hr; }