MSICA/MSICALib/MSITSCAOp.h

564 lines
17 KiB
C++

#ifndef __MSITSCAOP_H__
#define __MSITSCAOP_H__
#include "MSITSCA.h"
#include <atlbase.h>
#include <atlcoll.h>
#include <atlfile.h>
#include <atlstr.h>
#include <msi.h>
#include <mstask.h>
#include <windows.h>
class CMSITSCASession;
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOp
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOp
{
public:
CMSITSCAOp(int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession) = 0;
friend class CMSITSCAOpList;
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOp &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOp &op);
protected:
int m_iTicks; // Number of ticks on a progress bar required for this action execution
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpSingleStringOperation
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpSingleStringOperation : public CMSITSCAOp
{
public:
CMSITSCAOpSingleStringOperation(LPCWSTR pszValue = L"", int iTicks = 0);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSingleStringOperation &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSingleStringOperation &op);
protected:
CStringW m_sValue;
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpDoubleStringOperation
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpSrcDstStringOperation : public CMSITSCAOp
{
public:
CMSITSCAOpSrcDstStringOperation(LPCWSTR pszValue1 = L"", LPCWSTR pszValue2 = L"", int iTicks = 0);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSrcDstStringOperation &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSrcDstStringOperation &op);
protected:
CStringW m_sValue1;
CStringW m_sValue2;
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpBooleanOperation
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpBooleanOperation : public CMSITSCAOp
{
public:
CMSITSCAOpBooleanOperation(BOOL bValue = TRUE, int iTicks = 0);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpBooleanOperation &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpBooleanOperation &op);
protected:
BOOL m_bValue;
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpEnableRollback
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpEnableRollback : public CMSITSCAOpBooleanOperation
{
public:
CMSITSCAOpEnableRollback(BOOL bEnable = TRUE, int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpDeleteFile
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpDeleteFile : public CMSITSCAOpSingleStringOperation
{
public:
CMSITSCAOpDeleteFile(LPCWSTR pszFileName = L"", int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpMoveFile
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpMoveFile : public CMSITSCAOpSrcDstStringOperation
{
public:
CMSITSCAOpMoveFile(LPCWSTR pszFileSrc = L"", LPCWSTR pszFileDst = L"", int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpCreateTask
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpCreateTask : public CMSITSCAOpSingleStringOperation
{
public:
CMSITSCAOpCreateTask(LPCWSTR pszTaskName = L"", int iTicks = 0);
virtual ~CMSITSCAOpCreateTask();
virtual HRESULT Execute(CMSITSCASession *pSession);
UINT SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord);
UINT SetTriggersFromView(MSIHANDLE hView);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpCreateTask &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpCreateTask &op);
protected:
CStringW m_sApplicationName;
CStringW m_sParameters;
CStringW m_sWorkingDirectory;
CStringW m_sComment;
DWORD m_dwFlags;
DWORD m_dwPriority;
CStringW m_sAccountName;
CStringW m_sPassword;
WORD m_wIdleMinutes;
WORD m_wDeadlineMinutes;
DWORD m_dwMaxRuntimeMS;
CAtlList<TASK_TRIGGER> m_lTriggers;
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpDeleteTask
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpDeleteTask : public CMSITSCAOpSingleStringOperation
{
public:
CMSITSCAOpDeleteTask(LPCWSTR pszTaskName = L"", int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpEnableTask
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpEnableTask : public CMSITSCAOpSingleStringOperation
{
public:
CMSITSCAOpEnableTask(LPCWSTR pszTaskName = L"", BOOL bEnable = TRUE, int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpEnableTask &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpEnableTask &op);
protected:
BOOL m_bEnable;
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpCopyTask
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpCopyTask : public CMSITSCAOpSrcDstStringOperation
{
public:
CMSITSCAOpCopyTask(LPCWSTR pszTaskSrc = L"", LPCWSTR pszTaskDst = L"", int iTicks = 0);
virtual HRESULT Execute(CMSITSCASession *pSession);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCAOpList
////////////////////////////////////////////////////////////////////////////
class CMSITSCAOpList : public CMSITSCAOp, public CAtlList<CMSITSCAOp*>
{
public:
CMSITSCAOpList(int iTicks = 0);
void Free();
HRESULT LoadFromFile(LPCTSTR pszFileName);
HRESULT SaveToFile(LPCTSTR pszFileName) const;
virtual HRESULT Execute(CMSITSCASession *pSession);
friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpList &op);
friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpList &op);
protected:
enum OPERATION {
OPERATION_ENABLE_ROLLBACK = 1,
OPERATION_DELETE_FILE,
OPERATION_MOVE_FILE,
OPERATION_CREATE_TASK,
OPERATION_DELETE_TASK,
OPERATION_ENABLE_TASK,
OPERATION_COPY_TASK,
OPERATION_SUBLIST
};
protected:
template <class T, int ID> inline static HRESULT Save(CAtlFile &f, const CMSITSCAOp *p);
template <class T> inline HRESULT LoadAndAddTail(CAtlFile &f);
};
////////////////////////////////////////////////////////////////////////////
// CMSITSCASession
////////////////////////////////////////////////////////////////////////////
class CMSITSCASession
{
public:
CMSITSCASession();
MSIHANDLE m_hInstall; // Installer handle
CComPtr<ITaskScheduler> m_pTaskScheduler; // Task scheduler interface
BOOL m_bContinueOnError; // Continue execution on operation error?
BOOL m_bRollbackEnabled; // Is rollback enabled?
CMSITSCAOpList m_olRollback; // Rollback operation list
CMSITSCAOpList m_olCommit; // Commit operation list
};
////////////////////////////////////////////////////////////////////////////
// Inline operators
////////////////////////////////////////////////////////////////////////////
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOp &op)
{
return f << op.m_iTicks;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOp &op)
{
return f >> op.m_iTicks;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSingleStringOperation &op)
{
HRESULT hr;
hr = f << (const CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
return f << op.m_sValue;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSingleStringOperation &op)
{
HRESULT hr;
hr = f >> (CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
return f >> op.m_sValue;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSrcDstStringOperation &op)
{
HRESULT hr;
hr = f << (const CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
hr = f << op.m_sValue1;
if (FAILED(hr)) return hr;
return f << op.m_sValue2;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSrcDstStringOperation &op)
{
HRESULT hr;
hr = f >> (CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
hr = f >> op.m_sValue1;
if (FAILED(hr)) return hr;
return f >> op.m_sValue2;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpBooleanOperation &op)
{
HRESULT hr;
hr = f << (const CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
return f << (int)op.m_bValue;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpBooleanOperation &op)
{
int iValue;
HRESULT hr;
hr = f >> (CMSITSCAOp &)op;
if (FAILED(hr)) return hr;
hr = f >> iValue;
if (FAILED(hr)) return hr;
op.m_bValue = iValue ? TRUE : FALSE;
return S_OK;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpCreateTask &op)
{
HRESULT hr;
POSITION pos;
hr = f << (const CMSITSCAOpSingleStringOperation&)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;
hr = f << op.m_sComment; if (FAILED(hr)) return hr;
hr = f << (int)op.m_dwFlags; if (FAILED(hr)) return hr;
hr = f << (int)op.m_dwPriority; if (FAILED(hr)) return hr;
hr = f << op.m_sAccountName; if (FAILED(hr)) return hr;
hr = f << op.m_sPassword; if (FAILED(hr)) return hr;
hr = f << (int)MAKELONG(op.m_wDeadlineMinutes, op.m_wIdleMinutes); if (FAILED(hr)) return hr;
hr = f << (int)op.m_dwMaxRuntimeMS; if (FAILED(hr)) return hr;
hr = f << (int)op.m_lTriggers.GetCount(); if (FAILED(hr)) return hr;
for (pos = op.m_lTriggers.GetHeadPosition(); pos;) {
hr = f << op.m_lTriggers.GetNext(pos);
if (FAILED(hr)) return hr;
}
return S_OK;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpCreateTask &op)
{
HRESULT hr;
DWORD dwValue;
hr = f >> (CMSITSCAOpSingleStringOperation&)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;
hr = f >> op.m_sComment; if (FAILED(hr)) return hr;
hr = f >> (int&)op.m_dwFlags; if (FAILED(hr)) return hr;
hr = f >> (int&)op.m_dwPriority; if (FAILED(hr)) return hr;
hr = f >> op.m_sAccountName; if (FAILED(hr)) return hr;
hr = f >> op.m_sPassword; if (FAILED(hr)) return hr;
hr = f >> (int&)dwValue; if (FAILED(hr)) return hr; op.m_wIdleMinutes = HIWORD(dwValue); op.m_wDeadlineMinutes = LOWORD(dwValue);
hr = f >> (int&)op.m_dwMaxRuntimeMS; if (FAILED(hr)) return hr;
hr = f >> (int&)dwValue; if (FAILED(hr)) return hr;
while (dwValue--) {
TASK_TRIGGER ttData;
hr = f >> ttData;
if (FAILED(hr)) return hr;
op.m_lTriggers.AddTail(ttData);
}
return S_OK;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpEnableTask &op)
{
HRESULT hr;
hr = f << (const CMSITSCAOpSingleStringOperation&)op;
if (FAILED(hr)) return hr;
return f << (int)op.m_bEnable;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpEnableTask &op)
{
HRESULT hr;
int iTemp;
hr = f >> (CMSITSCAOpSingleStringOperation&)op;
if (FAILED(hr)) return hr;
hr = f >> iTemp;
if (FAILED(hr)) return hr;
op.m_bEnable = iTemp ? TRUE : FALSE;
return S_OK;
}
inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpList &list)
{
POSITION pos;
HRESULT hr;
hr = f << (const CMSITSCAOp &)list;
if (FAILED(hr)) return hr;
hr = f << (int)list.GetCount();
if (FAILED(hr)) return hr;
for (pos = list.GetHeadPosition(); pos;) {
const CMSITSCAOp *pOp = list.GetNext(pos);
if (dynamic_cast<const CMSITSCAOpEnableRollback*>(pOp))
hr = list.Save<CMSITSCAOpEnableRollback, CMSITSCAOpList::OPERATION_ENABLE_ROLLBACK>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpDeleteFile*>(pOp))
hr = list.Save<CMSITSCAOpDeleteFile, CMSITSCAOpList::OPERATION_DELETE_FILE>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpMoveFile*>(pOp))
hr = list.Save<CMSITSCAOpMoveFile, CMSITSCAOpList::OPERATION_MOVE_FILE>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpCreateTask*>(pOp))
hr = list.Save<CMSITSCAOpCreateTask, CMSITSCAOpList::OPERATION_CREATE_TASK>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpDeleteTask*>(pOp))
hr = list.Save<CMSITSCAOpDeleteTask, CMSITSCAOpList::OPERATION_DELETE_TASK>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpEnableTask*>(pOp))
hr = list.Save<CMSITSCAOpEnableTask, CMSITSCAOpList::OPERATION_ENABLE_TASK>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpCopyTask*>(pOp))
hr = list.Save<CMSITSCAOpCopyTask, CMSITSCAOpList::OPERATION_COPY_TASK>(f, pOp);
else if (dynamic_cast<const CMSITSCAOpList*>(pOp))
hr = list.Save<CMSITSCAOpList, CMSITSCAOpList::OPERATION_SUBLIST>(f, pOp);
else {
// Unsupported type of operation.
assert(0);
hr = E_UNEXPECTED;
}
if (FAILED(hr)) return hr;
}
return S_OK;
}
inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpList &list)
{
HRESULT hr;
DWORD dwCount;
hr = f >> (CMSITSCAOp &)list;
if (FAILED(hr)) return hr;
hr = f >> (int&)dwCount;
if (FAILED(hr)) return hr;
while (dwCount--) {
int iTemp;
hr = f >> iTemp;
if (FAILED(hr)) return hr;
switch ((CMSITSCAOpList::OPERATION)iTemp) {
case CMSITSCAOpList::OPERATION_ENABLE_ROLLBACK:
hr = list.LoadAndAddTail<CMSITSCAOpEnableRollback>(f);
break;
case CMSITSCAOpList::OPERATION_DELETE_FILE:
hr = list.LoadAndAddTail<CMSITSCAOpDeleteFile>(f);
break;
case CMSITSCAOpList::OPERATION_MOVE_FILE:
hr = list.LoadAndAddTail<CMSITSCAOpMoveFile>(f);
break;
case CMSITSCAOpList::OPERATION_CREATE_TASK:
hr = list.LoadAndAddTail<CMSITSCAOpCreateTask>(f);
break;
case CMSITSCAOpList::OPERATION_DELETE_TASK:
hr = list.LoadAndAddTail<CMSITSCAOpDeleteTask>(f);
break;
case CMSITSCAOpList::OPERATION_ENABLE_TASK:
hr = list.LoadAndAddTail<CMSITSCAOpEnableTask>(f);
break;
case CMSITSCAOpList::OPERATION_COPY_TASK:
hr = list.LoadAndAddTail<CMSITSCAOpCopyTask>(f);
break;
case CMSITSCAOpList::OPERATION_SUBLIST:
hr = list.LoadAndAddTail<CMSITSCAOpList>(f);
break;
default:
// Unsupported type of operation.
assert(0);
hr = E_UNEXPECTED;
}
if (FAILED(hr)) return hr;
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// Inline methods
////////////////////////////////////////////////////////////////////////////
template <class T, int ID> inline static HRESULT CMSITSCAOpList::Save(CAtlFile &f, const CMSITSCAOp *p)
{
assert(p);
HRESULT hr;
const T *pp = dynamic_cast<const T*>(p);
assert(pp);
hr = f << (int)ID;
if (FAILED(hr)) return hr;
return f << *pp;
}
template <class T> inline HRESULT CMSITSCAOpList::LoadAndAddTail(CAtlFile &f)
{
HRESULT hr;
// Create element.
T *p = new T();
if (!p) return E_OUTOFMEMORY;
// Load element from file.
hr = f >> *p;
if (FAILED(hr)) {
delete p;
return hr;
}
// Add element.
AddTail(p);
return S_OK;
}
#endif // __MSITSCAOP_H__