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:
parent
b68530c0a2
commit
12a8cbd84e
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
279
AMSICA/src/MSICARegOp.cpp
Normal 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
|
Loading…
x
Reference in New Issue
Block a user