#ifndef __MSICALib_H__ #define __MSICALib_H__ //////////////////////////////////////////////////////////////////////////// // Version //////////////////////////////////////////////////////////////////////////// #define MSICALib_VERSION 0x02000000 #define MSICALib_VERSION_MAJ 2 #define MSICALib_VERSION_MIN 0 #define MSICALib_VERSION_REV 0 #define MSICALib_VERSION_STR "2.0" #if !defined(RC_INVOKED) && !defined(MIDL_PASS) #include #include #include #include #include #include #include //////////////////////////////////////////////////////////////////// // Error codes (next unused 2569L) //////////////////////////////////////////////////////////////////// #define ERROR_INSTALL_DATABASE_OPEN 2550L #define ERROR_INSTALL_PROPERTY_SET 2553L #define ERROR_INSTALL_SCRIPT_WRITE 2552L #define ERROR_INSTALL_SCRIPT_READ 2560L #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_REGKEY_SETVALUE_FAILED 2565L #define ERROR_INSTALL_REGKEY_DELETEVALUE_FAILED 2567L #define ERROR_INSTALL_REGKEY_COPYVALUE_FAILED 2568L #define ERROR_INSTALL_REGKEY_PROBINGVAL_FAILED 2566L #define ERROR_INSTALL_TASK_CREATE_FAILED 2556L #define ERROR_INSTALL_TASK_DELETE_FAILED 2557L #define ERROR_INSTALL_TASK_ENABLE_FAILED 2558L #define ERROR_INSTALL_TASK_COPY_FAILED 2559L // Errors reported by MSITSCA #define ERROR_INSTALL_SCHEDULED_TASKS_OPLIST_CREATE 2551L namespace MSICA { //////////////////////////////////////////////////////////////////////////// // Forward declarations //////////////////////////////////////////////////////////////////////////// class CSession; //////////////////////////////////////////////////////////////////////////// // COperation //////////////////////////////////////////////////////////////////////////// class COperation { public: COperation(int iTicks = 0); virtual HRESULT Execute(CSession *pSession) = 0; friend class COpList; friend inline HRESULT operator <<(ATL::CAtlFile &f, const COperation &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COperation &op); protected: int m_iTicks; // Number of ticks on a progress bar required for this action execution }; //////////////////////////////////////////////////////////////////////////// // COpTypeSingleString //////////////////////////////////////////////////////////////////////////// class COpTypeSingleString : public COperation { public: COpTypeSingleString(LPCWSTR pszValue = L"", int iTicks = 0); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSingleString &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op); protected: ATL::CAtlStringW m_sValue; }; //////////////////////////////////////////////////////////////////////////// // COpTypeSrcDstString //////////////////////////////////////////////////////////////////////////// class COpTypeSrcDstString : public COperation { public: COpTypeSrcDstString(LPCWSTR pszValue1 = L"", LPCWSTR pszValue2 = L"", int iTicks = 0); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSrcDstString &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op); protected: ATL::CAtlStringW m_sValue1; ATL::CAtlStringW m_sValue2; }; //////////////////////////////////////////////////////////////////////////// // COpTypeBoolean //////////////////////////////////////////////////////////////////////////// class COpTypeBoolean : public COperation { public: COpTypeBoolean(BOOL bValue = TRUE, int iTicks = 0); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeBoolean &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op); protected: BOOL m_bValue; }; //////////////////////////////////////////////////////////////////////////// // COpRollbackEnable //////////////////////////////////////////////////////////////////////////// class COpRollbackEnable : public COpTypeBoolean { public: COpRollbackEnable(BOOL bEnable = TRUE, int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpFileDelete //////////////////////////////////////////////////////////////////////////// class COpFileDelete : public COpTypeSingleString { public: COpFileDelete(LPCWSTR pszFileName = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpFileMove //////////////////////////////////////////////////////////////////////////// class COpFileMove : public COpTypeSrcDstString { public: COpFileMove(LPCWSTR pszFileSrc = L"", LPCWSTR pszFileDst = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // 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 hKeyRoot = 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); static LONG CopyKeyRecursively(HKEY hKeySrc, HKEY hKeyDst, REGSAM samAdditional); }; //////////////////////////////////////////////////////////////////////////// // COpRegKeyDelete //////////////////////////////////////////////////////////////////////////// class COpRegKeyDelete : public COpRegKeySingle { public: COpRegKeyDelete(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); private: static LONG DeleteKeyRecursively(HKEY hKeyRoot, LPCWSTR pszKeyName, REGSAM samAdditional); }; //////////////////////////////////////////////////////////////////////////// // COpRegValueSingle //////////////////////////////////////////////////////////////////////////// class COpRegValueSingle : public COpRegKeySingle { public: COpRegValueSingle(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSingle &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op); protected: ATL::CAtlStringW m_sValueName; }; //////////////////////////////////////////////////////////////////////////// // COpRegValueSrcDst //////////////////////////////////////////////////////////////////////////// class COpRegValueSrcDst : public COpRegKeySingle { public: COpRegValueSrcDst(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueNameSrc = L"", LPCWSTR pszValueNameDst = L"", int iTicks = 0); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSrcDst &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op); protected: ATL::CAtlStringW m_sValueName1; ATL::CAtlStringW m_sValueName2; }; //////////////////////////////////////////////////////////////////////////// // COpRegValueCreate //////////////////////////////////////////////////////////////////////////// class COpRegValueCreate : public COpRegValueSingle { public: COpRegValueCreate(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0); COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORD dwData, int iTicks = 0); COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCVOID lpData, SIZE_T nSize, int iTicks = 0); COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, LPCWSTR pszData, int iTicks = 0); COpRegValueCreate(HKEY hKeyRoot, LPCWSTR pszKeyName, LPCWSTR pszValueName, DWORDLONG qwData, int iTicks = 0); virtual HRESULT Execute(CSession *pSession); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueCreate &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueCreate &op); protected: DWORD m_dwType; ATL::CAtlStringW m_sData; ATL::CAtlArray m_binData; DWORD m_dwData; ATL::CAtlArray m_szData; DWORDLONG m_qwData; }; //////////////////////////////////////////////////////////////////////////// // COpRegValueCopy //////////////////////////////////////////////////////////////////////////// class COpRegValueCopy : public COpRegValueSrcDst { public: COpRegValueCopy(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueNameSrc = L"", LPCWSTR pszValueNameDst = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpRegValueDelete //////////////////////////////////////////////////////////////////////////// class COpRegValueDelete : public COpRegValueSingle { public: COpRegValueDelete(HKEY hKeyRoot = NULL, LPCWSTR pszKeyName = L"", LPCWSTR pszValueName = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpTaskCreate //////////////////////////////////////////////////////////////////////////// class COpTaskCreate : public COpTypeSingleString { public: COpTaskCreate(LPCWSTR pszTaskName = L"", int iTicks = 0); virtual ~COpTaskCreate(); virtual HRESULT Execute(CSession *pSession); UINT SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord); UINT SetTriggersFromView(MSIHANDLE hView); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskCreate &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskCreate &op); protected: ATL::CAtlStringW m_sApplicationName; ATL::CAtlStringW m_sParameters; ATL::CAtlStringW m_sWorkingDirectory; ATL::CAtlStringW m_sAuthor; ATL::CAtlStringW m_sComment; DWORD m_dwFlags; DWORD m_dwPriority; ATL::CAtlStringW m_sAccountName; ATL::CAtlStringW m_sPassword; WORD m_wIdleMinutes; WORD m_wDeadlineMinutes; DWORD m_dwMaxRuntimeMS; ATL::CAtlList m_lTriggers; }; //////////////////////////////////////////////////////////////////////////// // COpTaskDelete //////////////////////////////////////////////////////////////////////////// class COpTaskDelete : public COpTypeSingleString { public: COpTaskDelete(LPCWSTR pszTaskName = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpTaskEnable //////////////////////////////////////////////////////////////////////////// class COpTaskEnable : public COpTypeSingleString { public: COpTaskEnable(LPCWSTR pszTaskName = L"", BOOL bEnable = TRUE, int iTicks = 0); virtual HRESULT Execute(CSession *pSession); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpTaskEnable &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskEnable &op); protected: BOOL m_bEnable; }; //////////////////////////////////////////////////////////////////////////// // COpTaskCopy //////////////////////////////////////////////////////////////////////////// class COpTaskCopy : public COpTypeSrcDstString { public: COpTaskCopy(LPCWSTR pszTaskSrc = L"", LPCWSTR pszTaskDst = L"", int iTicks = 0); virtual HRESULT Execute(CSession *pSession); }; //////////////////////////////////////////////////////////////////////////// // COpList //////////////////////////////////////////////////////////////////////////// class COpList : public COperation, public ATL::CAtlList { public: COpList(int iTicks = 0); void Free(); HRESULT LoadFromFile(LPCTSTR pszFileName); HRESULT SaveToFile(LPCTSTR pszFileName) const; virtual HRESULT Execute(CSession *pSession); friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &op); friend inline HRESULT operator >>(ATL::CAtlFile &f, COpList &op); protected: enum OPERATION { OP_ROLLBACK_ENABLE = 1, OP_FILE_DELETE, OP_FILE_MOVE, OP_REG_KEY_CREATE, OP_REG_KEY_COPY, OP_REG_KEY_DELETE, OP_REG_VALUE_CREATE, OP_REG_VALUE_COPY, OP_REG_VALUE_DELETE, OP_TASK_CREATE, OP_TASK_DELETE, OP_TASK_ENABLE, OP_TASK_COPY, OP_SUBLIST }; protected: template inline static HRESULT Save(ATL::CAtlFile &f, const COperation *p); template inline HRESULT LoadAndAddTail(ATL::CAtlFile &f); }; //////////////////////////////////////////////////////////////////////////// // CSession //////////////////////////////////////////////////////////////////////////// class CSession { public: CSession(); virtual ~CSession(); MSIHANDLE m_hInstall; // Installer handle BOOL m_bContinueOnError; // Continue execution on operation error? BOOL m_bRollbackEnabled; // Is rollback enabled? COpList m_olRollback; // Rollback operation list COpList m_olCommit; // Commit operation list }; } // namespace MSICA //////////////////////////////////////////////////////////////////// // Local includes //////////////////////////////////////////////////////////////////// #include #include #include #include //////////////////////////////////////////////////////////////////// // Inline Functions //////////////////////////////////////////////////////////////////// inline UINT MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, ATL::CAtlStringA &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the actual string length first. uiResult = ::MsiGetPropertyA(hInstall, szName, "", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to read the string data into and read it. LPSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiGetPropertyA(hInstall, szName, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The string in database is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, ATL::CAtlStringW &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the actual string length first. uiResult = ::MsiGetPropertyW(hInstall, szName, L"", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to read the string data into and read it. LPWSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiGetPropertyW(hInstall, szName, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The string in database is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiRecordGetStringA(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringA &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the actual string length first. uiResult = ::MsiRecordGetStringA(hRecord, iField, "", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to read the string data into and read it. LPSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiRecordGetStringA(hRecord, iField, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The string in database is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiRecordGetStringW(MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringW &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the actual string length first. uiResult = ::MsiRecordGetStringW(hRecord, iField, L"", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to read the string data into and read it. LPWSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiRecordGetStringW(hRecord, iField, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The string in database is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringA &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the final string length first. uiResult = ::MsiFormatRecordA(hInstall, hRecord, "", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to format the string data into and read it. LPSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiFormatRecordA(hInstall, hRecord, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The result is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringW &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the final string length first. uiResult = ::MsiFormatRecordW(hInstall, hRecord, L"", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to format the string data into and read it. LPWSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiFormatRecordW(hInstall, hRecord, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The result is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiRecordFormatStringA(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringA &sValue) { UINT uiResult; PMSIHANDLE hRecordEx; // Read string to format. uiResult = ::MsiRecordGetStringA(hRecord, iField, sValue); if (uiResult != ERROR_SUCCESS) return uiResult; // If the string is empty, there's nothing left to do. if (sValue.IsEmpty()) return ERROR_SUCCESS; // Create a record. hRecordEx = ::MsiCreateRecord(1); if (!hRecordEx) return ERROR_INVALID_HANDLE; // Populate record with data. uiResult = ::MsiRecordSetStringA(hRecordEx, 0, sValue); if (uiResult != ERROR_SUCCESS) return uiResult; // Do the formatting. return ::MsiFormatRecordA(hInstall, hRecordEx, sValue); } inline UINT MsiRecordFormatStringW(MSIHANDLE hInstall, MSIHANDLE hRecord, unsigned int iField, ATL::CAtlStringW &sValue) { UINT uiResult; PMSIHANDLE hRecordEx; // Read string to format. uiResult = ::MsiRecordGetStringW(hRecord, iField, sValue); if (uiResult != ERROR_SUCCESS) return uiResult; // If the string is empty, there's nothing left to do. if (sValue.IsEmpty()) return ERROR_SUCCESS; // Create a record. hRecordEx = ::MsiCreateRecord(1); if (!hRecordEx) return ERROR_INVALID_HANDLE; // Populate record with data. uiResult = ::MsiRecordSetStringW(hRecordEx, 0, sValue); if (uiResult != ERROR_SUCCESS) return uiResult; // Do the formatting. return ::MsiFormatRecordW(hInstall, hRecordEx, sValue); } #ifdef UNICODE #define MsiRecordFormatString MsiRecordFormatStringW #else #define MsiRecordFormatString MsiRecordFormatStringA #endif // !UNICODE inline UINT MsiGetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder, ATL::CAtlStringA &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the final string length first. uiResult = ::MsiGetTargetPathA(hInstall, szFolder, "", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to format the string data into and read it. LPSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The result is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } inline UINT MsiGetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, ATL::CAtlStringW &sValue) { DWORD dwSize = 0; UINT uiResult; // Query the final string length first. uiResult = ::MsiGetTargetPathW(hInstall, szFolder, L"", &dwSize); if (uiResult == ERROR_MORE_DATA) { // Prepare the buffer to format the string data into and read it. LPWSTR szBuffer = sValue.GetBuffer(dwSize++); if (!szBuffer) return ERROR_OUTOFMEMORY; uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szBuffer, &dwSize); sValue.ReleaseBuffer(uiResult == ERROR_SUCCESS ? dwSize : 0); return uiResult; } else if (uiResult == ERROR_SUCCESS) { // The result is empty. sValue.Empty(); return ERROR_SUCCESS; } else { // Return error code. return uiResult; } } namespace MSICA { //////////////////////////////////////////////////////////////////////////// // Inline operators //////////////////////////////////////////////////////////////////////////// inline HRESULT operator <<(ATL::CAtlFile &f, int i) { HRESULT hr; DWORD dwWritten; hr = f.Write(&i, sizeof(int), &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(int) ? hr : E_FAIL : hr; } inline HRESULT operator >>(ATL::CAtlFile &f, int &i) { HRESULT hr; DWORD dwRead; hr = f.Read(&i, sizeof(int), dwRead); return SUCCEEDED(hr) ? dwRead == sizeof(int) ? hr : E_FAIL : hr; } inline HRESULT operator <<(ATL::CAtlFile &f, DWORDLONG i) { HRESULT hr; DWORD dwWritten; hr = f.Write(&i, sizeof(DWORDLONG), &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(DWORDLONG) ? hr : E_FAIL : hr; } inline HRESULT operator >>(ATL::CAtlFile &f, DWORDLONG &i) { HRESULT hr; DWORD dwRead; hr = f.Read(&i, sizeof(DWORDLONG), dwRead); return SUCCEEDED(hr) ? dwRead == sizeof(DWORDLONG) ? hr : E_FAIL : hr; } template inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlArray &a) { HRESULT hr; DWORD dwCount = (DWORD)a.GetCount(), dwWritten; // Write element count. hr = f.Write(&dwCount, sizeof(DWORD), &dwWritten); if (FAILED(hr)) return hr; if (dwWritten < sizeof(DWORD)) return E_FAIL; // Write data. hr = f.Write(a.GetData(), sizeof(E) * dwCount, &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(E) * dwCount ? hr : E_FAIL : hr; } template inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlArray &a) { HRESULT hr; DWORD dwCount, dwRead; // Read element count as 32-bit integer. hr = f.Read(&dwCount, sizeof(DWORD), dwRead); if (FAILED(hr)) return hr; if (dwRead < sizeof(DWORD)) return E_FAIL; // Allocate the buffer. if (!a.SetCount(dwCount)) return E_OUTOFMEMORY; // Read data. hr = f.Read(a.GetData(), sizeof(E) * dwCount, dwRead); if (SUCCEEDED(hr)) a.SetCount(dwRead / sizeof(E)); return hr; } inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringA &str) { HRESULT hr; int iLength = str.GetLength(); DWORD dwWritten; // Write string length (in characters) as 32-bit integer. hr = f.Write(&iLength, sizeof(int), &dwWritten); if (FAILED(hr)) return hr; if (dwWritten < sizeof(int)) return E_FAIL; // Write string data (without terminator). hr = f.Write((LPCSTR)str, sizeof(CHAR) * iLength, &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(CHAR) * iLength ? hr : E_FAIL : hr; } inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringA &str) { HRESULT hr; int iLength; LPSTR buf; DWORD dwRead; // Read string length (in characters) as 32-bit integer. hr = f.Read(&iLength, sizeof(int), dwRead); if (FAILED(hr)) return hr; if (dwRead < sizeof(int)) return E_FAIL; // Allocate the buffer. buf = str.GetBuffer(iLength); if (!buf) return E_OUTOFMEMORY; // Read string data (without terminator). hr = f.Read(buf, sizeof(CHAR) * iLength, dwRead); str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(CHAR) : 0); return hr; } inline HRESULT operator <<(ATL::CAtlFile &f, const ATL::CAtlStringW &str) { HRESULT hr; int iLength = str.GetLength(); DWORD dwWritten; // Write string length (in characters) as 32-bit integer. hr = f.Write(&iLength, sizeof(int), &dwWritten); if (FAILED(hr)) return hr; if (dwWritten < sizeof(int)) return E_FAIL; // Write string data (without terminator). hr = f.Write((LPCWSTR)str, sizeof(WCHAR) * iLength, &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(WCHAR) * iLength ? hr : E_FAIL : hr; } inline HRESULT operator >>(ATL::CAtlFile &f, ATL::CAtlStringW &str) { HRESULT hr; int iLength; LPWSTR buf; DWORD dwRead; // Read string length (in characters) as 32-bit integer. hr = f.Read(&iLength, sizeof(int), dwRead); if (FAILED(hr)) return hr; if (dwRead < sizeof(int)) return E_FAIL; // Allocate the buffer. buf = str.GetBuffer(iLength); if (!buf) return E_OUTOFMEMORY; // Read string data (without terminator). hr = f.Read(buf, sizeof(WCHAR) * iLength, dwRead); str.ReleaseBuffer(SUCCEEDED(hr) ? dwRead / sizeof(WCHAR) : 0); return hr; } inline HRESULT operator <<(ATL::CAtlFile &f, const TASK_TRIGGER &ttData) { HRESULT hr; DWORD dwWritten; hr = f.Write(&ttData, sizeof(TASK_TRIGGER), &dwWritten); return SUCCEEDED(hr) ? dwWritten == sizeof(TASK_TRIGGER) ? hr : E_FAIL : hr; } inline HRESULT operator >>(ATL::CAtlFile &f, TASK_TRIGGER &ttData) { HRESULT hr; DWORD dwRead; hr = f.Read(&ttData, sizeof(TASK_TRIGGER), dwRead); return SUCCEEDED(hr) ? dwRead == sizeof(TASK_TRIGGER) ? hr : E_FAIL : hr; } inline HRESULT operator <<(ATL::CAtlFile &f, const COperation &op) { return f << op.m_iTicks; } inline HRESULT operator >>(ATL::CAtlFile &f, COperation &op) { return f >> op.m_iTicks; } inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSingleString &op) { HRESULT hr; hr = f << (const COperation &)op; if (FAILED(hr)) return hr; hr = f << op.m_sValue; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSingleString &op) { HRESULT hr; hr = f >> (COperation &)op; if (FAILED(hr)) return hr; hr = f >> op.m_sValue; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeSrcDstString &op) { HRESULT hr; hr = f << (const COperation &)op; if (FAILED(hr)) return hr; hr = f << op.m_sValue1; if (FAILED(hr)) return hr; hr = f << op.m_sValue2; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeSrcDstString &op) { HRESULT hr; hr = f >> (COperation &)op; if (FAILED(hr)) return hr; hr = f >> op.m_sValue1; if (FAILED(hr)) return hr; hr = f >> op.m_sValue2; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator <<(ATL::CAtlFile &f, const COpTypeBoolean &op) { HRESULT hr; hr = f << (const COperation &)op; if (FAILED(hr)) return hr; hr = f << (int)(op.m_bValue); if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpTypeBoolean &op) { HRESULT hr; int iValue; hr = f >> (COperation &)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 <<(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 COpRegValueSingle &op) { HRESULT hr; hr = f << (const COpRegKeySingle &)op; if (FAILED(hr)) return hr; hr = f << op.m_sValueName; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSingle &op) { HRESULT hr; hr = f >> (COpRegKeySingle &)op; if (FAILED(hr)) return hr; hr = f >> op.m_sValueName; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueSrcDst &op) { HRESULT hr; hr = f << (const COpRegKeySingle &)op; if (FAILED(hr)) return hr; hr = f << op.m_sValueName1; if (FAILED(hr)) return hr; hr = f << op.m_sValueName2; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueSrcDst &op) { HRESULT hr; hr = f >> (COpRegKeySingle &)op; if (FAILED(hr)) return hr; hr = f >> op.m_sValueName1; if (FAILED(hr)) return hr; hr = f >> op.m_sValueName2; if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator <<(ATL::CAtlFile &f, const COpRegValueCreate &op) { HRESULT hr; hr = f << (const COpRegValueSingle &)op; if (FAILED(hr)) return hr; hr = f << (int)(op.m_dwType); if (FAILED(hr)) return hr; switch (op.m_dwType) { case REG_SZ: case REG_EXPAND_SZ: case REG_LINK: hr = f << op.m_sData; if (FAILED(hr)) return hr; break; case REG_BINARY: hr = f << op.m_binData; if (FAILED(hr)) return hr; break; case REG_DWORD_LITTLE_ENDIAN: case REG_DWORD_BIG_ENDIAN: hr = f << (int)(op.m_dwData); if (FAILED(hr)) return hr; break; case REG_MULTI_SZ: hr = f << op.m_szData; if (FAILED(hr)) return hr; break; case REG_QWORD_LITTLE_ENDIAN: hr = f << op.m_qwData; if (FAILED(hr)) return hr; break; default: return E_UNEXPECTED; } return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpRegValueCreate &op) { HRESULT hr; hr = f >> (COpRegValueSingle &)op; if (FAILED(hr)) return hr; hr = f >> (int&)(op.m_dwType); if (FAILED(hr)) return hr; switch (op.m_dwType) { case REG_SZ: case REG_EXPAND_SZ: case REG_LINK: hr = f >> op.m_sData; if (FAILED(hr)) return hr; break; case REG_BINARY: hr = f >> op.m_binData; if (FAILED(hr)) return hr; break; case REG_DWORD_LITTLE_ENDIAN: case REG_DWORD_BIG_ENDIAN: hr = f >> (int&)(op.m_dwData); if (FAILED(hr)) return hr; break; case REG_MULTI_SZ: hr = f >> op.m_szData; if (FAILED(hr)) return hr; break; case REG_QWORD_LITTLE_ENDIAN: hr = f >> op.m_qwData; if (FAILED(hr)) return hr; break; default: return E_UNEXPECTED; } 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 << 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_sAuthor; 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 >>(ATL::CAtlFile &f, COpTaskCreate &op) { HRESULT hr; DWORD dwValue; 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; hr = f >> op.m_sAuthor; 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 <<(ATL::CAtlFile &f, const COpTaskEnable &op) { HRESULT hr; hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr; hr = f << (int)(op.m_bEnable); if (FAILED(hr)) return hr; return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpTaskEnable &op) { HRESULT hr; int iTemp; hr = f >> (COpTypeSingleString&)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 <<(ATL::CAtlFile &f, const COpList &list) { POSITION pos; HRESULT hr; hr = f << (const COperation &)list; if (FAILED(hr)) return hr; hr = f << (int)(list.GetCount()); if (FAILED(hr)) return hr; for (pos = list.GetHeadPosition(); pos;) { const COperation *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 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. hr = E_UNEXPECTED; } if (FAILED(hr)) return hr; } return S_OK; } inline HRESULT operator >>(ATL::CAtlFile &f, COpList &list) { HRESULT hr; int iCount; hr = f >> (COperation &)list; if (FAILED(hr)) return hr; hr = f >> iCount; if (FAILED(hr)) return hr; while (iCount--) { int iTemp; hr = f >> iTemp; if (FAILED(hr)) return hr; switch ((COpList::OPERATION)iTemp) { case COpList::OP_ROLLBACK_ENABLE: hr = list.LoadAndAddTail(f); break; case COpList::OP_FILE_DELETE: hr = list.LoadAndAddTail(f); break; case COpList::OP_FILE_MOVE: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_KEY_CREATE: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_KEY_COPY: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_KEY_DELETE: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_VALUE_CREATE: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_VALUE_COPY: hr = list.LoadAndAddTail(f); break; case COpList::OP_REG_VALUE_DELETE: hr = list.LoadAndAddTail(f); break; case COpList::OP_TASK_CREATE: hr = list.LoadAndAddTail(f); break; case COpList::OP_TASK_DELETE: hr = list.LoadAndAddTail(f); break; case COpList::OP_TASK_ENABLE: hr = list.LoadAndAddTail(f); break; case COpList::OP_TASK_COPY: hr = list.LoadAndAddTail(f); break; case COpList::OP_SUBLIST: hr = list.LoadAndAddTail(f); break; default: // Unsupported type of operation. hr = E_UNEXPECTED; } if (FAILED(hr)) return hr; } return S_OK; } //////////////////////////////////////////////////////////////////// // 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 //////////////////////////////////////////////////////////////////////////// template inline static HRESULT COpList::Save(ATL::CAtlFile &f, const COperation *p) { HRESULT hr; const T *pp = dynamic_cast(p); if (!pp) return E_UNEXPECTED; hr = f << (int)ID; if (FAILED(hr)) return hr; return f << *pp; } template inline HRESULT COpList::LoadAndAddTail(ATL::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; } } // namespace MSICA #endif // RC_INVOKED #endif // __MSICALib_H__