#ifndef __MSITSCAOP_H__ #define __MSITSCAOP_H__ #include "MSITSCA.h" #include #include #include #include #include #include #include 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 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 { 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 inline static HRESULT Save(CAtlFile &f, const CMSITSCAOp *p); template inline HRESULT LoadAndAddTail(CAtlFile &f); }; //////////////////////////////////////////////////////////////////////////// // CMSITSCASession //////////////////////////////////////////////////////////////////////////// class CMSITSCASession { public: CMSITSCASession(); MSIHANDLE m_hInstall; // Installer handle CComPtr 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(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(f, pOp); else if (dynamic_cast(pOp)) hr = list.Save(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(f); break; case CMSITSCAOpList::OPERATION_DELETE_FILE: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_MOVE_FILE: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_CREATE_TASK: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_DELETE_TASK: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_ENABLE_TASK: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_COPY_TASK: hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_SUBLIST: hr = list.LoadAndAddTail(f); break; default: // Unsupported type of operation. assert(0); hr = E_UNEXPECTED; } if (FAILED(hr)) return hr; } return S_OK; } //////////////////////////////////////////////////////////////////////////// // Inline methods //////////////////////////////////////////////////////////////////////////// template inline static HRESULT CMSITSCAOpList::Save(CAtlFile &f, const CMSITSCAOp *p) { assert(p); HRESULT hr; const T *pp = dynamic_cast(p); assert(pp); hr = f << (int)ID; if (FAILED(hr)) return hr; return f << *pp; } template 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__