Dodal sem podporo za delo s ključi v registru. Ni še dokončna. Vseeno uveljavljam, da bo na varnem.

This commit is contained in:
Simon Rozman 2013-04-26 15:30:05 +00:00
parent b68530c0a2
commit 12a8cbd84e
7 changed files with 473 additions and 24 deletions

1
.gitattributes vendored
View File

@ -9,6 +9,7 @@ AMSICA/res/en_GB.po -text
AMSICA/src/AMSICA.cpp -text
AMSICA/src/AMSICAFileOp.cpp -text
AMSICA/src/AMSICATSOp.cpp -text
AMSICA/src/MSICARegOp.cpp -text
AMSICA/src/StdAfx.cpp -text
MSITSCA/L10N/sl_SI.po -text
MSITSCA/MSITSCA.cpp -text

View File

@ -38,6 +38,7 @@
<ClCompile Include="..\src\AMSICA.cpp" />
<ClCompile Include="..\src\AMSICAFileOp.cpp" />
<ClCompile Include="..\src\AMSICATSOp.cpp" />
<ClCompile Include="..\src\MSICARegOp.cpp" />
<ClCompile Include="..\src\StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>

View File

@ -27,6 +27,9 @@
<ClCompile Include="..\src\StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\MSICARegOp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\AMSICA.h">

View File

