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
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
|