//*************************************************************************** // // MAINDLL.CPP // // Module: WBEM Instance provider sample code // // 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-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include "precomp.h" #include #include #include #include #include "classfac.h" #include "genericclass.h" #include "requestobject.h" // Function pointer type used with LoadMofFiles entrypoint in wbemupgd.dll typedef BOOL ( WINAPI *PFN_LOAD_MOF_FILES )(wchar_t* pComponentName, const char* rgpszMofFilename[]); HMODULE ghModule; DEFINE_GUID(CLSID_MSIprov,0xbe0a9830, 0x2b8b, 0x11d1, 0xa9, 0x49, 0x0, 0x60, 0x18, 0x1e, 0xbb, 0xad); // {BE0A9830-2B8B-11D1-A949-0060181EBBAD} //Count number of objects and number of locks. long g_cObj=0; long g_cLock=0; //*************************************************************************** // // LibMain32 // // Purpose: Entry point for DLL. // // Return: TRUE if OK. // //*************************************************************************** BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason , LPVOID pvReserved) { BOOL retVal = TRUE; if(DLL_PROCESS_DETACH == ulReason){ DeleteCriticalSection(&g_msi_prov_cs); DeleteCriticalSection(&(CRequestObject::m_cs)); DeleteCriticalSection(&(CGenericClass::m_cs)); }else if(DLL_PROCESS_ATTACH == ulReason){ InitializeCriticalSection(&(CRequestObject::m_cs)); InitializeCriticalSection(&(CGenericClass::m_cs)); DisableThreadLibraryCalls(hInstance); // 158024 try { //for this one we can't afford to throw on lock failure. retVal = InitializeCriticalSectionAndSpinCount(&g_msi_prov_cs, 0x80000000); } catch(...) { retVal = FALSE; } } return retVal; } //*************************************************************************** // // DllGetClassObject // // Purpose: Called by Ole when some client wants a class factory. Return // one only if it is the sort of class this DLL supports. // //*************************************************************************** STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv) { HRESULT hr = 0; CProvFactory *pObj; if(CLSID_MSIprov!=rclsid) return E_FAIL; pObj = new CProvFactory(); if(NULL == pObj) return E_OUTOFMEMORY; hr = pObj->QueryInterface(riid, ppv); if(FAILED(hr)) delete pObj; return hr; } //*************************************************************************** // // DllCanUnloadNow // // Purpose: Called periodically by Ole in order to determine if the // DLL can be freed. // // Return: S_OK if there are no objects in use and the class factory // isn't locked. // //*************************************************************************** STDAPI DllCanUnloadNow(void) { SCODE sc; //It is OK to unload if there are no objects or locks on the // class factory. sc = (0L == g_cObj && 0L == g_cLock) ? S_OK : S_FALSE; if ( sc == S_OK ) { UnloadMsiDll(); if ( g_wcpLoggingDir ) { delete [] g_wcpLoggingDir; g_wcpLoggingDir = NULL; } } return sc; } BOOL IsLessThan4() { OSVERSIONINFO os; os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(!GetVersionEx(&os)) return FALSE; // should never happen return os.dwMajorVersion < 4; } //*************************************************************************** // // DllRegisterServer // // Purpose: Called during setup or by regsvr32. // // Return: NOERROR if registration successful, error otherwise. //*************************************************************************** STDAPI DllRegisterServer(void) { #ifndef UNICODE TCHAR szID[265]; #else UNICODE TCHAR* szID = NULL; #endif UNICODE WCHAR wcID[265]; TCHAR szCLSID[265]; TCHAR szModule[MAX_PATH+1]; TCHAR * pName = _T("WMI MSI Provider"); TCHAR * pModel; HKEY hKey1, hKey2; ghModule = GetModuleHandle(_T("MSIPROV")); // Normally we want to use "Both" as the threading model since // the DLL is free threaded, but NT 3.51 Ole doesnt work unless // the model is "Aparment" if(IsLessThan4()) pModel = _T("Apartment"); else pModel = _T("Both"); // Create the path. StringFromGUID2(CLSID_MSIprov, wcID, 128); #ifndef UNICODE WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, wcID, (-1), szID, 256, NULL, NULL); #else UNICODE szID = wcID; #endif UNICODE _tcscpy(szCLSID, _T("Software\\classes\\CLSID\\")); _tcscat(szCLSID, szID); #ifdef LOCALSERVER HKEY hKey; TCHAR szProviderCLSIDAppID[128]; _tcscpy(szProviderCLSIDAppID, _T("SOFTWARE\\CLASSES\\APPID\\")); _tcscat(szProviderCLSIDAppID, szID); RegCreateKey(HKEY_LOCAL_MACHINE, szProviderCLSIDAppID, &hKey); RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)pName, (_tcslen(pName)+1) * sizeof ( TCHAR )); CloseHandle(hKey); #endif RegCreateKey(HKEY_LOCAL_MACHINE, szCLSID, &hKey1); RegSetValueEx(hKey1, NULL, 0, REG_SZ, (BYTE *)pName, (_tcslen(pName)+1) * sizeof ( TCHAR )); // Create entries under CLSID #ifdef LOCALSERVER RegCreateKey(hKey1, _T("LocalServer32"), &hKey2); #else RegCreateKey(hKey1, _T("InprocServer32"), &hKey2); #endif szModule[MAX_PATH] = 0; GetModuleFileName(ghModule, szModule, MAX_PATH/*length in TCHARS*/); RegSetValueEx(hKey2, NULL, 0, REG_SZ, (BYTE *)szModule, (_tcslen(szModule)+1) * sizeof ( TCHAR )); RegSetValueEx(hKey2, _T("ThreadingModel"), 0, REG_SZ, (BYTE *)pModel, (_tcslen(pModel)+1) * sizeof ( TCHAR )); CloseHandle(hKey1); CloseHandle(hKey2); // load the MOF files for this component HRESULT hr = NOERROR; HINSTANCE hinstWbemupgd = LoadLibrary(L"wbemupgd.dll"); if (hinstWbemupgd) { PFN_LOAD_MOF_FILES pfnLoadMofFiles = (PFN_LOAD_MOF_FILES) GetProcAddress(hinstWbemupgd, "LoadMofFiles"); // no wide version of GetProcAddress if (pfnLoadMofFiles) { wchar_t* wszComponentName = L"MSI Provider"; const char* rgpszMofFilename[] = { "msi.mof", "msi.mfl", NULL }; if (!pfnLoadMofFiles(wszComponentName, rgpszMofFilename)) { hr = WBEM_E_FAILED; } } else { hr = HRESULT_FROM_WIN32(GetLastError()); } FreeLibrary(hinstWbemupgd); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; } //*************************************************************************** // // DllUnregisterServer // // Purpose: Called when it is time to remove the registry entries. // // Return: NOERROR if registration successful, error otherwise. //*************************************************************************** STDAPI DllUnregisterServer(void) { WCHAR wcID[256]; #ifndef UNICODE TCHAR szID[265]; #else UNICODE TCHAR* szID = NULL; #endif UNICODE TCHAR wcCLSID[256]; HKEY hKey; // Create the path using the CLSID StringFromGUID2(CLSID_MSIprov, wcID, 128); #ifndef UNICODE WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, wcID, (-1), szID, 256, NULL, NULL); #else UNICODE szID = wcID; #endif UNICODE _tcscpy(wcCLSID, _T("Software\\classes\\CLSID\\")); _tcscat(wcCLSID, szID); #ifdef LOCALSERVER TCHAR szProviderCLSIDAppID[128]; _tcscpy(szProviderCLSIDAppID, _T("SOFTWARE\\CLASSES\\APPID\\")); _tcscat(szProviderCLSIDAppID,wcCLSID); //Delete entries under APPID RegDeleteKey(HKEY_LOCAL_MACHINE, szProviderCLSIDAppID); TCHAR szTemp[128]; _tcscpy(szTemp, wcCLSID); _tcscat(szTemp,_T("\\")); _tcscat(szTemp,_T("LocalServer32")); RegDeleteKey(HKEY_CLASSES_ROOT, szTemp); #endif // First delete the InProcServer subkey. DWORD dwRet = RegOpenKey(HKEY_LOCAL_MACHINE, wcCLSID, &hKey); if(dwRet == NO_ERROR){ RegDeleteKey(hKey, _T("InprocServer32")); CloseHandle(hKey); } dwRet = RegOpenKey(HKEY_LOCAL_MACHINE, _T("Software\\classes\\CLSID"), &hKey); if(dwRet == NO_ERROR){ RegDeleteKey(hKey,szID); CloseHandle(hKey); } return NOERROR; }