@ -26,11 +26,15 @@
////////////////////////////////////////////////////////////////////
// Error codes (last unused 2561L)
// Error codes (next unused 2565L)
////////////////////////////////////////////////////////////////////
#define ERROR_INSTALL_DELETE_FAILED 2554L
#define ERROR_INSTALL_MOVE_FAILED 2555L
#define ERROR_INSTALL_FILE_DELETE_FAILED 2554L
#define ERROR_INSTALL_FILE_MOVE_FAILED 2555L
#define ERROR_INSTALL_REGKEY_CREATE_FAILED 2561L
#define ERROR_INSTALL_REGKEY_COPY_FAILED 2562L
#define ERROR_INSTALL_REGKEY_PROBING_FAILED 2563L
#define ERROR_INSTALL_REGKEY_DELETE_FAILED 2564L
#define ERROR_INSTALL_TASK_CREATE_FAILED 2556L
#define ERROR_INSTALL_TASK_DELETE_FAILED 2557L
#define ERROR_INSTALL_TASK_ENABLE_FAILED 2558L
@ -83,8 +87,8 @@ class COpTypeSingleString : public COperation
public:
COpTypeSingleString(LPCWSTR pszValue = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const AMSICA::COpTypeSingleString &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, AMSICA::COpTypeSingleString &op);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSingleString &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op);
protected:
ATL::CAtlStringW m_sValue;
@ -100,8 +104,8 @@ class COpTypeSrcDstString : public COperation
public:
COpTypeSrcDstString(LPCWSTR pszValue1 = L"", LPCWSTR pszValue2 = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const AMSICA::COpTypeSrcDstString &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, AMSICA::COpTypeSrcDstString &op);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSrcDstString &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op);
protected:
ATL::CAtlStringW m_sValue1;
@ -118,8 +122,8 @@ class COpTypeBoolean : public COperation
public:
COpTypeBoolean(BOOL bValue = TRUE, int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const AMSICA::COpTypeBoolean &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, AMSICA::COpTypeBoolean &op);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeBoolean &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op);
protected:
BOOL m_bValue;
@ -162,6 +166,82 @@ public:
};
////////////////////////////////////////////////////////////////////////////
// COpRegKeySingle
////////////////////////////////////////////////////////////////////////////
class COpRegKeySingle : public COpTypeSingleString
{
public:
COpRegKeySingle(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySingle &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegKeySingle &op);
protected:
HKEY m_hKeyRoot;
};
////////////////////////////////////////////////////////////////////////////
// COpRegKeySrcDst
////////////////////////////////////////////////////////////////////////////
class COpRegKeySrcDst : public COpTypeSrcDstString
{
public:
COpRegKeySrcDst(HKEY hKeyRoot = NULL, LPCWSTR pszKeyNameSrc = L"", LPCWSTR pszKeyNameDst = L"", int iTicks = 0);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySrcDst &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegKeySrcDst &op);
protected:
HKEY m_hKeyRoot;
};
////////////////////////////////////////////////////////////////////////////
// COpRegKeyCreate
////////////////////////////////////////////////////////////////////////////
class COpRegKeyCreate : public COpRegKeySingle
{
public:
COpRegKeyCreate(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// COpRegKeyCopy
////////////////////////////////////////////////////////////////////////////
class COpRegKeyCopy : public COpRegKeySrcDst
{
public:
COpRegKeyCopy(HKEY hKey = NULL, LPCWSTR pszKeyNameSrc = L"", LPCWSTR pszKeyNameDst = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
private:
static LONG CopyKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, REGSAM samAdditional);
};
////////////////////////////////////////////////////////////////////////////
// COpRegKeyDelete
////////////////////////////////////////////////////////////////////////////
class COpRegKeyDelete : public COpRegKeySingle
{
public:
COpRegKeyDelete(HKEY hKey = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0);
virtual HRESULT Execute(CSession *pSession);
private:
static LONG DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM sam);
};
////////////////////////////////////////////////////////////////////////////
// COpTaskCreate
////////////////////////////////////////////////////////////////////////////
@ -176,8 +256,8 @@ public:
UINT SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord);
UINT SetTriggersFromView(MSIHANDLE hView);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const AMSICA::COpTaskCreate &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, AMSICA::COpTaskCreate &op);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op);
protected:
ATL::CAtlStringW m_sApplicationName;
@ -665,7 +745,7 @@ inline HRESULT operator >>(ATL::CAtlFile &f, TASK_TRIGGER &ttData)
}
inline HRESULT operator <<(ATL::CAtlFile &f, const AMSICA::COperation &op)
inline HRESULT operator <<(ATL::CAtlFile &f, const COperation &op)
{
return f << op.m_iTicks;
}
@ -740,8 +820,8 @@ inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeBoolean &op)
inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op)
{
int iValue;
HRESULT hr;
int iValue;
hr = f >> (COperation &)op;
if (FAILED(hr)) return hr;
@ -754,12 +834,59 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op)
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySingle &op)
{
HRESULT hr;
hr = f << (const COpTypeSingleString &)op; if (FAILED(hr)) return hr;
hr = f << (int)(op.m_hKeyRoot); if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpRegKeySingle &op)
{
HRESULT hr;
int iValue;
hr = f >> (COpTypeSingleString &)op; if (FAILED(hr)) return hr;
hr = f >> iValue; if (FAILED(hr)) return hr; op.m_hKeyRoot = (HKEY)iValue;
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegKeySrcDst &op)
{
HRESULT hr;
hr = f << (const COpTypeSrcDstString &)op; if (FAILED(hr)) return hr;
hr = f << (int)(op.m_hKeyRoot); if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpRegKeySrcDst &op)
{
HRESULT hr;
int iValue;
hr = f >> (COpTypeSrcDstString &)op; if (FAILED(hr)) return hr;
hr = f >> iValue; if (FAILED(hr)) return hr; op.m_hKeyRoot = (HKEY)iValue;
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op)
{
HRESULT hr;
POSITION pos;
hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f << op.m_sApplicationName; if (FAILED(hr)) return hr;
hr = f << op.m_sParameters; if (FAILED(hr)) return hr;
hr = f << op.m_sWorkingDirectory; if (FAILED(hr)) return hr;
@ -786,7 +913,7 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op)
HRESULT hr;
DWORD dwValue;
hr = f >> (COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f >> (COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f >> op.m_sApplicationName; if (FAILED(hr)) return hr;
hr = f >> op.m_sParameters; if (FAILED(hr)) return hr;
hr = f >> op.m_sWorkingDirectory; if (FAILED(hr)) return hr;
@ -934,6 +1061,44 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpList &list)
}
////////////////////////////////////////////////////////////////////
// Inline Functions
////////////////////////////////////////////////////////////////////
inline BOOL IsWow64Process()
{
#ifndef _WIN64
// Find IsWow64Process() address in KERNEL32.DLL.
BOOL (WINAPI *_IsWow64Process)(__in HANDLE hProcess, __out PBOOL Wow64Process) = (BOOL(WINAPI*)(__in HANDLE, __out PBOOL))::GetProcAddress(::GetModuleHandle(_T("KERNEL32.DLL")), "IsWow64Process");
// See if our 32-bit process is running in 64-bit environment.
if (_IsWow64Process) {
BOOL bResult;
// See, what IsWow64Process() says about current process.
if (_IsWow64Process(::GetCurrentProcess(), &bResult)) {
// Return result.
return bResult;
} else {
// IsWow64Process() returned an error. Assume, the process is not WOW64.
return FALSE;
}
} else {
// This KERNEL32.DLL doesn't know IsWow64Process().Definitely not a WOW64 process.
return FALSE;
}
#else
// 64-bit processes are never run as WOW64.
return FALSE;
#endif
}
#ifndef _WIN64
#endif
////////////////////////////////////////////////////////////////////////////
// Inline methods
////////////////////////////////////////////////////////////////////////////

