// Copyright (c) 2000 Microsoft Corporation, All Rights Reserved #include "precomp.h" #include #include #include #include #include "upgrade.h" #include "wbemutil.h" #include "reg.h" #include "export.h" #include "import.h" #include #include #include #include #include #include #include //Handy pointer to the MMF arena which almost every file //to do with the on-disk representation management uses. CMMFArena2* g_pDbArena = 0; bool DoCoreUpgrade(int nInstallType ) { LogMessage(MSG_INFO, "Beginning Core Upgrade"); bool bRet = true; bool bCoreFailure = false; bool bExternalFailure = false; bool bOrgRepositoryPreserved = false; CMultiString mszSystemMofs; CMultiString mszExternalMofList; CString szFailedSystemMofs; CString szFailedExternalMofs; CString szMissingMofs; Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for DoCoreUpgrade."); return false; } IWbemContext * pCtx = NULL; HRESULT hRes = CoCreateInstance(CLSID_WbemContext, 0, CLSCTX_INPROC_SERVER, IID_IWbemContext, (LPVOID *) &pCtx); if (FAILED(hRes)) { LogMessage(MSG_ERROR, "Unable to create CLSID_WbemContext."); return false; } OnDelete rmCtx(pCtx); _variant_t Var = true; if (FAILED(hRes = pCtx->SetValue(L"__MOFD_DO_STORE",0,&Var))) return false; IWinmgmtMofCompiler * pCompiler = NULL; SCODE sc = CoCreateInstance(CLSID_WinmgmtMofCompiler, 0, CLSCTX_INPROC_SERVER, IID_IWinmgmtMofCompiler, (LPVOID *) &pCompiler); if(SUCCEEDED(sc)) { GetStandardMofs(mszSystemMofs, nInstallType); UpgradeAutoRecoveryRegistry(mszSystemMofs, mszExternalMofList, szMissingMofs); WipeOutAutoRecoveryRegistryEntries(); if (DoesFSRepositoryExist()) { // check whether repository needs upgrading, and perform upgrade if necessary bOrgRepositoryPreserved = UpgradeRepository(); } // if we find an MMF, convert it, regardless of whether another repository already exists if (DoesMMFRepositoryExist()) { bOrgRepositoryPreserved = DoConvertRepository(); } bRet = LoadMofList(pCtx,pCompiler, mszSystemMofs, szFailedSystemMofs); if (bRet == false) bCoreFailure = true; // if the repository did not exist when we began, // or we had to create a new one due to an upgrade failure, // we need to reload external mofs if (!bOrgRepositoryPreserved) { bRet = LoadMofList(pCtx,pCompiler, mszExternalMofList, szFailedExternalMofs); if (bRet == false) bExternalFailure = true; } pCompiler->Release(); //Part of the tidy-up code is to write back the registry entries, so here we go... WriteBackAutoRecoveryMofs(mszSystemMofs, mszExternalMofList); FILETIME ftCurTime; LARGE_INTEGER liCurTime; char szBuff[50]; GetSystemTimeAsFileTime(&ftCurTime); liCurTime.LowPart = ftCurTime.dwLowDateTime; liCurTime.HighPart = ftCurTime.dwHighDateTime; _ui64toa(liCurTime.QuadPart, szBuff, 10); r.SetStr("Autorecover MOFs timestamp", szBuff); } else { bRet = false; } if (szFailedSystemMofs.Length()) { LogMessage(MSG_ERROR, "The following WMI CORE MOF file(s) failed to load:"); LogMessage(MSG_ERROR, szFailedSystemMofs); } else if (bCoreFailure) { LogMessage(MSG_NTSETUPERROR, "None of the WMI CORE MOFs could be loaded."); } else if (szFailedExternalMofs.Length()) { LogMessage(MSG_ERROR, "The following External MOF file(s) failed to load:"); LogMessage(MSG_ERROR, szFailedExternalMofs); } else if (bExternalFailure) { LogMessage(MSG_NTSETUPERROR, "None of the External MOFs could be loaded."); } else if (bRet == false) { LogMessage(MSG_NTSETUPERROR, "No MOFs could be loaded because the MOF Compiler failed to intialize."); } if (szMissingMofs.Length()) { LogMessage(MSG_WARNING, "The following MOFs could not be found and were removed from the auto-recovery registry setting:"); LogMessage(MSG_WARNING, szMissingMofs); } LogMessage(MSG_INFO, "Core Upgrade completed."); return bRet; } bool UpgradeAutoRecoveryRegistry(CMultiString &mszSystemMofs, CMultiString &mszExternalMofList, CString &szMissingMofs) { char* pszNewList = NULL; char* pszEmptyList = NULL; char* pszRecoveredList = NULL; try { //First we need to recover the existing entries... Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for UpgradeAutoRecoveryRegistry."); return false; } DWORD dwSize = 0; pszNewList = r.GetMultiStr(WBEM_REG_AUTORECOVER, dwSize); pszEmptyList = r.GetMultiStr(WBEM_REG_AUTORECOVER_EMPTY, dwSize); pszRecoveredList = r.GetMultiStr(WBEM_REG_AUTORECOVER_RECOVERED, dwSize); CMultiString mszOtherMofs; //Lets work through the list in the new mof list if it exists... GetNewMofLists(pszNewList, mszSystemMofs, mszOtherMofs, szMissingMofs); //Lets work through the empty list first... GetNewMofLists(pszEmptyList, mszSystemMofs, mszOtherMofs, szMissingMofs); //Lets work through the recovered list next... GetNewMofLists(pszRecoveredList, mszSystemMofs, mszOtherMofs, szMissingMofs); //Now we copy across the other MOFs to the external list... CopyMultiString(mszOtherMofs, mszExternalMofList); } catch (...) { // assume something has corrupted the registry key, so toss out the work we've done so far (empty the lists) mszExternalMofList.Empty(); szMissingMofs = ""; } //Tidy up the memory... delete [] pszNewList; delete [] pszEmptyList; delete [] pszRecoveredList; //Now we are done with the registry. return true; } bool GetNewMofLists(const char *pszMofList, CMultiString &mszSystemMofs, CMultiString &mszOtherMofs, CString &szMissingMofs) { // produce a standard mof list with only filenames and no paths to be used as our search list CMultiString mszStandardMofList; const char* pszFrom = mszSystemMofs; CString path; CString filename; while (pszFrom && *pszFrom) { ExtractPathAndFilename(pszFrom, path, filename); mszStandardMofList.AddUnique(filename); pszFrom += strlen(pszFrom) + 1; } // check each file to see if it is a standard mof const char *psz = pszMofList; while (psz && *psz) { if (FileExists(psz)) { if (IsStandardMof(mszStandardMofList, psz)) { // This means we will be loading it with this install, // so we don't need to do anything here... } else { mszOtherMofs.AddUnique(psz); } } else { if (szMissingMofs.Length()) { szMissingMofs += "\n"; } szMissingMofs += psz; } //Move on to the next string... psz += strlen(psz) + 1; } return true; } bool GetMofList(const char* rgpszMofFilename[], CMultiString &mszMofs) { char* pszFullName = NULL; for (int i = 0; rgpszMofFilename[i] != NULL; i++) { pszFullName = GetFullFilename(rgpszMofFilename[i]); if (pszFullName) { if (FileExists(pszFullName)) mszMofs.AddUnique(pszFullName); delete [] pszFullName; pszFullName = NULL; } else { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Failed GetFullFilename for %s in GetMofList.", rgpszMofFilename[i]); LogMessage(MSG_ERROR, szTemp); // do not return false here, keep processing other mofs } } return true; } bool FileExists(const char *pszFilename) { char *szExpandedFilename = NULL; DWORD nRes = ExpandEnvironmentStrings(pszFilename,NULL,0); if (nRes == 0) { size_t fileNameLen = strlen(pszFilename) + 1; szExpandedFilename = new char[fileNameLen]; if (szExpandedFilename == NULL) { return false; } StringCchCopyA(szExpandedFilename, fileNameLen, pszFilename); } else { szExpandedFilename = new char[nRes]; if (szExpandedFilename == NULL) { return false; } nRes = ExpandEnvironmentStrings(pszFilename,szExpandedFilename,nRes); if (nRes == 0) { delete [] szExpandedFilename; return false; } } bool bExists = false; DWORD dwAttribs = GetFileAttributes(szExpandedFilename); if (dwAttribs != 0xFFFFFFFF) { bExists = true; } delete [] szExpandedFilename; return bExists; } bool IsStandardMof(CMultiString &mszStandardMofList, const char* pszMofFile) { //For this one we need to loop though our standard MOF list to see if it appears //in the list. Ignore the path if present and compare only the filename. CString path; CString filename; ExtractPathAndFilename(pszMofFile, path, filename); bool bFound = false; const char* pszCompare = mszStandardMofList; while (pszCompare && *pszCompare) { if (_stricmp(pszCompare, filename) == 0) { bFound = true; break; } pszCompare += strlen(pszCompare) + 1; } return bFound; } bool ExtractPathAndFilename(const char *pszFullPath, CString &path, CString &filename) { size_t tmpNameLen = strlen(pszFullPath) + 1; char *pszTmpName = new char[tmpNameLen]; if (pszTmpName == NULL) return false; StringCchCopyA(pszTmpName, tmpNameLen, pszFullPath); char *pszFilename = pszTmpName; char *psz = strtok(pszTmpName, "\\"); while (psz != NULL) { pszFilename = psz; psz = strtok(NULL, "\\"); if (psz != NULL) { path += pszFilename; path += "\\"; } } filename = pszFilename; delete [] pszTmpName; return true; } bool CopyMultiString(CMultiString &mszFrom, CMultiString &mszTo) { const char *pszFrom = mszFrom; while (pszFrom && *pszFrom) { //Due to the fact that we should not have duplicates in the list, we will now do //a check to inforce this... mszTo.AddUnique(pszFrom); pszFrom += strlen(pszFrom) + 1; } return true; } bool GetStandardMofs(CMultiString &mszSystemMofs, int nCurInstallType) { // find the location of the inf char* pszWinDir = new char[_MAX_PATH+1]; if (!pszWinDir) { LogMessage(MSG_ERROR, "Failed to allocate memory for pszWinDir for GetStandardMofs."); return FALSE; } if (!GetWindowsDirectory(pszWinDir, _MAX_PATH+1)) { LogMessage(MSG_ERROR, "Failed to retrieve Windows directory for GetStandardMofs."); delete [] pszWinDir; return FALSE; } size_t fileNameLen = strlen(pszWinDir)+strlen("\\inf\\wbemoc.inf")+1; char* pszFileName = new char[fileNameLen]; if (!pszFileName) { LogMessage(MSG_ERROR, "Failed to allocate memory for pszFileName for GetStandardMofs."); delete [] pszWinDir; return FALSE; } StringCchCopyA(pszFileName, fileNameLen, pszWinDir); StringCchCatA(pszFileName, fileNameLen, "\\inf\\wbemoc.inf"); delete [] pszWinDir; // verify that inf exists if (!FileExists(pszFileName)) { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Failed to locate inf file %s in GetStandardMofs.", pszFileName); LogMessage(MSG_ERROR, szTemp); delete [] pszFileName; return FALSE; } // GetPrivateProfileSection doesn't tell how large of a buffer is needed, // only how many chars it succeeded in copying, so I have to test to see // if I need to enlarge the buffer and try again const DWORD INITIAL_BUFFER_SIZE = 700; const DWORD BUFFER_SIZE_INCREMENT = 100; DWORD dwSize = INITIAL_BUFFER_SIZE; char* pszBuffer = new char[dwSize]; if (!pszBuffer) { LogMessage(MSG_ERROR, "Failed to allocate memory for pszBuffer for GetStandardMofs."); delete [] pszFileName; return FALSE; } char* pszAppName = "WBEM.SYSTEMMOFS"; DWORD dwCopied = GetPrivateProfileSection(pszAppName, pszBuffer, dwSize, pszFileName); // if buffer isn't large enough, it copies dwSize - 2, so test for this while (dwCopied == (dwSize - 2)) { delete [] pszBuffer; dwSize += BUFFER_SIZE_INCREMENT; pszBuffer = new char[dwSize]; if (!pszBuffer) { LogMessage(MSG_ERROR, "Failed to allocate memory for pszBuffer for GetStandardMofs."); delete [] pszFileName; return FALSE; } dwCopied = GetPrivateProfileSection(pszAppName, pszBuffer, dwSize, pszFileName); } delete [] pszFileName; // now extract all the mofs from the buffer, get the full path, and store in the mof list char* pszFullName = NULL; char* psz = pszBuffer; char* pComment = NULL; while (psz[0] != '\0') { // if a comment is present after the filename, this will cut it off if (pComment = strchr(psz, ';')) { psz = strtok(psz, " \t;"); // there may be leading space or tabs as well as the semicolon } pszFullName = GetFullFilename(psz, (InstallType)nCurInstallType); if (pszFullName) { if (nCurInstallType != MUI || strstr(_strupr(pszFullName), ".MFL") != NULL) { if (FileExists(pszFullName)) mszSystemMofs.AddUnique(pszFullName); else { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "GetStandardMofs failed to locate file %s.", pszFullName); LogMessage(MSG_ERROR, szTemp); } } delete [] pszFullName; pszFullName = NULL; } else { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Failed GetFullFilename for %s with install type = %i in GetStandardMofs.", psz, nCurInstallType); LogMessage(MSG_ERROR, szTemp); // do not return false here, keep processing other mofs } psz += (strlen(psz) + 1); if (pComment) { // skip over the comment at the end of the line psz += (strlen(psz) + 1); pComment = NULL; } } delete [] pszBuffer; return true; } char* GetFullFilename(const char *pszFilename, InstallType eInstallType) { char *pszDirectory = NULL; Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for GetFullFilename."); return NULL; } if (r.GetStr("Working Directory", &pszDirectory)) { LogMessage(MSG_ERROR, "Unable to retrieve Installation Directory from registry for GetFullFilename."); return NULL; } CString pszPathFilename(pszDirectory); if (eInstallType == MUI) { if (pszPathFilename.Length() && (pszPathFilename[pszPathFilename.Length()-1] != '\\')) { pszPathFilename += "\\MUI\\"; pszPathFilename += g_szLangId; } } if (pszPathFilename.Length() && (pszPathFilename[pszPathFilename.Length()-1] != '\\')) { pszPathFilename += "\\"; } pszPathFilename += pszFilename; delete [] pszDirectory; return pszPathFilename.Unbind(); } bool WipeOutAutoRecoveryRegistryEntries() { Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for WipeOutAutoRecoveryRegistryEntries."); return false; } else { r.SetMultiStr(WBEM_REG_AUTORECOVER, "\0", 2); r.DeleteEntry(WBEM_REG_AUTORECOVER_EMPTY); r.DeleteEntry(WBEM_REG_AUTORECOVER_RECOVERED); return true; } } bool DoesMMFRepositoryExist() { Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for DoesMMFRepositoryExist."); return false; } char *pszDbDir = NULL; if (r.GetStr("Repository Directory", &pszDbDir)) { LogMessage(MSG_ERROR, "Unable to retrieve Repository Directory from registry for DoesMMFRepositoryExist."); return false; } if (!pszDbDir) { LogMessage(MSG_ERROR, "Unable to retrieve Repository Directory from registry for DoesMMFRepositoryExist."); return false; } CString szDbFilename(pszDbDir); if (szDbFilename.Length() != 0) szDbFilename += "\\"; szDbFilename += "cim.rep"; delete [] pszDbDir; return FileExists(szDbFilename); } bool DoesFSRepositoryExist() { Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for DoesMMFRepositoryExist."); return false; } char *pszDbDir = NULL; if (r.GetStr("Repository Directory", &pszDbDir)) { LogMessage(MSG_ERROR, "Unable to retrieve Repository Directory from registry for DoesMMFRepositoryExist."); return false; } if (!pszDbDir || (strlen(pszDbDir) == 0)) { LogMessage(MSG_ERROR, "Unable to retrieve Repository Directory from registry for DoesMMFRepositoryExist."); return false; } CString szDbFilename1(pszDbDir); szDbFilename1 += "\\FS\\MainStage.dat"; CString szDbFilename2(pszDbDir); szDbFilename2 += "\\FS\\LowStage.dat"; delete [] pszDbDir; return FileExists(szDbFilename1)||FileExists(szDbFilename2); } // This function is used to detect an earlier post-MMF repository version and upgrade it // Returns TRUE if repository upgrade succeeded; FALSE in all other cases bool UpgradeRepository() { LogMessage(MSG_INFO, "Beginning repository upgrade"); bool bRet = false; IWbemLocator *pLocator = NULL; HRESULT hr = CoCreateInstance(CLSID_WbemLocator,NULL, CLSCTX_ALL, IID_IWbemLocator,(void**)&pLocator); if(FAILED(hr)) { LogMessage(MSG_ERROR, "WMI Repository upgrade failed CoCreateInstance."); return bRet; } IWbemServices *pNamespace = NULL; BSTR tmpStr = SysAllocString(L"root"); hr = pLocator->ConnectServer(tmpStr, NULL, NULL, NULL, NULL, NULL, NULL, &pNamespace); if (SUCCEEDED(hr)) { pNamespace->Release(); LogMessage(MSG_INFO, "WMI Repository upgrade succeeded."); bRet = true; } else { if (hr == WBEM_E_DATABASE_VER_MISMATCH) { LogMessage(MSG_ERROR, "WMI Repository upgrade failed with WBEM_E_DATABASE_VER_MISMATCH."); // shut down so we can delete the repository ShutdownWinMgmt(); // delete the repository so it can be rebuilt // try multiple times in case winmgmt hasn't shut down yet int nTry = 20; while (nTry--) { hr = MoveRepository(); if (SUCCEEDED(hr)) { break; } Sleep(500); } if (FAILED(hr)) { LogMessage(MSG_ERROR, "WMI Repository upgrade failed to move repository to backup location."); } } else { LogMessage(MSG_ERROR, "WMI Repository upgrade failed ConnectServer."); } } SysFreeString(tmpStr); pLocator->Release(); LogMessage(MSG_INFO, "Repository upgrade completed."); return bRet; } // This function is used to convert an old MMF repository to the current default repository bool DoConvertRepository() { // get MMF filename Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for DoConvertRepository."); return false; } char* pszDbDir = NULL; if (r.GetStr("Repository Directory", &pszDbDir)) { LogMessage(MSG_ERROR, "Unable to get repository directory from registry for DoConvertRepository"); return false; } if (!pszDbDir) { LogMessage(MSG_ERROR, "Unable to get repository directory from registry for DoConvertRepository"); return false; } CString szDbFilename(pszDbDir); delete [] pszDbDir; if (szDbFilename.Length() != 0) szDbFilename += "\\"; szDbFilename += "cim.rep"; // check that MMF really exists if (!FileExists(szDbFilename)) { LogMessage(MSG_ERROR, "MMF Repository does not exist."); return false; } { //Scope so that we delete the g_pDbArena before we try to delete the file // create arena and load MMF g_pDbArena = new CMMFArena2(); if (g_pDbArena == 0) { LogMessage(MSG_ERROR, "Unable to create CMMFArena2"); return false; } CDeleteMe delMe1(g_pDbArena); if (!g_pDbArena->LoadMMF(szDbFilename) || (g_pDbArena->GetStatus() != no_error)) { LogMessage(MSG_ERROR, "Error opening existing MMF"); return false; } // get export filename TCHAR *pszFilename = GetFullFilename(WINMGMT_DBCONVERT_NAME); if (pszFilename == 0) { LogMessage(MSG_ERROR, "Unable to get DB name"); return false; } CVectorDeleteMe delMe2(pszFilename); // determine version of exporter to use CRepExporter* pExporter = NULL; DWORD dwVersion = g_pDbArena->GetVersion(); MsgType msgType = MSG_INFO; char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Upgrading repository format. Repository format version detected %lu.", dwVersion); switch (dwVersion) { case INTERNAL_DATABASE_VERSION: { pExporter = new CRepExporterV9; break; } case 3: //450 build { pExporter = new CRepExporterV1; break; } case 5: //500 series case 6: //600 series Nova M1 { pExporter = new CRepExporterV5; break; } case 7: //900 series Nova M3 first attempt! case 8: //900 series... has null key trees until instance created { pExporter = new CRepExporterV7; break; } case 10: //9x version of version 9! { pExporter = new CRepExporterV9; break; } default: { StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Unsupported repository version detected. Version found = %lu, version expected = %lu.", dwVersion, DWORD(INTERNAL_DATABASE_VERSION)); msgType = MSG_ERROR; } } LogMessage(msgType, szTemp); // do we have an exporter? if (!pExporter) { LogMessage(MSG_ERROR, "Unable to create exporter object."); return false; } CDeleteMe delMe3(pExporter); // export the old repository if (pExporter->Export(g_pDbArena, pszFilename) != no_error) { LogMessage(MSG_ERROR, "Failed to export old WMI Repository."); return false; } // create new repository and import into it using IWbemServices CRepImporter import; if (import.ImportRepository(pszFilename) != no_error) { LogMessage(MSG_ERROR, "Failed to import data from old WMI Repository."); return false; } DeleteFile(pszFilename); } // conversion was successful, so now delete the old stuff DeleteMMFRepository(); return true; } void DeleteMMFRepository() { Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for DeleteMMFRepository."); return; } char* pszDbDir = NULL; if (r.GetStr("Repository Directory", &pszDbDir)) { LogMessage(MSG_ERROR, "Unable to get repository directory from registry for DeleteMMFRepository"); return; } if (!pszDbDir) { LogMessage(MSG_ERROR, "Unable to get repository directory from registry for DeleteMMFRepository"); return; } CString szDbFilename(pszDbDir); if (szDbFilename.Length() != 0) szDbFilename += "\\"; szDbFilename += "cim.rep"; CString szDbBackup(pszDbDir); if (szDbBackup.Length() != 0) szDbBackup += "\\"; szDbBackup += "cim.rec"; CString szDbNewFilename(pszDbDir); if (szDbNewFilename.Length() != 0) szDbNewFilename += "\\"; szDbNewFilename += "cim.bak"; delete [] pszDbDir; DeleteFile(szDbFilename); DeleteFile(szDbBackup); DeleteFile(szDbNewFilename); } void ShutdownWinMgmt() { PROCESS_INFORMATION pi; STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); //Try killing WinMgmt char *pszFullPath = GetFullFilename("Winmgmt.exe"); if (!pszFullPath) { LogMessage(MSG_NTSETUPERROR, "Could not shut down Winmgmt -- failed to get full path to Winmgmt.exe."); return; } size_t cmdLineLen = strlen("Winmgmt /kill") + 1; char *pszCommandLine = new char[cmdLineLen]; if (!pszCommandLine) { LogMessage(MSG_NTSETUPERROR, "Could not shut down Winmgmt -- failed to allocate memory."); return; } StringCchCopyA(pszCommandLine, cmdLineLen, "Winmgmt /kill"); if (CreateProcess(pszFullPath, pszCommandLine, 0, 0, FALSE, 0, 0, 0, &si, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); Sleep(10000); } else { LogMessage(MSG_NTSETUPERROR, "Could not shut down Winmgmt -- failed to create process for Winmgmt.exe."); } delete [] pszCommandLine; delete [] pszFullPath; } /****************************************************************************** * * GetRepositoryDirectory * * Description: * Retrieves the location of the repository directory from the registry. * * Parameters: * wszRepositoryDirectory: Array to store location in. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1]) { HKEY hKey; long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey); if(lRes) return WBEM_E_FAILED; wchar_t wszTmp[MAX_PATH + 1]; DWORD dwLen = (MAX_PATH + 1)*sizeof(wchar_t); lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen); RegCloseKey(hKey); if(lRes) return WBEM_E_FAILED; if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0) return WBEM_E_FAILED; return WBEM_S_NO_ERROR; } HRESULT GetLoggingDirectory(wchar_t wszLoggingDirectory[MAX_PATH+1]) { HKEY hKey; long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey); if(lRes) return WBEM_E_FAILED; wchar_t wszTmp[MAX_PATH + 1]; DWORD dwLen = sizeof(wszTmp); lRes = RegQueryValueExW(hKey, L"Logging Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen); RegCloseKey(hKey); if(lRes) return WBEM_E_FAILED; if (ExpandEnvironmentStringsW(wszTmp,wszLoggingDirectory, MAX_PATH + 1) == 0) return WBEM_E_FAILED; return WBEM_S_NO_ERROR; } /****************************************************************************** * * MoveRepository * * Description: * Move all files and directories under the repository directory * to a backup location. The repository directory location is retrieved * from the registry. * * Parameters: * * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT MoveRepository() { HRESULT hres = WBEM_S_NO_ERROR; wchar_t wszRepositoryDirectory[MAX_PATH+1]; wchar_t wszRepositoryMove[MAX_PATH+1]; //Get the root directory of the repository hres = GetRepositoryDirectory(wszRepositoryDirectory); if (SUCCEEDED(hres)) { for (int i=1; i<999; i++) { StringCchPrintfW(wszRepositoryMove, MAX_PATH+1, L"%s.%03i", wszRepositoryDirectory, i); if (GetFileAttributesW(wszRepositoryMove) == 0xFFFFFFFF) break; } if (!MoveFileW(wszRepositoryDirectory, wszRepositoryMove)) hres = WBEM_E_FAILED; else { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "wbemupgd.dll: The WMI repository has failed to upgrade. " "The repository has been backed up to %S and a new one created.", wszRepositoryMove); LogMessage(MSG_NTSETUPERROR, szTemp); } } return hres; } bool LoadMofList(IWbemContext * pCtx, IWinmgmtMofCompiler * pCompiler, const char *mszMofs, CString &szMOFFailureList, long lOptionFlags, long lClassFlags) { LogMessage(MSG_INFO, "Beginning MOF load"); bool bRet = true; WCHAR wFileName[MAX_PATH+1]; const char *pszMofs = mszMofs; char szTemp[MAX_MSG_TEXT_LENGTH+1]; WBEM_COMPILE_STATUS_INFO statusInfo; // get logging directory or default if failed wchar_t wszMofcompLog[MAX_PATH+1]; HRESULT hres = GetLoggingDirectory(wszMofcompLog); if (SUCCEEDED(hres)) { StringCchCatW(wszMofcompLog, MAX_PATH+1, L"mofcomp.log"); } else { StringCchCopyW(wszMofcompLog, MAX_PATH+1, L"\\system32\\wbem\\logs\\mofcomp.log"); } // process each MOF while (*pszMofs != '\0') { char *szExpandedFilename = NULL; DWORD nRes = ExpandEnvironmentStrings(pszMofs,NULL,0); if (nRes == 0) { size_t expandedFilenameLen = strlen(pszMofs) + 1; szExpandedFilename = new char[expandedFilenameLen]; if (szExpandedFilename == NULL) { LogMessage(MSG_INFO, "Failed allocating memory for szExpandedFilename - 1."); bRet = false; break; } StringCchCopyA(szExpandedFilename, expandedFilenameLen, pszMofs); } else { szExpandedFilename = new char[nRes]; if (szExpandedFilename == NULL) { LogMessage(MSG_INFO, "Failed allocating memory for szExpandedFilename - 2."); bRet = false; break; } nRes = ExpandEnvironmentStrings(pszMofs,szExpandedFilename,nRes); if (nRes == 0) { LogMessage(MSG_INFO, "Failed expanding environment strings."); delete [] szExpandedFilename; bRet = false; break; } } StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "Processing %s", szExpandedFilename); LogMessage(MSG_INFO, szTemp); //Call MOF Compiler with (pszMofs); mbstowcs(wFileName, szExpandedFilename, MAX_PATH+1); SCODE sRet = pCompiler->WinmgmtCompileFile(wFileName, NULL, lOptionFlags, lClassFlags, 0, NULL, pCtx, &statusInfo); if (sRet != S_OK) { //This MOF failed to load. if (szMOFFailureList.Length()) szMOFFailureList += "\n"; szMOFFailureList += szExpandedFilename; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "An error occurred while compiling the following MOF file: %s " "Please refer to %S for more detailed information.", szExpandedFilename, wszMofcompLog); LogMessage(MSG_NTSETUPERROR, szTemp); bRet = false; } delete [] szExpandedFilename; //Move on to the next string pszMofs += strlen(pszMofs) + 1; } // end while LogMessage(MSG_INFO, "MOF load completed."); return bRet; } bool WriteBackAutoRecoveryMofs(CMultiString &mszSystemMofs, CMultiString &mszExternalMofList) { CMultiString mszNewList; CopyMultiString(mszSystemMofs, mszNewList); CopyMultiString(mszExternalMofList, mszNewList); Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { LogMessage(MSG_ERROR, "Unable to access registry for WriteBackAutoRecoverMofs."); return false; } r.SetMultiStr(WBEM_REG_AUTORECOVER, mszNewList, mszNewList.Length() + 1); return true; } void LogMessage(MsgType msgType, const char *pszMessage) { //Load messages from the resource char pszSetupMessage[10]; switch (msgType) { case MSG_NTSETUPERROR: LogSetupError(pszMessage); // now fall through to next case case MSG_ERROR: StringCchCopyA(pszSetupMessage, 10, "ERROR: "); break; case MSG_WARNING: StringCchCopyA(pszSetupMessage, 10, "WARNING: "); break; case MSG_INFO: default: StringCchCopyA(pszSetupMessage, 10, ""); break; } size_t newMessageLen = strlen(pszMessage) + 1; char* pszNewMessage = new char[newMessageLen]; if (!pszNewMessage) { // we failed to allocate memory for the message, so no logging :( return; } StringCchCopyA(pszNewMessage, newMessageLen, pszMessage); // get log file path and name Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() != no_error) { // no messages will be logged because we don't know where to write the log :( delete [] pszNewMessage; return; } char* pszFullDirectory = NULL; if (r.GetStr("Logging Directory", &pszFullDirectory)) { // no messages will be logged because we don't know where to write the log :( delete [] pszNewMessage; return; } if (!pszFullDirectory) { // no messages will be logged because we don't know where to write the log :( delete [] pszNewMessage; return; } char* pszFilename = "setup.log"; size_t fullPathLen = strlen(pszFullDirectory) + strlen("\\") + strlen(pszFilename) + 1; char* pszFullPath = new char [fullPathLen]; if (!pszFullPath) { // we failed to allocate memory for the path, so no logging :( delete [] pszNewMessage; return; } StringCchCopyA(pszFullPath, fullPathLen, pszFullDirectory); StringCchCatA(pszFullPath, fullPathLen, "\\"); StringCchCatA(pszFullPath, fullPathLen, pszFilename); delete [] pszFullDirectory; // Get time char timebuf[64]; time_t now = time(0); struct tm *local = localtime(&now); if(local) { StringCchCopyA(timebuf, 64, asctime(local)); timebuf[strlen(timebuf) - 1] = 0; } else StringCchCopyA(timebuf,64, "unknown time"); size_t timeLen = strlen(timebuf) + strlen("(): ") + 1; char* pszTime = new char [timeLen]; if (!pszTime) { // we failed to allocate memory for the time, so no logging :( delete [] pszNewMessage; delete [] pszFullPath; return; } StringCchCopyA(pszTime, timeLen, "("); StringCchCatA(pszTime, timeLen, timebuf); StringCchCatA(pszTime, timeLen, "): "); // write messages to log file HANDLE hFile = CreateFile(pszFullPath, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hFile != INVALID_HANDLE_VALUE) { const char* pszCR = "\r\n"; char* psz; DWORD dwWritten; SetFilePointer(hFile, 0, 0, FILE_END); psz = strtok(pszNewMessage, "\n"); while (psz) { WriteFile(hFile, pszTime, strlen(pszTime), &dwWritten, 0); WriteFile(hFile, pszSetupMessage, strlen(pszSetupMessage), &dwWritten, 0); WriteFile(hFile, psz, strlen(psz), &dwWritten, 0); WriteFile(hFile, pszCR, strlen(pszCR), &dwWritten, 0); psz = strtok(NULL, "\n"); } CloseHandle(hFile); } delete [] pszNewMessage; delete [] pszFullPath; delete [] pszTime; } void LogSetupError(const char *pszMessage) { size_t tempLen = strlen(pszMessage) + 1; char* pszTemp = new char[tempLen]; if (!pszTemp) { // we failed to allocate memory for the message, so no logging :( return; } StringCchCopyA(pszTemp, tempLen, pszMessage); char* psz; char* pszMessageLine; const char* pszCR = "\r\n"; psz = strtok(pszTemp, "\n"); while (psz) { size_t messageLineLen = strlen(psz) + strlen(pszCR) + 1; pszMessageLine = new char[messageLineLen]; if (!pszMessageLine) { delete [] pszTemp; return; } StringCchCopyA(pszMessageLine, messageLineLen, psz); StringCchCatA(pszMessageLine, messageLineLen, pszCR); SetupLogError(pszMessageLine, LogSevError); delete [] pszMessageLine; psz = strtok(NULL, "\n"); } delete [] pszTemp; } void ClearWMISetupRegValue() { Registry r(WBEM_REG_WINMGMT); if (r.GetStatus() == no_error) r.SetStr("WMISetup", "0"); else LogMessage(MSG_NTSETUPERROR, "Unable to clear WMI setup reg value."); r.DeleteEntry("KnownSvcs"); } void SetWBEMBuildRegValue() { Registry r(WBEM_REG_WBEM); if (r.GetStatus() != no_error) { LogMessage(MSG_NTSETUPERROR, "Unable to set WBEM build reg value."); return; } char* pszBuildNo = new char[10]; OSVERSIONINFO os; os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&os)) { StringCchPrintfA(pszBuildNo, 10, "%lu.0000", os.dwBuildNumber); } r.SetStr("Build", pszBuildNo); delete [] pszBuildNo; } void RecordFileVersion() { DWORD dwHandle; DWORD dwLen = GetFileVersionInfoSizeW(L"wbemupgd.dll", &dwHandle); if (dwLen) { BYTE* lpData = new BYTE[dwLen]; if (lpData) { if (GetFileVersionInfoW(L"wbemupgd.dll", dwHandle, dwLen, lpData)) { struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; } *lpTranslate; UINT cbTranslate; if (VerQueryValueW(lpData, L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate)) { wchar_t* pswzSubBlock = new wchar_t[dwLen]; wchar_t* pwszFileVersion = NULL; UINT cbBytes; for(UINT i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++) { StringCchPrintfW(pswzSubBlock, dwLen, L"\\StringFileInfo\\%04x%04x\\FileVersion", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage); // Retrieve file description for language and code page "i". if (VerQueryValueW(lpData, pswzSubBlock, (LPVOID*)&pwszFileVersion, &cbBytes)) { if (cbBytes) { wchar_t wszTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfW(wszTemp, MAX_MSG_TEXT_LENGTH, L"Current build of wbemupgd.dll is %s", pwszFileVersion); // once LogMessage is updated to handle wchars, this conversion can be removed char* szTemp = new char[MAX_MSG_TEXT_LENGTH+1]; if (szTemp) { wcstombs(szTemp, wszTemp, MAX_MSG_TEXT_LENGTH+1); LogMessage(MSG_INFO, szTemp); delete [] szTemp; } } } } delete [] pswzSubBlock; } } delete [] lpData; } } } void CallEscapeRouteBeforeMofCompilation() { HMODULE hDll = NULL; ESCDOOR_BEFORE_MOF_COMPILATION pfnEscRouteBeforeMofCompilation; char *pszFullPath = GetFullFilename("WmiEscpe.dll"); if (!pszFullPath) return; hDll = LoadLibrary(pszFullPath); delete[] pszFullPath; if(hDll == NULL) { return; } pfnEscRouteBeforeMofCompilation = (ESCDOOR_BEFORE_MOF_COMPILATION)GetProcAddress((HMODULE)hDll, "EscRouteBeforeMofCompilation"); if (pfnEscRouteBeforeMofCompilation == NULL) { if(hDll != NULL) FreeLibrary(hDll); return; } pfnEscRouteBeforeMofCompilation(); if(hDll != NULL) FreeLibrary(hDll); } void CallEscapeRouteAfterMofCompilation() { HMODULE hDll = NULL; ESCDOOR_AFTER_MOF_COMPILATION pfnEscRouteAfterMofCompilation; char *pszFullPath = GetFullFilename("WmiEscpe.dll"); if (!pszFullPath) return; hDll = LoadLibrary(pszFullPath); delete[] pszFullPath; if(hDll == NULL) { return; } pfnEscRouteAfterMofCompilation = (ESCDOOR_AFTER_MOF_COMPILATION)GetProcAddress((HMODULE)hDll, "EscRouteAfterMofCompilation"); if (pfnEscRouteAfterMofCompilation == NULL) { if(hDll != NULL) FreeLibrary(hDll); return; } pfnEscRouteAfterMofCompilation(); if(hDll != NULL) FreeLibrary(hDll); } bool DoMofLoad(wchar_t* pComponentName, CMultiString& mszSystemMofs) { bool bRet = true; bool bMofLoadFailure = false; CString szFailedSystemMofs; IWbemContext * pCtx = NULL; HRESULT hRes = CoCreateInstance(CLSID_WbemContext, 0, CLSCTX_INPROC_SERVER, IID_IWbemContext, (LPVOID *) &pCtx); if (FAILED(hRes)) { LogMessage(MSG_ERROR, "Unable to create CLSID_WbemContext."); return false; } OnDelete rmCtx(pCtx); _variant_t Var = true; if (FAILED(hRes = pCtx->SetValue(L"__MOFD_DO_STORE",0,&Var))) return false; IWinmgmtMofCompiler * pCompiler = NULL; SCODE sc = CoCreateInstance(CLSID_WinmgmtMofCompiler, 0, CLSCTX_INPROC_SERVER, IID_IWinmgmtMofCompiler, (LPVOID *) &pCompiler); if(SUCCEEDED(sc)) { bRet = LoadMofList(pCtx,pCompiler, mszSystemMofs, szFailedSystemMofs, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, 0); if (bRet == false) bMofLoadFailure = true; pCompiler->Release(); } else { bRet = false; } if (szFailedSystemMofs.Length()) { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "The following %S file(s) failed to load:", pComponentName); LogMessage(MSG_ERROR, szTemp); LogMessage(MSG_ERROR, szFailedSystemMofs); } else if (bMofLoadFailure) { char szTemp[MAX_MSG_TEXT_LENGTH]; StringCchPrintfA(szTemp, MAX_MSG_TEXT_LENGTH, "None of the %S files could be loaded.", pComponentName); LogMessage(MSG_ERROR, szTemp); } else if (bRet == false) { LogMessage(MSG_ERROR, "No MOFs could be loaded because the MOF Compiler failed to intialize."); } return bRet; } // this call back is needed by the wdmlib functions called by DoWDMProviderInit() void WINAPI EventCallbackRoutine(PWNODE_HEADER WnodeHeader, ULONG_PTR Context) { return; } bool DoWDMNamespaceInit() { LogMessage(MSG_INFO, "Beginning WMI(WDM) Namespace Init"); bool bRet = FALSE; IWbemLocator *pLocator = NULL; HRESULT hr = CoCreateInstance(CLSID_WbemAdministrativeLocator,NULL, CLSCTX_ALL, IID_IWbemLocator,(void**)&pLocator); if(SUCCEEDED(hr)) { BSTR tmpStr = SysAllocString(L"root\\wmi"); IWbemServices* pNamespace = NULL; hr = pLocator->ConnectServer(tmpStr, NULL, NULL, NULL, WBEM_FLAG_CONNECT_PROVIDERS, NULL, NULL, &pNamespace); if (SUCCEEDED(hr)) { CHandleMap HandleMap; CWMIBinMof Mof; if( SUCCEEDED( Mof.Initialize(&HandleMap, TRUE, WMIGUID_EXECUTE|WMIGUID_QUERY, pNamespace, pNamespace, NULL, NULL))) { Mof.ProcessListOfWMIBinaryMofsFromWMI(); } pNamespace->Release(); bRet = TRUE; } SysFreeString(tmpStr); pLocator->Release(); } if (bRet) LogMessage(MSG_INFO, "WMI(WDM) Namespace Init Completed"); else LogMessage(MSG_NTSETUPERROR, "WMI(WDM) Namespace Init Failed"); return bRet; } bool EnableESS() { CPersistentConfig cfg; bool bRet1 = (cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_ESS_NEEDS_LOADING, 1) != 0); bool bRet2 = (cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_ESS_TO_BE_INITIALIZED,1) != 0); if (bRet1 && bRet2) LogMessage(MSG_INFO, "ESS enabled"); else LogMessage(MSG_ERROR, "Failed to enable ESS"); return (bRet1 && bRet2); } #ifdef _X86_ bool RemoveOldODBC() { bool bRet = true; bool bDoUninstall = false; WCHAR strBuff[MAX_PATH + 30]; DWORD dwSize = GetWindowsDirectoryW((LPWSTR) &strBuff, MAX_PATH); if ((dwSize > 1) && (dwSize < MAX_PATH) && (strBuff[dwSize] == L'\0')) { //can be c:\ or c:\windows if (strBuff[dwSize - 1] != L'\\') { StringCchCatW(strBuff, MAX_PATH+1, L"\\system32\\wbemdr32.dll"); //we want dwSize to include the slash (may be used later)... dwSize++; } else { StringCchCatW(strBuff, MAX_PATH+1, L"system32\\wbemdr32.dll"); } DWORD dwDummy = 0; DWORD dwInfSize = GetFileVersionInfoSizeW(strBuff, &dwDummy); if (dwInfSize > 0) { BYTE *verBuff = new BYTE[dwInfSize]; if (verBuff) { if (GetFileVersionInfoW(strBuff, 0, dwInfSize, (LPVOID)verBuff)) { VS_FIXEDFILEINFO *verInfo = NULL; UINT uVerInfoSize = 0; if (VerQueryValueW((const LPVOID)verBuff, L"\\", (LPVOID *)&verInfo, &uVerInfoSize) && (uVerInfoSize == sizeof(VS_FIXEDFILEINFO))) { if (0x043D0000 > verInfo->dwFileVersionLS) //1085 = 43D { bDoUninstall = true; LogMessage(MSG_INFO, "Detected incompatible WBEM ODBC - removing"); if (!DeleteFileW(strBuff)) { if (!MoveFileExW(strBuff, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { bRet = false; LogMessage(MSG_INFO, "Failed to delete \\wbemdr32.dll"); } else { LogMessage(MSG_INFO, "Will delete \\wbemdr32.dll on next reboot"); } } } } else { GetLastError(); LogMessage(MSG_INFO, "Failed to read ODBC Driver version info from resource buffer"); bRet = false; } } else { GetLastError(); LogMessage(MSG_INFO, "Failed to get ODBC Driver version info"); bRet = false; } delete [] verBuff; verBuff = NULL; } else { bRet = false; } } else { dwDummy = GetLastError(); if ((ERROR_FILE_NOT_FOUND != dwDummy) && // for some reason, the GetFileVersionInfoW function seems to be (ERROR_RESOURCE_DATA_NOT_FOUND != dwDummy) && // returning ERROR_RESOURCE_DATA_NOT_FOUND instead of ERROR_FILE_NOT_FOUND (ERROR_SUCCESS != dwDummy)) // when the file isn't present, so check against this value as well { LogMessage(MSG_INFO, "Failed to get ODBC Driver version size info"); bRet = false; } else { //the driver isn't present clean up anything lying around LogMessage(MSG_INFO, "ODBC Driver \\wbemdr32.dll not present"); bDoUninstall = true; } } } else { bRet = false; } if (bDoUninstall) { // //delete files and registry entries //leave ini entries as they were not added by us but by ODBC Mgr // strBuff[dwSize] = L'\0'; StringCchCatW(strBuff, MAX_PATH + 30, L"system32\\wbem\\wbemdr32.chm"); if (!DeleteFileW(strBuff)) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { if (!MoveFileExW(strBuff, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { bRet = false; LogMessage(MSG_INFO, "Failed to delete \\wbem\\wbemdr32.chm"); } else { LogMessage(MSG_INFO, "Will delete \\wbem\\wbemdr32.chm on next reboot"); } } } strBuff[dwSize] = L'\0'; StringCchCatW(strBuff, MAX_PATH + 30, L"help\\wbemdr32.chm"); if (!DeleteFileW(strBuff)) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { if (!MoveFileExW(strBuff, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { bRet = false; LogMessage(MSG_INFO, "Failed to delete \\help\\wbemdr32.chm"); } else { LogMessage(MSG_INFO, "Will delete \\help\\wbemdr32.chm on next reboot"); } } } LONG lErr = RegDeleteKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ODBC\\ODBC.INI\\WBEM Source"); if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr)) { LogMessage(MSG_INFO, "Failed to delete registry key: SSoftware\\Microsoft\\ODBC\\ODBC.INI\\WBEM Source"); bRet = false; } lErr = RegDeleteKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ODBC\\ODBCINST.INI\\WBEM ODBC Driver"); if ((ERROR_SUCCESS != lErr) && (ERROR_FILE_NOT_FOUND != lErr)) { LogMessage(MSG_INFO, "Failed to delete registry key: Software\\Microsoft\\ODBC\\ODBCINST.INI\\WBEM ODBC Driver"); bRet = false; } Registry regODBC1("Software\\Microsoft\\ODBC\\ODBC.INI\\ODBC Data Sources"); if (regODBC1.GetStatus() == no_error) { if (no_error != regODBC1.DeleteEntry("WBEM Source")) { if (ERROR_FILE_NOT_FOUND != regODBC1.GetLastError()) { LogMessage(MSG_INFO, "Failed to delete registry value: Software\\Microsoft\\ODBC\\ODBC.INI\\ODBC Data Sources|WBEM Source"); bRet = false; } } } else { bRet = false; } Registry regODBC2("Software\\Microsoft\\ODBC\\ODBCINST.INI\\ODBC Drivers"); if (regODBC2.GetStatus() == no_error) { if (no_error != regODBC2.DeleteEntry("WBEM ODBC Driver")) { if (ERROR_FILE_NOT_FOUND != regODBC2.GetLastError()) { LogMessage(MSG_INFO, "Failed to delete registry value: Software\\Microsoft\\ODBC\\ODBCINST.INI\\ODBC Drivers|WBEM ODBC Driver"); bRet = false; } } } else { bRet = false; } } if (!bRet) { LogMessage(MSG_ERROR, "A failure in verifying or removing currently installed version of WBEM ODBC."); } else { LogMessage(MSG_INFO, "Successfully verified WBEM OBDC adapter (incompatible version removed if it was detected)."); } return bRet; } #endif