diff --git a/.gitattributes b/.gitattributes index 1705dcc..ee0872a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,15 @@ * text=auto !eol /MSICA.sln svneol=CRLF#text/plain eol=crlf +MSICACert/L10N/sl_SI.po -text +MSICACert/MSICACert.cpp -text +MSICACert/MSICACert.h -text +MSICACert/MSICACert.rc -text svneol=unset#unset +MSICACert/MSICACert.rcx -text svneol=unset#unset +MSICACert/MSICACert.vcxproj -text svneol=unset#text/xml +MSICACert/MSICACert.vcxproj.filters -text svneol=unset#text/xml +MSICACert/msm/Makefile -text svneol=unset#text/plain%3B+charset%3DWindows-1250 +MSICACert/stdafx.cpp -text +MSICACert/stdafx.h -text MSICALib/L10N/sl_SI.po -text MSICALib/MSICALib.cpp -text MSICALib/MSICALib.h -text diff --git a/.gitignore b/.gitignore index 8f16db4..ef2f2d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,18 @@ /*.opensdf /*.sdf /*.suo +MSICACert/*.user +MSICACert/L10N/*.mo +MSICACert/msm/*-1.idt +MSICACert/msm/*-2.idt +MSICACert/msm/*-2.idtx +MSICACert/msm/*.Binary-1 +MSICACert/msm/*.Binary-2 +MSICACert/msm/*.Icon-1 +MSICACert/msm/*.Icon-2 +MSICACert/msm/*.lst +MSICACert/msm/*.msm +MSICACert/temp MSICALib/*.user MSICALib/L10N/*.mo MSICALib/msm/*-1.idt diff --git a/MSICA.sln b/MSICA.sln index 92c7d35..dde0f03 100644 --- a/MSICA.sln +++ b/MSICA.sln @@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution include\version.h = include\version.h EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MSICACert", "MSICACert\MSICACert.vcxproj", "{0379563D-9835-44AC-928E-24D4E316CE5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -34,6 +36,14 @@ Global {A7D9EBC1-1E64-4399-9C88-6692F8742153}.Release|Win32.Build.0 = Release|Win32 {A7D9EBC1-1E64-4399-9C88-6692F8742153}.Release|x64.ActiveCfg = Release|x64 {A7D9EBC1-1E64-4399-9C88-6692F8742153}.Release|x64.Build.0 = Release|x64 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Debug|Win32.ActiveCfg = Debug|Win32 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Debug|Win32.Build.0 = Debug|Win32 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Debug|x64.ActiveCfg = Debug|x64 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Debug|x64.Build.0 = Debug|x64 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Release|Win32.ActiveCfg = Release|Win32 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Release|Win32.Build.0 = Release|Win32 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Release|x64.ActiveCfg = Release|x64 + {0379563D-9835-44AC-928E-24D4E316CE5D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MSICACert/L10N/sl_SI.po b/MSICACert/L10N/sl_SI.po new file mode 100644 index 0000000..657eb2f --- /dev/null +++ b/MSICACert/L10N/sl_SI.po @@ -0,0 +1,73 @@ +msgid "" +msgstr "" +"Project-Id-Version: MSICACert\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-13 11:34+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: Simon Rozman \n" +"Language-Team: Amebis, d. o. o., Kamnik \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: __\n" +"X-Poedit-Basepath: ..\n" +"X-Generator: Poedit 1.5.7\n" +"X-Poedit-SearchPath-0: .\n" + +# Language Code and Windows Charset (hexadecimal) +# If we do not intend to provide different localization of same base language (like merging Portugal Portugeese and Brasil Portugese into the same Portugeese), use the code of Microsoft defined default sublanguage. +# For example: Use LANG_PORTUGUESE + SUBLANG_DEFAULT = 0x416, although 0x416 represents Brasil Portugese (too). +#: MSICACert.rcx:42 +msgid "040904e4" +msgstr "042404e2" + +# Language Code (hexadecimal) +# If we do not intend to provide different localization of same base language (like merging Portugal Portugeese and Brasil Portugese into the same Portugeese), use the code of Microsoft defined default sublanguage. +# For example: Use LANG_PORTUGUESE + SUBLANG_DEFAULT = 0x416, although 0x416 represents Brasil Portugese (too). +#: MSICACert.rcx:60 +msgid "0x409" +msgstr "0x424" + +# Windows charset for this language (decimal) +#: MSICACert.rcx:60 +msgid "1252" +msgstr "1250" + +# The name of the constant in RC to include the resources in this language. +#: MSICACert.rcx:41 MSICACert.rcx:59 MSICACert.rcx:75 +msgid "AFX_TARG_ENU" +msgstr "AFX_TARG_SLV" + +#: MSICACert.rcx:44 +msgid "Amebis, d. o. o., Kamnik" +msgstr "Amebis, d. o. o., Kamnik" + +#: MSICACert.rcx:45 +msgid "Certificate Installation Support Library" +msgstr "Podporna knjižnica za nameščanje certifikatov" + +#: MSICACert.rcx:48 +msgid "Copyright © Amebis, d. o. o., Kamnik, 2012" +msgstr "Vse pravice pridržane © Amebis, d. o. o., Kamnik, 2012" + +# Language Identifier (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx) +#: MSICACert.rcx:77 +msgid "LANG_ENGLISH" +msgstr "LANG_SLOVENIAN" + +#: MSICACert.rcx:47 MSICACert.rcx:49 +msgid "MSICACert" +msgstr "MSICACert" + +# Sublanguage Identifier (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx) +#: MSICACert.rcx:77 +msgid "SUBLANG_DEFAULT" +msgstr "SUBLANG_DEFAULT" + +#~ msgid "Scheduled task: [1]" +#~ msgstr "Razporejeno opravilo: [1]" + +#~ msgid "Registering scheduled tasks" +#~ msgstr "Registracija razporejenih opravil" diff --git a/MSICACert/MSICACert.cpp b/MSICACert/MSICACert.cpp new file mode 100644 index 0000000..8bd316d --- /dev/null +++ b/MSICACert/MSICACert.cpp @@ -0,0 +1,216 @@ +#include "stdafx.h" + + +//////////////////////////////////////////////////////////////////////////// +// Local constants +//////////////////////////////////////////////////////////////////////////// + +#define MSICACERT_TASK_TICK_SIZE (16*1024) + + +//////////////////////////////////////////////////////////////////////////// +// Global functions +//////////////////////////////////////////////////////////////////////////// + +extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + UNREFERENCED_PARAMETER(hInstance); + UNREFERENCED_PARAMETER(lpReserved); + + return TRUE; +} + + +//////////////////////////////////////////////////////////////////// +// Exported functions +//////////////////////////////////////////////////////////////////// + +UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall) +{ + UINT uiResult; + HRESULT hr; + BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL)); + MSICA::COpList olExecute; + BOOL bRollbackEnabled; + PMSIHANDLE + hDatabase, + hRecordProg = ::MsiCreateRecord(3); + ATL::CAtlString sValue; + + // Check and add the rollback enabled state. + uiResult = ::MsiGetProperty(hInstall, _T("RollbackDisabled"), sValue); + bRollbackEnabled = uiResult == ERROR_SUCCESS ? + _ttoi(sValue) || !sValue.IsEmpty() && _totlower(sValue.GetAt(0)) == _T('y') ? FALSE : TRUE : + TRUE; + olExecute.AddTail(new MSICA::COpRollbackEnable(bRollbackEnabled)); + + // Open MSI database. + hDatabase = ::MsiGetActiveDatabase(hInstall); + if (hDatabase) { + // Check if ScheduledTask table exists. If it doesn't exist, there's nothing to do. + MSICONDITION condition = ::MsiDatabaseIsTablePersistent(hDatabase, _T("ScheduledTask")); + if (condition == MSICONDITION_FALSE || condition == MSICONDITION_TRUE) { + PMSIHANDLE hViewST; + + // Prepare a query to get a list/view of tasks. + uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Task,DisplayName,Application,Parameters,Directory_,Flags,Priority,User,Password,Author,Description,IdleMin,IdleDeadline,MaxRuntime,Condition,Component_ FROM ScheduledTask"), &hViewST); + if (uiResult == ERROR_SUCCESS) { + // Execute query! + uiResult = ::MsiViewExecute(hViewST, NULL); + if (uiResult == ERROR_SUCCESS) { + //ATL::CAtlString sComponent; + ATL::CAtlStringW sDisplayName; + + for (;;) { + PMSIHANDLE hRecord; + INSTALLSTATE iInstalled, iAction; + + // Fetch one record from the view. + uiResult = ::MsiViewFetch(hViewST, &hRecord); + if (uiResult == ERROR_NO_MORE_ITEMS) { + uiResult = ERROR_SUCCESS; + break; + } else if (uiResult != ERROR_SUCCESS) + break; + + // Read and evaluate task's condition. + uiResult = ::MsiRecordGetString(hRecord, 15, sValue); + if (uiResult != ERROR_SUCCESS) break; + condition = ::MsiEvaluateCondition(hInstall, sValue); + if (condition == MSICONDITION_FALSE) + continue; + else if (condition == MSICONDITION_ERROR) { + uiResult = ERROR_INVALID_FIELD; + break; + } + + // Read task's Component ID. + uiResult = ::MsiRecordGetString(hRecord, 16, sValue); + if (uiResult != ERROR_SUCCESS) break; + + // Get the component state. + uiResult = ::MsiGetComponentState(hInstall, sValue, &iInstalled, &iAction); + if (uiResult != ERROR_SUCCESS) break; + + // Get task's DisplayName. + uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 2, sDisplayName); + + if (iAction >= INSTALLSTATE_LOCAL) { + // Component is or should be installed. Create the task. + PMSIHANDLE hViewTT; + MSICA::COpTaskCreate *opCreateTask = new MSICA::COpTaskCreate(sDisplayName, MSICACERT_TASK_TICK_SIZE); + + // Populate the operation with task's data. + uiResult = opCreateTask->SetFromRecord(hInstall, hRecord); + if (uiResult != ERROR_SUCCESS) break; + + // Perform another query to get task's triggers. + uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Trigger,BeginDate,EndDate,StartTime,StartTimeRand,MinutesDuration,MinutesInterval,Flags,Type,DaysInterval,WeeksInterval,DaysOfTheWeek,DaysOfMonth,WeekOfMonth,MonthsOfYear FROM TaskTrigger WHERE Task_=?"), &hViewTT); + if (uiResult != ERROR_SUCCESS) break; + + // Execute query! + uiResult = ::MsiViewExecute(hViewTT, hRecord); + if (uiResult == ERROR_SUCCESS) { + // Populate trigger list. + uiResult = opCreateTask->SetTriggersFromView(hViewTT); + ::MsiViewClose(hViewTT); + if (uiResult != ERROR_SUCCESS) break; + } else + break; + + olExecute.AddTail(opCreateTask); + } else if (iAction >= INSTALLSTATE_REMOVED) { + // Component is installed, but should be degraded to advertised/removed. Delete the task. + olExecute.AddTail(new MSICA::COpTaskDelete(sDisplayName, MSICACERT_TASK_TICK_SIZE)); + } + + // The amount of tick space to add for each task to progress indicator. + ::MsiRecordSetInteger(hRecordProg, 1, 3 ); + ::MsiRecordSetInteger(hRecordProg, 2, MSICACERT_TASK_TICK_SIZE); + if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; } + } + ::MsiViewClose(hViewST); + + if (SUCCEEDED(uiResult)) { + ATL::CAtlString sSequenceFilename; + ATL::CAtlFile fSequence; + + // Prepare our own sequence script file. + // The InstallCertificates is a deferred custom action, thus all this information will be unavailable to it. + // Therefore save all required info to file now. + { + LPTSTR szBuffer = sSequenceFilename.GetBuffer(MAX_PATH); + ::GetTempPath(MAX_PATH, szBuffer); + ::GetTempFileName(szBuffer, _T("TS"), 0, szBuffer); + sSequenceFilename.ReleaseBuffer(); + } + // Save execute sequence to file. + hr = olExecute.SaveToFile(sSequenceFilename); + if (SUCCEEDED(hr)) { + // Store sequence script file names to properties for deferred custiom actions. + uiResult = ::MsiSetProperty(hInstall, _T("InstallCertificates"), sSequenceFilename); + if (uiResult == ERROR_SUCCESS) { + LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); + ATL::CAtlString sSequenceFilename2; + + sSequenceFilename2.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); + uiResult = ::MsiSetProperty(hInstall, _T("RollbackCertificates"), sSequenceFilename2); + if (uiResult == ERROR_SUCCESS) { + sSequenceFilename2.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); + uiResult = ::MsiSetProperty(hInstall, _T("CommitCertificates"), sSequenceFilename2); + if (uiResult != ERROR_SUCCESS) { + ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET); + ::MsiRecordSetString (hRecordProg, 2, _T("CommitCertificates")); + ::MsiRecordSetInteger(hRecordProg, 3, uiResult ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else { + ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET ); + ::MsiRecordSetString (hRecordProg, 2, _T("RollbackCertificates")); + ::MsiRecordSetInteger(hRecordProg, 3, uiResult ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else { + ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_PROPERTY_SET ); + ::MsiRecordSetString (hRecordProg, 2, _T("InstallCertificates")); + ::MsiRecordSetInteger(hRecordProg, 3, uiResult ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + if (uiResult != ERROR_SUCCESS) ::DeleteFile(sSequenceFilename); + } else { + uiResult = ERROR_INSTALL_SCRIPT_WRITE; + ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); + ::MsiRecordSetString (hRecordProg, 2, sSequenceFilename); + ::MsiRecordSetInteger(hRecordProg, 3, hr ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else if (uiResult != ERROR_INSTALL_USEREXIT) { + ::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_OPLIST_CREATE); + ::MsiRecordSetInteger(hRecordProg, 2, uiResult ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else { + ::MsiRecordSetInteger(hRecordProg, 1, uiResult); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else { + ::MsiRecordSetInteger(hRecordProg, 1, uiResult); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } + } else { + uiResult = ERROR_INSTALL_DATABASE_OPEN; + ::MsiRecordSetInteger(hRecordProg, 1, uiResult); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + + olExecute.Free(); + if (bIsCoInitialized) ::CoUninitialize(); + return uiResult; +} + + +UINT MSICACERT_API ExecuteSequence(MSIHANDLE hInstall) +{ + return MSICA::ExecuteSequence(hInstall); +} diff --git a/MSICACert/MSICACert.h b/MSICACert/MSICACert.h new file mode 100644 index 0000000..8913f8d --- /dev/null +++ b/MSICACert/MSICACert.h @@ -0,0 +1,34 @@ +#ifndef __MSICACERT_H__ +#define __MSICACERT_H__ + +#include + + +//////////////////////////////////////////////////////////////////// +// Calling declaration +//////////////////////////////////////////////////////////////////// + +#if defined(MSICACERT_DLL) +#define MSICACERT_API __declspec(dllexport) +#elif defined(MSICACERT_DLLIMP) +#define MSICACERT_API __declspec(dllimport) +#else +#define MSICACERT_API +#endif + +//////////////////////////////////////////////////////////////////// +// Exported functions +//////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + + UINT MSICACERT_API EvaluateSequence(MSIHANDLE hInstall); + UINT MSICACERT_API ExecuteSequence(MSIHANDLE hInstall); + +#ifdef __cplusplus +} +#endif + +#endif // __MSICACERT_H__ diff --git a/MSICACert/MSICACert.rc b/MSICACert/MSICACert.rc new file mode 100644 index 0000000..f4a1999 Binary files /dev/null and b/MSICACert/MSICACert.rc differ diff --git a/MSICACert/MSICACert.rcx b/MSICACert/MSICACert.rcx new file mode 100644 index 0000000..57e0e43 Binary files /dev/null and b/MSICACert/MSICACert.rcx differ diff --git a/MSICACert/MSICACert.vcxproj b/MSICACert/MSICACert.vcxproj new file mode 100644 index 0000000..1a815e9 --- /dev/null +++ b/MSICACert/MSICACert.vcxproj @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {0379563D-9835-44AC-928E-24D4E316CE5D} + v4.0 + + + + DynamicLibrary + Static + Unicode + true + + + DynamicLibrary + Static + Unicode + + + DynamicLibrary + Static + Unicode + true + + + DynamicLibrary + Static + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\output\$(Configuration).$(Platform)\ + true + ..\output\$(Configuration).$(Platform)\ + true + ..\output\$(Configuration).$(Platform)\ + true + ..\output\$(Configuration).$(Platform)\ + true + + + + Windows + + + %(Filename)_h.h + + + + L10N\sl_SI.po + + + + + + Windows + + + %(Filename)_h.h + + + + L10N\sl_SI.po + + + + + + Windows + + + %(Filename)_h.h + + + + L10N\sl_SI.po + + + + + + Windows + + + %(Filename)_h.h + + + + L10N\sl_SI.po + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + {8552ee55-177e-4f51-b51b-baf7d6462cde} + + + + + + + \ No newline at end of file diff --git a/MSICACert/MSICACert.vcxproj.filters b/MSICACert/MSICACert.vcxproj.filters new file mode 100644 index 0000000..1145ec2 --- /dev/null +++ b/MSICACert/MSICACert.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;rcx;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;po + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/MSICACert/msm/Makefile b/MSICACert/msm/Makefile new file mode 100644 index 0000000..c2d5639 --- /dev/null +++ b/MSICACert/msm/Makefile @@ -0,0 +1,167 @@ +!INCLUDE "..\..\include\MSIBuildCfg.mak" + +MSIBUILD_IS_LOCALIZEABLE=1 + + +###################################################################### +# _Validation + +All :: "$(LANG).$(PLAT).$(CFG)._Validation-1.idt" + +"$(LANG).$(PLAT).$(CFG)._Validation-1.idt" : "Makefile" ""..\..\include\MSIBuildCfg.mak"" + -if exist $@ del /f /q $@ + move /y << $@ > NUL +Table Column Nullable MinValue MaxValue KeyTable KeyColumn Category Set Description +s32 s32 s4 I4 I4 S255 I2 S32 S255 S255 +_Validation Table Column +ScheduledTask Task N Identifier Primary key, non-localized token. +ScheduledTask DisplayName N Formatted Task name. +ScheduledTask Application N Formatted Task application name. +ScheduledTask Parameters Y Formatted Task command line parameters. +ScheduledTask Directory_ N Directory 1 Identifier Task working directory. +ScheduledTask Flags N DoubleInteger Task's flags to pass in IScheduledWorkItem::SetFlags() call. +ScheduledTask Priority N DoubleInteger 32;64;128;256;16384,32768 Task's priority to pass in ITask::SetPriority() call. +ScheduledTask User Y Formatted Account name to run task as. Use empty string for system account. +ScheduledTask Password Y Formatted Account password to run task as. Use NULL for system account. +ScheduledTask Author Y Formatted Task author. +ScheduledTask Description Y Formatted Task description. +ScheduledTask IdleMin Y Integer A value that specifies how long, in minutes, the system must remain idle before the work item can run. +ScheduledTask IdleDeadline Y Integer A value that specifies the maximum number of minutes that the Task Scheduler will wait for the idle-time period. +ScheduledTask MaxRuntime N DoubleInteger Specifies the maximum run time (in milliseconds), for the task. This parameter may be set to -1 to specify an unlimited time. +ScheduledTask Condition Y Condition Optional expression which skips the task if evaluates to expFalse. If the expression syntax is invalid, the engine will terminate, returning iesBadActionData. +ScheduledTask Component_ N Component 1 Identifier Component the task is part of. +TaskTrigger Trigger N Identifier Primary key, non-localized token. +TaskTrigger BeginDate N DoubleInteger Date that the task trigger activates (counted in days from January 1st, 1980). The beginning date must be specified when setting a task. +TaskTrigger EndDate Y DoubleInteger Date that the task trigger deactivates (counted in days from January 1st, 1980). +TaskTrigger StartTime N DoubleInteger Time of the day the task runs (counted in minutes since midnight). +TaskTrigger StartTimeRand Y Integer Maximum random number of minutes to add to start time. +TaskTrigger MinutesDuration Y DoubleInteger Number of minutes after the task starts that the trigger will remain active. The number of minutes specified here must be greater than or equal to the MinutesInterval column. +TaskTrigger MinutesInterval Y DoubleInteger Number of minutes between consecutive task executions. This number is counted from the start of the previous scheduled task. The number of minutes specified here must be less than the MinutesDuration column. +TaskTrigger Flags N DoubleInteger Value that describes the behavior of the trigger. This value is a combination of the flags in TASK_TRIGGER::rgFlags. +TaskTrigger Type N 0 7 Integer A TASK_TRIGGER_TYPE enumerated value that specifies the type of trigger. This member is used with Type. The type of trigger specified here determines which fields of the TRIGGER_TYPE_UNION specified in Type member will be used. Trigger type is based on when the trigger will run the task. +TaskTrigger DaysInterval Y Integer Specifies the number of days between task runs. +TaskTrigger WeeksInterval Y Integer Number of weeks between invocations of a task. +TaskTrigger DaysOfTheWeek Y 0 127 Integer Value that describes the days of the week the task runs. This value is a bitfield and is a combination of the following values: 1=Sun, 2=Mon, 4=Tue, 8=Wed, 16=Thu, 32=Fri, 64=Sat. +TaskTrigger DaysOfMonth Y DoubleInteger Specifies the day of the month a task runs. This value is a bitfield that specifies the day(s) the task will run. Bit 0 corresponds to the first of the month, bit 1 to the second, and so forth. +TaskTrigger WeekOfMonth Y Integer 1;2;3;4;5 Specifies the week of the month when the task runs. This value is exclusive and is one of the following: 1=The task will run between the first and seventh day of the month, 2=The task will run between the eighth and 14th day of the month, 3=The task will run between the 15th and 21st day of the month, 4=The task will run between the 22nd and 28th of the month, 5=The task will run between the last seven days of the month. +TaskTrigger MonthsOfYear Y 0 4095 Integer Specifies the month(s) when the task runs. This value is a combination of the following values: 1=Jan, 2=Feb, 4=Mar, 8=Apr, 16=May, 32=Jun, 64=Jul, 128=Aug, 256=Sep, 512=Oct, 1024=Nov, 2048=Dec. +TaskTrigger Task_ N ScheduledTask 1 Identifier Key of the Trigger's task. +< NUL +Action Description Template +s$(MSIBUILD_LENGTH_ID) L0 L0 +1250 ActionText Action +InstallCertificates Installing certificates Certificate: [1] +< NUL + +"It.$(CFG).$(PLAT).ActionText-2.idt" : "En.$(PLAT).$(CFG).ActionText-2.idtx" "..\L10N\it_IT.po" + rcxgettext.exe idtp $@ $** + +"Sl.$(CFG).$(PLAT).ActionText-2.idt" : "En.$(PLAT).$(CFG).ActionText-2.idtx" "..\L10N\sl_SI.po" + rcxgettext.exe idtp $@ $** + + +###################################################################### +# Binary + +All :: \ + "$(LANG).$(PLAT).$(CFG).Binary-1.idt" \ + "$(LANG).$(PLAT).$(CFG).Binary-1\MSICACert.dll" + +"$(LANG).$(PLAT).$(CFG).Binary-1.idt" : "Makefile" ""..\..\include\MSIBuildCfg.mak"" "$(LANG).$(PLAT).$(CFG).Binary-1" + -if exist $@ del /f /q $@ + move /y << $@ > NUL +Name Data +s$(MSIBUILD_LENGTH_ID) v0 +Binary Name +binMSICACert.dll MSICACert.dll +< NUL + + +###################################################################### +# CustomAction + +All :: "$(LANG).$(PLAT).$(CFG).CustomAction-1.idt" + +"$(LANG).$(PLAT).$(CFG).CustomAction-1.idt" : "Makefile" ""..\..\include\MSIBuildCfg.mak"" + -if exist $@ del /f /q $@ + move /y << $@ > NUL +Action Type Source Target +s$(MSIBUILD_LENGTH_ID) i2 S$(MSIBUILD_LENGTH_ID) S255 +CustomAction Action +EvaluateCertificates 1 binMSICACert.dll EvaluateSequence +InstallCertificates 3073 binMSICACert.dll ExecuteSequence +RollbackCertificates 3329 binMSICACert.dll ExecuteSequence +CommitCertificates 3585 binMSICACert.dll ExecuteSequence +< NUL +Action Condition Sequence +s$(MSIBUILD_LENGTH_ID) S255 I2 +InstallExecuteSequence Action +EvaluateCertificates 6577 +RollbackCertificates 6576 +InstallCertificates 6578 +CommitCertificates 6579 +< NUL +Task DisplayName Application Parameters Directory_ Flags Priority User Password Author Description IdleMin IdleDeadline MaxRuntime Condition Component_ +s$(MSIBUILD_LENGTH_ID) l255 s255 S255 s$(MSIBUILD_LENGTH_ID) i4 i4 S255 S255 L255 L0 I2 I2 i4 S255 s$(MSIBUILD_LENGTH_ID) +ScheduledTask Task +< NUL +Trigger BeginDate EndDate StartTime StartTimeRand MinutesDuration MinutesInterval Flags Type DaysInterval WeeksInterval DaysOfTheWeek DaysOfMonth WeekOfMonth MonthsOfYear Task_ +s$(MSIBUILD_LENGTH_ID) i2 I2 i2 I2 I4 I4 i4 i2 I2 I2 I2 I4 I2 I2 s$(MSIBUILD_LENGTH_ID) +TaskTrigger Trigger +< +#include +#include + +#include +#include +#include + +#include "..\MSICALib\MSICALib.h" + +#include "MSICACert.h" diff --git a/MSICALib/MSICALib.cpp b/MSICALib/MSICALib.cpp index 94e4326..b3ac7be 100644 --- a/MSICALib/MSICALib.cpp +++ b/MSICALib/MSICALib.cpp @@ -181,4 +181,127 @@ CSession::~CSession() m_olCommit.Free(); } + +//////////////////////////////////////////////////////////////////////////// +// Helper functions +//////////////////////////////////////////////////////////////////////////// + +UINT ExecuteSequence(MSIHANDLE hInstall) +{ + UINT uiResult; + HRESULT hr; + BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL)); + ATL::CAtlString sSequenceFilename; + + uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename); + if (uiResult == ERROR_SUCCESS) { + MSICA::COpList lstOperations; + BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK); + + // Load operation sequence. + hr = lstOperations.LoadFromFile(sSequenceFilename); + if (SUCCEEDED(hr)) { + MSICA::CSession session; + + session.m_hInstall = hInstall; + + // In case of commit/rollback, continue sequence on error, to do as much cleanup as possible. + session.m_bContinueOnError = bIsCleanup; + + // Execute the operations. + hr = lstOperations.Execute(&session); + if (!bIsCleanup) { + // Save cleanup scripts of delayed action regardless of action's execution status. + // Rollback action MUST be scheduled in InstallExecuteSequence before this action! Otherwise cleanup won't be performed in case this action execution failed. + LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); + ATL::CAtlString sSequenceFilenameCM, sSequenceFilenameRB; + HRESULT hr; + + sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); + sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); + + // After commit, delete rollback file. After rollback, delete commit file. + session.m_olCommit.AddTail(new MSICA::COpFileDelete( +#ifdef _UNICODE + sSequenceFilenameRB +#else + ATL::CAtlStringW(sSequenceFilenameRB) +#endif + )); + session.m_olRollback.AddTail(new MSICA::COpFileDelete( +#ifdef _UNICODE + sSequenceFilenameCM +#else + ATL::CAtlStringW(sSequenceFilenameCM) +#endif + )); + + // Save commit file first. + hr = session.m_olCommit.SaveToFile(sSequenceFilenameCM); + if (SUCCEEDED(hr)) { + // Save rollback file next. + hr = session.m_olRollback.SaveToFile(sSequenceFilenameRB); + if (SUCCEEDED(hr)) { + uiResult = ERROR_SUCCESS; + } else { + // Saving rollback file failed. + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + uiResult = ERROR_INSTALL_SCRIPT_WRITE; + ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); + ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameRB); + ::MsiRecordSetInteger(hRecordProg, 3, hr ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + } else { + // Saving commit file failed. + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + uiResult = ERROR_INSTALL_SCRIPT_WRITE; + ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); + ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameCM); + ::MsiRecordSetInteger(hRecordProg, 3, hr ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + + if (uiResult != ERROR_SUCCESS) { + // The commit and/or rollback scripts were not written to file successfully. Perform the cleanup immediately. + session.m_bContinueOnError = TRUE; + session.m_bRollbackEnabled = FALSE; + session.m_olRollback.Execute(&session); + ::DeleteFile(sSequenceFilenameRB); + } + } else { + // No cleanup after cleanup support. + uiResult = ERROR_SUCCESS; + } + + if (FAILED(hr)) { + // Execution of the action failed. + uiResult = HRESULT_CODE(hr); + } + + ::DeleteFile(sSequenceFilename); + } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && bIsCleanup) { + // Sequence file not found and this is rollback/commit action. Either of the following scenarios are possible: + // - The delayed action failed to save the rollback/commit file. The delayed action performed cleanup itself. No further action is required. + // - Somebody removed the rollback/commit file between delayed action and rollback/commit action. No further action is possible. + uiResult = ERROR_SUCCESS; + } else { + // Sequence loading failed. Probably, LOCAL SYSTEM doesn't have read access to user's temp directory. + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + uiResult = ERROR_INSTALL_SCRIPT_READ; + ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); + ::MsiRecordSetString (hRecordProg, 2, sSequenceFilename); + ::MsiRecordSetInteger(hRecordProg, 3, hr ); + ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + + lstOperations.Free(); + } else { + // Couldn't get CustomActionData property. uiResult has the error code. + } + + if (bIsCoInitialized) ::CoUninitialize(); + return uiResult; +} + } // namespace MSICA diff --git a/MSICALib/MSICALib.h b/MSICALib/MSICALib.h index be87731..8c201d2 100644 --- a/MSICALib/MSICALib.h +++ b/MSICALib/MSICALib.h @@ -516,6 +516,13 @@ public: COpList m_olCommit; // Commit operation list }; + +//////////////////////////////////////////////////////////////////////////// +// Helper functions +//////////////////////////////////////////////////////////////////////////// + +UINT ExecuteSequence(MSIHANDLE hInstall); + } // namespace MSICA diff --git a/MSICATS/L10N/sl_SI.po b/MSICATS/L10N/sl_SI.po index d47d7a7..07608e4 100644 --- a/MSICATS/L10N/sl_SI.po +++ b/MSICATS/L10N/sl_SI.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: MSICATS\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-06-07 20:27+0100\n" +"POT-Creation-Date: 2014-03-13 11:35+0100\n" "PO-Revision-Date: \n" "Last-Translator: Simon Rozman \n" "Language-Team: Amebis, d. o. o., Kamnik \n" @@ -14,64 +14,60 @@ msgstr "" "X-Poedit-KeywordsList: __\n" "X-Poedit-Basepath: ..\n" "X-Generator: Poedit 1.5.7\n" -"X-Poedit-SearchPath-0: res\n" -"X-Poedit-SearchPath-1: msm\n" +"X-Poedit-SearchPath-0: .\n" # Language Code and Windows Charset (hexadecimal) # If we do not intend to provide different localization of same base language (like merging Portugal Portugeese and Brasil Portugese into the same Portugeese), use the code of Microsoft defined default sublanguage. # For example: Use LANG_PORTUGUESE + SUBLANG_DEFAULT = 0x416, although 0x416 represents Brasil Portugese (too). -#: MSICATS.rcx:43 +#: MSICATS.rcx:42 msgid "040904e4" msgstr "042404e2" # Language Code (hexadecimal) # If we do not intend to provide different localization of same base language (like merging Portugal Portugeese and Brasil Portugese into the same Portugeese), use the code of Microsoft defined default sublanguage. # For example: Use LANG_PORTUGUESE + SUBLANG_DEFAULT = 0x416, although 0x416 represents Brasil Portugese (too). -#: MSICATS.rcx:61 +#: MSICATS.rcx:60 msgid "0x409" msgstr "0x424" # Windows charset for this language (decimal) -#: MSICATS.rcx:61 ..\msm/Sl.DebugU.Win32.ActionText-2.idtx:3 -#: ..\msm/Sl.DebugU.Win32.Error-2.idtx:3 +#: MSICATS.rcx:60 msgid "1252" msgstr "1250" # The name of the constant in RC to include the resources in this language. -#: MSICATS.rcx:42 MSICATS.rcx:60 MSICATS.rcx:76 +#: MSICATS.rcx:41 MSICATS.rcx:59 MSICATS.rcx:75 msgid "AFX_TARG_ENU" msgstr "AFX_TARG_SLV" -#: MSICATS.rcx:45 +#: MSICATS.rcx:44 msgid "Amebis, d. o. o., Kamnik" msgstr "Amebis, d. o. o., Kamnik" +#: MSICATS.rcx:48 +msgid "Copyright © Amebis, d. o. o., Kamnik, 2012" +msgstr "Vse pravice pridržane © Amebis, d. o. o., Kamnik, 2012" + # Language Identifier (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx) -#: MSICATS.rcx:78 +#: MSICATS.rcx:77 msgid "LANG_ENGLISH" msgstr "LANG_SLOVENIAN" -#: MSICATS.rcx:48 MSICATS.rcx:50 +#: MSICATS.rcx:47 MSICATS.rcx:49 msgid "MSICATS" msgstr "MSICATS" -#: MSICATS.rcx:46 +#: MSICATS.rcx:45 msgid "Scheduled Task Installation Support Library" msgstr "Podporna knjižnica za nameščanje načrtovanih opravil" # Sublanguage Identifier (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx) -#: MSICATS.rcx:78 +#: MSICATS.rcx:77 msgid "SUBLANG_DEFAULT" msgstr "SUBLANG_DEFAULT" -#: MSICATS.rcx:49 -msgid "Copyright © Amebis, d. o. o., Kamnik, 2012" -msgstr "Vse pravice pridržane © Amebis, d. o. o., Kamnik, 2012" +#~ msgid "Scheduled task: [1]" +#~ msgstr "Razporejeno opravilo: [1]" -#: ..\msm/Sl.DebugU.Win32.ActionText-2.idtx:4 -msgid "Scheduled task: [1]" -msgstr "Razporejeno opravilo: [1]" - -#: ..\msm/Sl.DebugU.Win32.ActionText-2.idtx:4 -msgid "Registering scheduled tasks" -msgstr "Registracija razporejenih opravil" +#~ msgid "Registering scheduled tasks" +#~ msgstr "Registracija razporejenih opravil" diff --git a/MSICATS/MSICATS.cpp b/MSICATS/MSICATS.cpp index 978012e..ea08602 100644 --- a/MSICATS/MSICATS.cpp +++ b/MSICATS/MSICATS.cpp @@ -17,19 +17,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpRes UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(lpReserved); - switch (dwReason) { - case DLL_PROCESS_ATTACH: - //assert(0); // Attach debugger here, or press "Ignore"! - - // Randomize! - srand((unsigned)time(NULL)); - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; } @@ -38,7 +25,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpRes // Exported functions //////////////////////////////////////////////////////////////////// -UINT MSICATS_API EvaluateScheduledTasks(MSIHANDLE hInstall) +UINT MSICATS_API EvaluateSequence(MSIHANDLE hInstall) { UINT uiResult; HRESULT hr; @@ -223,122 +210,7 @@ UINT MSICATS_API EvaluateScheduledTasks(MSIHANDLE hInstall) } -UINT MSICATS_API InstallScheduledTasks(MSIHANDLE hInstall) +UINT MSICATS_API ExecuteSequence(MSIHANDLE hInstall) { - UINT uiResult; - HRESULT hr; - BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL)); - ATL::CAtlString sSequenceFilename; - - uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename); - if (uiResult == ERROR_SUCCESS) { - MSICA::COpList lstOperations; - BOOL bIsCleanup = ::MsiGetMode(hInstall, MSIRUNMODE_COMMIT) || ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK); - - //assert(0); // Attach debugger here, or press "Ignore"! - - // Load operation sequence. - hr = lstOperations.LoadFromFile(sSequenceFilename); - if (SUCCEEDED(hr)) { - MSICA::CSession session; - - session.m_hInstall = hInstall; - - // In case of commit/rollback, continue sequence on error, to do as much cleanup as possible. - session.m_bContinueOnError = bIsCleanup; - - // Execute the operations. - hr = lstOperations.Execute(&session); - if (!bIsCleanup) { - // Save cleanup scripts of delayed action regardless of action's execution status. - // Rollback action MUST be scheduled in InstallExecuteSequence before this action! Otherwise cleanup won't be performed in case this action execution failed. - LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); - ATL::CAtlString sSequenceFilenameCM, sSequenceFilenameRB; - HRESULT hr; - - sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); - sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); - - // After commit, delete rollback file. After rollback, delete commit file. - session.m_olCommit.AddTail(new MSICA::COpFileDelete( -#ifdef _UNICODE - sSequenceFilenameRB -#else - ATL::CAtlStringW(sSequenceFilenameRB) -#endif - )); - session.m_olRollback.AddTail(new MSICA::COpFileDelete( -#ifdef _UNICODE - sSequenceFilenameCM -#else - ATL::CAtlStringW(sSequenceFilenameCM) -#endif - )); - - // Save commit file first. - hr = session.m_olCommit.SaveToFile(sSequenceFilenameCM); - if (SUCCEEDED(hr)) { - // Save rollback file next. - hr = session.m_olRollback.SaveToFile(sSequenceFilenameRB); - if (SUCCEEDED(hr)) { - uiResult = ERROR_SUCCESS; - } else { - // Saving rollback file failed. - PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); - uiResult = ERROR_INSTALL_SCRIPT_WRITE; - ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); - ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameRB); - ::MsiRecordSetInteger(hRecordProg, 3, hr ); - ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); - } - } else { - // Saving commit file failed. - PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); - uiResult = ERROR_INSTALL_SCRIPT_WRITE; - ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); - ::MsiRecordSetString (hRecordProg, 2, sSequenceFilenameCM); - ::MsiRecordSetInteger(hRecordProg, 3, hr ); - ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); - } - - if (uiResult != ERROR_SUCCESS) { - // The commit and/or rollback scripts were not written to file successfully. Perform the cleanup immediately. - session.m_bContinueOnError = TRUE; - session.m_bRollbackEnabled = FALSE; - session.m_olRollback.Execute(&session); - ::DeleteFile(sSequenceFilenameRB); - } - } else { - // No cleanup after cleanup support. - uiResult = ERROR_SUCCESS; - } - - if (FAILED(hr)) { - // Execution of the action failed. - uiResult = HRESULT_CODE(hr); - } - - ::DeleteFile(sSequenceFilename); - } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && bIsCleanup) { - // Sequence file not found and this is rollback/commit action. Either of the following scenarios are possible: - // - The delayed action failed to save the rollback/commit file. The delayed action performed cleanup itself. No further action is required. - // - Somebody removed the rollback/commit file between delayed action and rollback/commit action. No further action is possible. - uiResult = ERROR_SUCCESS; - } else { - // Sequence loading failed. Probably, LOCAL SYSTEM doesn't have read access to user's temp directory. - PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); - uiResult = ERROR_INSTALL_SCRIPT_READ; - ::MsiRecordSetInteger(hRecordProg, 1, uiResult ); - ::MsiRecordSetString (hRecordProg, 2, sSequenceFilename); - ::MsiRecordSetInteger(hRecordProg, 3, hr ); - ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecordProg); - } - - lstOperations.Free(); - } else { - // Couldn't get CustomActionData property. uiResult has the error code. - } - - if (bIsCoInitialized) ::CoUninitialize(); - return uiResult; + return MSICA::ExecuteSequence(hInstall); } diff --git a/MSICATS/MSICATS.h b/MSICATS/MSICATS.h index 2bb009d..4f3fb9a 100644 --- a/MSICATS/MSICATS.h +++ b/MSICATS/MSICATS.h @@ -24,8 +24,8 @@ extern "C" { #endif - UINT MSICATS_API EvaluateScheduledTasks(MSIHANDLE hInstall); - UINT MSICATS_API InstallScheduledTasks(MSIHANDLE hInstall); + UINT MSICATS_API EvaluateSequence(MSIHANDLE hInstall); + UINT MSICATS_API ExecuteSequence(MSIHANDLE hInstall); #ifdef __cplusplus } diff --git a/MSICATS/msm/Makefile b/MSICATS/msm/Makefile index 5fdff92..d1f538c 100644 --- a/MSICATS/msm/Makefile +++ b/MSICATS/msm/Makefile @@ -107,10 +107,10 @@ All :: "$(LANG).$(PLAT).$(CFG).CustomAction-1.idt" Action Type Source Target s$(MSIBUILD_LENGTH_ID) i2 S$(MSIBUILD_LENGTH_ID) S255 CustomAction Action -EvaluateScheduledTasks 1 binMSICATS.dll EvaluateScheduledTasks -InstallScheduledTasks 3073 binMSICATS.dll InstallScheduledTasks -RollbackScheduledTasks 3329 binMSICATS.dll InstallScheduledTasks -CommitScheduledTasks 3585 binMSICATS.dll InstallScheduledTasks +EvaluateScheduledTasks 1 binMSICATS.dll EvaluateSequence +InstallScheduledTasks 3073 binMSICATS.dll ExecuteSequence +RollbackScheduledTasks 3329 binMSICATS.dll ExecuteSequence +CommitScheduledTasks 3585 binMSICATS.dll ExecuteSequence <