View File

@ -43,9 +43,9 @@ HRESULT COpFileDelete::Execute(CSession *pSession)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_DELETE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 3, dwError ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_DELETE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 3, dwError ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError);
}
@ -78,10 +78,10 @@ HRESULT COpFileMove::Execute(CSession *pSession)
return S_OK;
} else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_MOVE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue1 ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue2 ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, dwError ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_FILE_MOVE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue1 ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue2 ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, dwError ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(dwError);
}

View File

@ -45,8 +45,8 @@ HRESULT COpTaskCreate::Execute(CSession *pSession)
// Delete existing task first.
// Since task deleting is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpTaskDelete::Execute() returns S_OK if task doesn't exist.
COpTaskDelete opDeleteTask(m_sValue);
hr = opDeleteTask.Execute(pSession);
COpTaskDelete opDelete(m_sValue);
hr = opDelete.Execute(pSession);
if (FAILED(hr)) goto finish;
}

279
AMSICA/src/MSICARegOp.cpp Normal file
View File

@ -0,0 +1,279 @@
#include "StdAfx.h"
namespace AMSICA {
////////////////////////////////////////////////////////////////////////////
// COpRegKeySingle
////////////////////////////////////////////////////////////////////////////
COpRegKeySingle::COpRegKeySingle(HKEY hKeyRoot, LPCWSTR pszKeyName, int iTicks) :
m_hKeyRoot(hKeyRoot),
COpTypeSingleString(pszKeyName, iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpRegKeySrcDst
////////////////////////////////////////////////////////////////////////////
COpRegKeySrcDst::COpRegKeySrcDst(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, int iTicks) :
m_hKeyRoot(hKeyRoot),
COpTypeSrcDstString(pszKeyNameSrc, pszKeyNameDst, iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpRegKeyCreate
////////////////////////////////////////////////////////////////////////////
COpRegKeyCreate::COpRegKeyCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, int iTicks) : COpRegKeySingle(hKeyRoot, pszKeyName, iTicks)
{
}
HRESULT COpRegKeyCreate::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM samAdditional = 0;
ATL::CAtlStringW sPartialName;
int iStart = 0;
assert(0); // TODO: Preizkusi ta del kode.
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
samAdditional |= KEY_WOW64_64KEY;
}
#endif
for (;;) {
HKEY hKey;
int iStartNext = m_sValue.Find(L'\\', iStart);
if (iStartNext >= 0)
sPartialName.SetString(m_sValue, iStartNext);
else
sPartialName = m_sValue;
// Try to open the key, to see if it exists.
lResult = ::RegOpenKeyExW(m_hKeyRoot, sPartialName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey);
if (lResult == ERROR_FILE_NOT_FOUND) {
// The key doesn't exist yet. Create it.
if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the key. ::RegCreateEx() might create a key but return failure.
pSession->m_olRollback.AddHead(new COpRegKeyDelete(m_hKeyRoot, sPartialName));
}
// Create the key.
lResult = ::RegCreateKeyExW(m_hKeyRoot, sPartialName, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ENUMERATE_SUB_KEYS | samAdditional, NULL, &hKey, NULL);
if (lResult != ERROR_SUCCESS) break;
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
} else if (lResult == ERROR_SUCCESS) {
// This key already exists. Release its handle and continue.
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
} else
break;
if (iStartNext < 0) break;
iStart = iStartNext + 1;
}
if (lResult == ERROR_SUCCESS)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_CREATE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
////////////////////////////////////////////////////////////////////////////
// COpRegKeyCopy
////////////////////////////////////////////////////////////////////////////
COpRegKeyCopy::COpRegKeyCopy(HKEY hKeyRoot, LPCWSTR pszKeyNameSrc, LPCWSTR pszKeyNameDst, int iTicks) : COpRegKeySrcDst(hKeyRoot, pszKeyNameSrc, pszKeyNameDst, iTicks)
{
}
HRESULT COpRegKeyCopy::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM samAdditional = 0;
assert(0); // TODO: Preizkusi ta del kode.
{
// Delete existing destination key first.
// Since deleting registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
// Don't worry, COpRegKeyDelete::Execute() returns S_OK if key doesn't exist.
COpRegKeyDelete opDelete(m_hKeyRoot, m_sValue2);
HRESULT hr = opDelete.Execute(pSession);
if (FAILED(hr)) return hr;
}
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
samAdditional |= KEY_WOW64_64KEY;
}
#endif
if (pSession->m_bRollbackEnabled) {
// Order rollback action to delete the destination key.
pSession->m_olRollback.AddHead(new COpRegKeyDelete(m_hKeyRoot, m_sValue2));
}
// Copy the registry key.
lResult = CopyKeyRecursively(m_hKeyRoot, m_sValue1, m_sValue2, samAdditional);
if (lResult == ERROR_SUCCESS)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(5);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_COPY_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue1 ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 4, m_sValue2 ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 5, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
////////////////////////////////////////////////////////////////////////////
// COpRegKeyDelete
////////////////////////////////////////////////////////////////////////////
COpRegKeyDelete::COpRegKeyDelete(HKEY hKeyRoot, LPCWSTR m_hKeyRoot, int iTicks) : COpRegKeySingle(hKeyRoot, m_hKeyRoot, iTicks)
{
}
HRESULT COpRegKeyDelete::Execute(CSession *pSession)
{
assert(pSession);
LONG lResult;
REGSAM samAdditional = 0;
assert(0); // TODO: Preizkusi ta del kode.
#ifndef _WIN64
if (IsWow64Process()) {
// 32-bit processes run as WOW64 should use 64-bit registry too.
samAdditional |= KEY_WOW64_64KEY;
}
#endif
if (pSession->m_bRollbackEnabled) {
// Make a backup of the key first.
ATL::CAtlStringW sBackupName;
UINT uiCount = 0;
for (;;) {
HKEY hKey;
sBackupName.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount);
lResult = ::RegOpenKeyExW(m_hKeyRoot, sBackupName, 0, KEY_ENUMERATE_SUB_KEYS | samAdditional, &hKey);
if (lResult != ERROR_SUCCESS) break;
verify(::RegCloseKey(hKey));
}
if (lResult == ERROR_FILE_NOT_FOUND) {
// Since copying registry key is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it.
COpRegKeyCopy opCopy(m_hKeyRoot, m_sValue, sBackupName);
HRESULT hr = opCopy.Execute(pSession);
if (FAILED(hr)) return hr;
// Order rollback action to restore the key from backup copy.
pSession->m_olRollback.AddHead(new COpRegKeyCopy(m_hKeyRoot, sBackupName, m_sValue));
// Order commit action to delete backup copy.
pSession->m_olCommit.AddTail(new COpRegKeyDelete(m_hKeyRoot, sBackupName, TRUE));
} else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_PROBING_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, sBackupName ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
// Delete the registry key.
lResult = DeleteKeyRecursively(m_hKeyRoot, m_sValue, KEY_ENUMERATE_SUB_KEYS | samAdditional);
if (lResult == ERROR_SUCCESS)
return S_OK;
else {
PMSIHANDLE hRecordProg = ::MsiCreateRecord(4);
verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_REGKEY_DELETE_FAILED) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 2, (UINT)m_hKeyRoot & 0x7fffffff ) == ERROR_SUCCESS);
verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue ) == ERROR_SUCCESS);
verify(::MsiRecordSetInteger(hRecordProg, 4, lResult ) == ERROR_SUCCESS);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg);
return AtlHresultFromWin32(lResult);
}
}
LONG COpRegKeyDelete::DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM sam)
{
HKEY hKey;
LONG lResult;
// Open the key.
lResult = ::RegOpenKeyEx(hKeyRoot, pszKeyName, 0, sam, &hKey);
if (lResult == ERROR_SUCCESS) {
DWORD dwMaxSubKeyLen;
// Determine the largest subkey name.
lResult = ::RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (lResult == ERROR_SUCCESS) {
LPWSTR pszSubKeyName;
// Prepare buffer to hold the subkey names (including zero terminator).
dwMaxSubKeyLen++;
pszSubKeyName = new TCHAR[dwMaxSubKeyLen];
if (pszSubKeyName) {
DWORD dwIndex;
// Iterate over all subkeys and delete them. Skip failed.
for (dwIndex = 0; lResult != ERROR_NO_MORE_ITEMS ;) {
lResult = ::RegEnumKeyEx(hKey, dwIndex, pszSubKeyName, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL);
if (lResult == ERROR_SUCCESS)
lResult = DeleteKeyRecursively(hKey, pszSubKeyName, sam);
else
dwIndex++;
}
delete [] pszSubKeyName;
} else
lResult = ERROR_OUTOFMEMORY;
}
verify(::RegCloseKey(hKey) == ERROR_SUCCESS);
// Finally try to delete the key.
lResult = ::RegDeleteKeyW(hKeyRoot, pszKeyName);
} else if (lResult == ERROR_FILE_NOT_FOUND) {
// The key doesn't exist. Not really an error in this case.
lResult = ERROR_SUCCESS;
}
return lResult;
}
} // namespace AMSICA