Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1765 lines
47 KiB

// Copyright (c) 2000 Microsoft Corporation, All Rights Reserved
#include "precomp.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <wbemint.h>
#include "upgrade.h"
#include "wbemutil.h"
#include "reg.h"
#include "export.h"
#include "import.h"
#include <WDMSHELL.h>
#include <wmimof.h>
#include <wmicom.h>
#include <setupapi.h>
#include <persistcfg.h>
#include <str.h>
#include <helper.h>
//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<IUnknown *,void(*)(IUnknown *),RM> 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<CMMFArena2> 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<TCHAR> 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<CRepExporter> 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:
* <none>
*
* 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"<systemroot>\\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<IUnknown *,void(*)(IUnknown *),RM> 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 <system32>\\wbemdr32.dll");
}
else
{
LogMessage(MSG_INFO, "Will delete <system32>\\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 <system32>\\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 <system32>\\wbem\\wbemdr32.chm");
}
else
{
LogMessage(MSG_INFO, "Will delete <system32>\\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 <windir>\\help\\wbemdr32.chm");
}
else
{
LogMessage(MSG_INFO, "Will delete <windir>\\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