MSICA/MSICALib/MSICALib.cpp
2014-03-12 13:00:59 +00:00

185 lines
4.8 KiB
C++

#include "stdafx.h"
#pragma comment(lib, "msi.lib")
namespace MSICA {
////////////////////////////////////////////////////////////////////////////
// COperation
////////////////////////////////////////////////////////////////////////////
COperation::COperation(int iTicks) :
m_iTicks(iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpTypeSingleString
////////////////////////////////////////////////////////////////////////////
COpTypeSingleString::COpTypeSingleString(LPCWSTR pszValue, int iTicks) :
m_sValue(pszValue),
COperation(iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpTypeSrcDstString
////////////////////////////////////////////////////////////////////////////
COpTypeSrcDstString::COpTypeSrcDstString(LPCWSTR pszValue1, LPCWSTR pszValue2, int iTicks) :
m_sValue1(pszValue1),
m_sValue2(pszValue2),
COperation(iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpTypeBoolean
////////////////////////////////////////////////////////////////////////////
COpTypeBoolean::COpTypeBoolean(BOOL bValue, int iTicks) :
m_bValue(bValue),
COperation(iTicks)
{
}
////////////////////////////////////////////////////////////////////////////
// COpRollbackEnable
////////////////////////////////////////////////////////////////////////////
COpRollbackEnable::COpRollbackEnable(BOOL bEnable, int iTicks) :
COpTypeBoolean(bEnable, iTicks)
{
}
HRESULT COpRollbackEnable::Execute(CSession *pSession)
{
pSession->m_bRollbackEnabled = m_bValue;
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// COpList
////////////////////////////////////////////////////////////////////////////
COpList::COpList(int iTicks) :
COperation(iTicks),
ATL::CAtlList<COperation*>(sizeof(COperation*))
{
}
void COpList::Free()
{
POSITION pos;
for (pos = GetHeadPosition(); pos;) {
COperation *pOp = GetNext(pos);
COpList *pOpList = dynamic_cast<COpList*>(pOp);
if (pOpList) {
// Recursivelly free sublists.
pOpList->Free();
}
delete pOp;
}
RemoveAll();
}
HRESULT COpList::LoadFromFile(LPCTSTR pszFileName)
{
HRESULT hr;
ATL::CAtlFile fSequence;
hr = fSequence.Create(pszFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN);
if (FAILED(hr)) return hr;
// Load operation sequence.
return fSequence >> *this;
}
HRESULT COpList::SaveToFile(LPCTSTR pszFileName) const
{
HRESULT hr;
ATL::CAtlFile fSequence;
hr = fSequence.Create(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN);
if (FAILED(hr)) return hr;
// Save execute sequence to file.
hr = fSequence << *this;
fSequence.Close();
if (FAILED(hr)) ::DeleteFile(pszFileName);
return hr;
}
HRESULT COpList::Execute(CSession *pSession)
{
POSITION pos;
HRESULT hr;
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
// Tell the installer to use explicit progress messages.
::MsiRecordSetInteger(hRecordProg, 1, 1);
::MsiRecordSetInteger(hRecordProg, 2, 1);
::MsiRecordSetInteger(hRecordProg, 3, 0);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg);
// Prepare hRecordProg for progress messages.
::MsiRecordSetInteger(hRecordProg, 1, 2);
::MsiRecordSetInteger(hRecordProg, 3, 0);
for (pos = GetHeadPosition(); pos;) {
COperation *pOp = GetNext(pos);
hr = pOp->Execute(pSession);
if (!pSession->m_bContinueOnError && FAILED(hr)) {
// Operation failed. Its Execute() method should have sent error message to Installer.
// Therefore, just quit here.
return hr;
}
::MsiRecordSetInteger(hRecordProg, 2, pOp->m_iTicks);
if (::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL)
return AtlHresultFromWin32(ERROR_INSTALL_USEREXIT);
}
::MsiRecordSetInteger(hRecordProg, 2, m_iTicks);
::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// CSession
////////////////////////////////////////////////////////////////////////////
CSession::CSession() :
m_bContinueOnError(FALSE),
m_bRollbackEnabled(FALSE)
{
}
CSession::~CSession()
{
m_olRollback.Free();
m_olCommit.Free();
}
} // namespace MSICA