From d5162a64d7ec7f5bf52fb4c92695aabfa69cd83c Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 9 Jan 2013 13:14:41 +0000 Subject: [PATCH] Dodal sem polno podporo za Task Scheduler 2.0. Dodal sem obvestila o napakah pri delu z razporejenimi opravili. Estetski popravki --- .gitattributes | 1 - MSICALib/MSI/Makefile | 21 +- MSICALib/MSITSCA.cpp | 90 ++-- MSICALib/MSITSCA.h | 4 + MSICALib/MSITSCA.vcxproj | 1 - MSICALib/MSITSCA.vcxproj.filters | 1 - MSICALib/MSITSCAOp.cpp | 803 ++++++++++++++++++++----------- MSICALib/MSITSCAOp.h | 164 +++---- MSICALib/Naredi.txt | 3 - MSICALib/StdAfx.h | 3 +- MSICALib/res/en_GB.po | 102 +++- 11 files changed, 765 insertions(+), 428 deletions(-) delete mode 100644 MSICALib/Naredi.txt diff --git a/.gitattributes b/.gitattributes index db6e65b..74286d5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,7 +6,6 @@ MSICALib/MSITSCA.vcxproj -text svneol=unset#text/xml MSICALib/MSITSCA.vcxproj.filters -text svneol=unset#text/xml MSICALib/MSITSCAOp.cpp -text MSICALib/MSITSCAOp.h -text -MSICALib/Naredi.txt -text MSICALib/StdAfx.cpp -text MSICALib/StdAfx.h -text MSICALib/res/MSITSCA.rc -text svneol=unset#unset diff --git a/MSICALib/MSI/Makefile b/MSICALib/MSI/Makefile index 731fe5a..27c8ca7 100644 --- a/MSICALib/MSI/Makefile +++ b/MSICALib/MSI/Makefile @@ -30,6 +30,7 @@ ScheduledTask Flags N DoubleInteger Task's flags to pass in IScheduledWorkI 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. @@ -131,12 +132,16 @@ Vse :: "$(JEZIK).$(CFG).$(PLAT).Error-2.idt" Error Message i2 L0 1250 Error Error -2550 Pri odpiranju namestitvenega paketa je prišlo do napake. -2551 Pri pripravi seznama razvrščenih opravil je prišlo do napake [2]. -2552 Pri pisanju v datoteko seznama razporejenih opravil »[2]« je prišlo do napake [3]. -2553 Pri nastavljanju parametra »[2]« je prišlo do napake [3]. -2554 Pri brisanju datoteke »[2]« je prišlo do napake [3]. -2555 Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. +2550 Pri odpiranju namestitvenega paketa je prišlo do napake. Obrnite se na svojo tehnično službo. +2551 Pri pripravi seznama razvrščenih opravil je prišlo do napake [2]. Obrnite se na svojo tehnično službo. +2552 Pri pisanju v datoteko seznama razporejenih opravil »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2553 Pri nastavljanju parametra »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2554 Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2555 Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na svojo tehnično službo. +2556 Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2557 Pri brisanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2558 Pri o(ne)mogočanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite se na svojo tehnično službo. +2559 Pri kopiranju razporejenega opravila »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na svojo tehnično službo. < NUL -Task DisplayName Application Parameters WorkingDir Flags Priority User Password Description IdleMin IdleDeadline MaxRuntime Condition Component_ -s$(MSI_TIP_ID) s255 s255 S255 s255 i4 i4 S255 S255 S255 I2 I2 i4 S255 s$(MSI_TIP_ID) +Task DisplayName Application Parameters WorkingDir Flags Priority User Password Author Description IdleMin IdleDeadline MaxRuntime Condition Component_ +s$(MSI_TIP_ID) s255 s255 S255 s255 i4 i4 S255 S255 S255 S255 I2 I2 i4 S255 s$(MSI_TIP_ID) ScheduledTask Task <= INSTALLSTATE_LOCAL) { // Component is or should be installed. Create the task. PMSIHANDLE hViewTT; - CMSITSCAOpCreateTask *opCreateTask = new CMSITSCAOpCreateTask(sDisplayName, MSITSCA_TASK_TICK_SIZE); + CMSITSCAOpTaskCreate *opCreateTask = new CMSITSCAOpTaskCreate(sDisplayName, MSITSCA_TASK_TICK_SIZE); assert(opCreateTask); // Populate the operation with task's data. - opCreateTask->SetFromRecord(hInstall, hRecord); + 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); @@ -138,7 +141,7 @@ UINT MSITSCA_API EvaluateScheduledTasks(MSIHANDLE hInstall) olExecute.AddTail(opCreateTask); } else if (iAction >= INSTALLSTATE_REMOVED) { // Component is installed, but should be degraded to advertised/removed. Delete the task. - olExecute.AddTail(new CMSITSCAOpDeleteTask(sDisplayName, MSITSCA_TASK_TICK_SIZE)); + olExecute.AddTail(new CMSITSCAOpTaskDelete(sDisplayName, MSITSCA_TASK_TICK_SIZE)); } // The amount of tick space to add for each task to progress indicator. @@ -235,7 +238,9 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall) BOOL bIsCoInitialized = SUCCEEDED(::CoInitialize(NULL)); CString sSequenceFilename; +#ifdef ASSERT_TO_DEBUG assert(0); // Attach debugger here, or press "Ignore"! +#endif uiResult = ::MsiGetProperty(hInstall, _T("CustomActionData"), sSequenceFilename); if (uiResult == ERROR_SUCCESS) { @@ -252,59 +257,52 @@ UINT MSITSCA_API InstallScheduledTasks(MSIHANDLE hInstall) // In case of commit/rollback, continue sequence on error, to do as much cleanup as possible. session.m_bContinueOnError = bIsCleanup; - // Get task scheduler object. - hr = session.m_pTaskScheduler.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_ALL); + // Execute the operations. + hr = lstOperations.Execute(&session); if (SUCCEEDED(hr)) { - // Execute the operations. - hr = lstOperations.Execute(&session); - if (SUCCEEDED(hr)) { - if (!bIsCleanup && session.m_bRollbackEnabled) { - // Save cleanup scripts. - LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); - CString sSequenceFilenameCM, sSequenceFilenameRB; + if (!bIsCleanup && session.m_bRollbackEnabled) { + // Save cleanup scripts. + LPCTSTR pszExtension = ::PathFindExtension(sSequenceFilename); + CString sSequenceFilenameCM, sSequenceFilenameRB; - sSequenceFilenameRB.Format(_T("%.*ls-rb%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); - sSequenceFilenameCM.Format(_T("%.*ls-cm%ls"), pszExtension - (LPCTSTR)sSequenceFilename, (LPCTSTR)sSequenceFilename, pszExtension); + 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 end of commit, delete rollback file too. After end of rollback, delete commit file too. - session.m_olCommit.AddTail(new CMSITSCAOpDeleteFile(sSequenceFilenameRB)); - session.m_olRollback.AddTail(new CMSITSCAOpDeleteFile(sSequenceFilenameCM)); + // After end of commit, delete rollback file too. After end of rollback, delete commit file too. + session.m_olCommit.AddTail(new CMSITSCAOpFileDelete(sSequenceFilenameRB)); + session.m_olRollback.AddTail(new CMSITSCAOpFileDelete(sSequenceFilenameCM)); - // Save commit file first. - hr = session.m_olCommit.SaveToFile(sSequenceFilenameCM); + // 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)) { - // Save rollback file next. - hr = session.m_olRollback.SaveToFile(sSequenceFilenameRB); - if (SUCCEEDED(hr)) { - uiResult = ERROR_SUCCESS; - } else { - // Saving rollback file failed. - uiResult = HRESULT_CODE(hr); - } + uiResult = ERROR_SUCCESS; } else { - // Saving commit file failed. + // Saving rollback file failed. uiResult = HRESULT_CODE(hr); } } else { - // No cleanup support required. - uiResult = ERROR_SUCCESS; + // Saving commit file failed. + uiResult = HRESULT_CODE(hr); } } else { - // Execution failed. - uiResult = HRESULT_CODE(hr); - } - - if (uiResult != ERROR_SUCCESS) { - // Perform the cleanup now. The rollback script might not have been written to file yet. - // And even if it was, the rollback action might not get invoked at all (if scheduled in InstallExecuteSequence later than this action). - session.m_bContinueOnError = TRUE; - session.m_bRollbackEnabled = FALSE; - verify(SUCCEEDED(session.m_olRollback.Execute(&session))); + // No cleanup support required. + uiResult = ERROR_SUCCESS; } } else { - // Task scheduler creation failed. + // Execution failed. uiResult = HRESULT_CODE(hr); } + + if (uiResult != ERROR_SUCCESS) { + // Perform the cleanup now. The rollback script might not have been written to file yet. + // And even if it was, the rollback action might not get invoked at all (if scheduled in InstallExecuteSequence later than this action). + session.m_bContinueOnError = TRUE; + session.m_bRollbackEnabled = FALSE; + verify(SUCCEEDED(session.m_olRollback.Execute(&session))); + } } else { // Sequence loading failed. Don't panic => do nothing. uiResult = ERROR_SUCCESS; diff --git a/MSICALib/MSITSCA.h b/MSICALib/MSITSCA.h index 3efa8d8..2503a87 100644 --- a/MSICALib/MSITSCA.h +++ b/MSICALib/MSITSCA.h @@ -45,6 +45,10 @@ #define ERROR_INSTALL_SCHEDULED_TASKS_PROPERTY_SET 2553L #define ERROR_INSTALL_DELETE_FAILED 2554L #define ERROR_INSTALL_MOVE_FAILED 2555L +#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 //////////////////////////////////////////////////////////////////// diff --git a/MSICALib/MSITSCA.vcxproj b/MSICALib/MSITSCA.vcxproj index 6ab70c8..90a8404 100644 --- a/MSICALib/MSITSCA.vcxproj +++ b/MSICALib/MSITSCA.vcxproj @@ -273,7 +273,6 @@ - diff --git a/MSICALib/MSITSCA.vcxproj.filters b/MSICALib/MSITSCA.vcxproj.filters index b5960ed..a03fa1e 100644 --- a/MSICALib/MSITSCA.vcxproj.filters +++ b/MSICALib/MSITSCA.vcxproj.filters @@ -50,6 +50,5 @@ Resource Files - \ No newline at end of file diff --git a/MSICALib/MSITSCAOp.cpp b/MSICALib/MSITSCAOp.cpp index 90b69d0..b30a6ae 100644 --- a/MSICALib/MSITSCAOp.cpp +++ b/MSICALib/MSITSCAOp.cpp @@ -14,10 +14,10 @@ CMSITSCAOp::CMSITSCAOp(int iTicks) : //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpSingleStringOperation +// CMSITSCAOpTypeSingleString //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpSingleStringOperation::CMSITSCAOpSingleStringOperation(LPCWSTR pszValue, int iTicks) : +CMSITSCAOpTypeSingleString::CMSITSCAOpTypeSingleString(LPCWSTR pszValue, int iTicks) : m_sValue(pszValue), CMSITSCAOp(iTicks) { @@ -28,7 +28,7 @@ CMSITSCAOpSingleStringOperation::CMSITSCAOpSingleStringOperation(LPCWSTR pszValu // CMSITSCAOpDoubleStringOperation //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpSrcDstStringOperation::CMSITSCAOpSrcDstStringOperation(LPCWSTR pszValue1, LPCWSTR pszValue2, int iTicks) : +CMSITSCAOpTypeSrcDstString::CMSITSCAOpTypeSrcDstString(LPCWSTR pszValue1, LPCWSTR pszValue2, int iTicks) : m_sValue1(pszValue1), m_sValue2(pszValue2), CMSITSCAOp(iTicks) @@ -37,10 +37,10 @@ CMSITSCAOpSrcDstStringOperation::CMSITSCAOpSrcDstStringOperation(LPCWSTR pszValu //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpBooleanOperation +// CMSITSCAOpTypeBoolean //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpBooleanOperation::CMSITSCAOpBooleanOperation(BOOL bValue, int iTicks) : +CMSITSCAOpTypeBoolean::CMSITSCAOpTypeBoolean(BOOL bValue, int iTicks) : m_bValue(bValue), CMSITSCAOp(iTicks) { @@ -48,16 +48,16 @@ CMSITSCAOpBooleanOperation::CMSITSCAOpBooleanOperation(BOOL bValue, int iTicks) //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpEnableRollback +// CMSITSCAOpRollbackEnable //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpEnableRollback::CMSITSCAOpEnableRollback(BOOL bEnable, int iTicks) : - CMSITSCAOpBooleanOperation(bEnable, iTicks) +CMSITSCAOpRollbackEnable::CMSITSCAOpRollbackEnable(BOOL bEnable, int iTicks) : + CMSITSCAOpTypeBoolean(bEnable, iTicks) { } -HRESULT CMSITSCAOpEnableRollback::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpRollbackEnable::Execute(CMSITSCASession *pSession) { assert(pSession); @@ -67,16 +67,16 @@ HRESULT CMSITSCAOpEnableRollback::Execute(CMSITSCASession *pSession) //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpDeleteFile +// CMSITSCAOpFileDelete //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpDeleteFile::CMSITSCAOpDeleteFile(LPCWSTR pszFileName, int iTicks) : - CMSITSCAOpSingleStringOperation(pszFileName, iTicks) +CMSITSCAOpFileDelete::CMSITSCAOpFileDelete(LPCWSTR pszFileName, int iTicks) : + CMSITSCAOpTypeSingleString(pszFileName, iTicks) { } -HRESULT CMSITSCAOpDeleteFile::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpFileDelete::Execute(CMSITSCASession *pSession) { assert(pSession); DWORD dwError; @@ -92,10 +92,10 @@ HRESULT CMSITSCAOpDeleteFile::Execute(CMSITSCASession *pSession) } while (dwError == ERROR_ALREADY_EXISTS); if (dwError == ERROR_SUCCESS) { // Order rollback action to restore from backup copy. - pSession->m_olRollback.AddHead(new CMSITSCAOpMoveFile(sBackupName, m_sValue)); + pSession->m_olRollback.AddHead(new CMSITSCAOpFileMove(sBackupName, m_sValue)); // Order commit action to delete backup copy. - pSession->m_olCommit.AddTail(new CMSITSCAOpDeleteFile(sBackupName)); + pSession->m_olCommit.AddTail(new CMSITSCAOpFileDelete(sBackupName)); } } else { // Delete the file. @@ -116,16 +116,16 @@ HRESULT CMSITSCAOpDeleteFile::Execute(CMSITSCASession *pSession) //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpMoveFile +// CMSITSCAOpFileMove //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpMoveFile::CMSITSCAOpMoveFile(LPCWSTR pszFileSrc, LPCWSTR pszFileDst, int iTicks) : - CMSITSCAOpSrcDstStringOperation(pszFileSrc, pszFileDst, iTicks) +CMSITSCAOpFileMove::CMSITSCAOpFileMove(LPCWSTR pszFileSrc, LPCWSTR pszFileDst, int iTicks) : + CMSITSCAOpTypeSrcDstString(pszFileSrc, pszFileDst, iTicks) { } -HRESULT CMSITSCAOpMoveFile::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpFileMove::Execute(CMSITSCASession *pSession) { assert(pSession); DWORD dwError; @@ -135,7 +135,7 @@ HRESULT CMSITSCAOpMoveFile::Execute(CMSITSCASession *pSession) if (dwError == ERROR_SUCCESS) { if (pSession->m_bRollbackEnabled) { // Order rollback action to move it back. - pSession->m_olRollback.AddHead(new CMSITSCAOpMoveFile(m_sValue2, m_sValue1)); + pSession->m_olRollback.AddHead(new CMSITSCAOpFileMove(m_sValue2, m_sValue1)); } return S_OK; @@ -152,21 +152,21 @@ HRESULT CMSITSCAOpMoveFile::Execute(CMSITSCASession *pSession) //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpCreateTask +// CMSITSCAOpTaskCreate //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpCreateTask::CMSITSCAOpCreateTask(LPCWSTR pszTaskName, int iTicks) : +CMSITSCAOpTaskCreate::CMSITSCAOpTaskCreate(LPCWSTR pszTaskName, int iTicks) : m_dwFlags(0), m_dwPriority(NORMAL_PRIORITY_CLASS), m_wIdleMinutes(0), m_wDeadlineMinutes(0), m_dwMaxRuntimeMS(INFINITE), - CMSITSCAOpSingleStringOperation(pszTaskName, iTicks) + CMSITSCAOpTypeSingleString(pszTaskName, iTicks) { } -CMSITSCAOpCreateTask::~CMSITSCAOpCreateTask() +CMSITSCAOpTaskCreate::~CMSITSCAOpTaskCreate() { // Clear the password in memory. int iLength = m_sPassword.GetLength(); @@ -175,12 +175,12 @@ CMSITSCAOpCreateTask::~CMSITSCAOpCreateTask() } -HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpTaskCreate::Execute(CMSITSCASession *pSession) { HRESULT hr; - POSITION pos; PMSIHANDLE hRecordMsg = ::MsiCreateRecord(1); CComPtr pService; + POSITION pos; // Display our custom message in the progress bar. verify(::MsiRecordSetStringW(hRecordMsg, 1, m_sValue) == ERROR_SUCCESS); @@ -190,10 +190,10 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) { // Delete existing task first. // Since task deleting is a complicated job (when rollback/commit support is required), and we do have an operation just for that, we use it. - // Don't worry, CMSITSCAOpDeleteTask::Execute() returns S_OK if task doesn't exist. - CMSITSCAOpDeleteTask opDeleteTask(m_sValue); + // Don't worry, CMSITSCAOpTaskDelete::Execute() returns S_OK if task doesn't exist. + CMSITSCAOpTaskDelete opDeleteTask(m_sValue); hr = opDeleteTask.Execute(pSession); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } hr = pService.CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER); @@ -209,6 +209,7 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) CComPtr pExecAction; CComPtr pRegististrationInfo; CComPtr pTriggerCollection; + CComPtr pTaskFolder; CComPtr pTask; CStringW str; UINT iTrigger; @@ -217,65 +218,61 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) // Connect to local task service. hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Prepare the definition for a new task. hr = pService->NewTask(0, &pTaskDefinition); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Get the task's settings. hr = pTaskDefinition->get_Settings(&pTaskSettings); - if (FAILED(hr)) return hr; - - // Configure Task Scheduler 1.0 compatible task. - hr = pTaskSettings->put_Compatibility(TASK_COMPATIBILITY_V1); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Enable/disable task. if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) { // The task is supposed to be enabled. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. - pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE)); + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); m_dwFlags |= TASK_FLAG_DISABLED; } - hr = pTaskSettings->put_Enabled(m_dwFlags & TASK_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); if (FAILED(hr)) return hr; + hr = pTaskSettings->put_Enabled(m_dwFlags & TASK_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); if (FAILED(hr)) goto finish; // Get task actions. hr = pTaskDefinition->get_Actions(&pActionCollection); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Add execute action. hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pAction.QueryInterface(&pExecAction); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Configure the action. - hr = pExecAction->put_Path (CComBSTR(m_sApplicationName )); if (FAILED(hr)) return hr; - hr = pExecAction->put_Arguments (CComBSTR(m_sParameters )); if (FAILED(hr)) return hr; - hr = pExecAction->put_WorkingDirectory(CComBSTR(m_sWorkingDirectory)); if (FAILED(hr)) return hr; + hr = pExecAction->put_Path (CComBSTR(m_sApplicationName )); if (FAILED(hr)) goto finish; + hr = pExecAction->put_Arguments (CComBSTR(m_sParameters )); if (FAILED(hr)) goto finish; + hr = pExecAction->put_WorkingDirectory(CComBSTR(m_sWorkingDirectory)); if (FAILED(hr)) goto finish; // Set task description. hr = pTaskDefinition->get_RegistrationInfo(&pRegististrationInfo); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; + hr = pRegististrationInfo->put_Author(CComBSTR(m_sAuthor)); + if (FAILED(hr)) goto finish; hr = pRegististrationInfo->put_Description(CComBSTR(m_sComment)); - if (FAILED(hr)) return hr; - - hr = pRegististrationInfo->put_Author(CComBSTR(L"Amebis, d. o. o., Kamnik")); + if (FAILED(hr)) goto finish; // Configure task "flags". if (m_dwFlags & TASK_FLAG_DELETE_WHEN_DONE) { hr = pTaskSettings->put_DeleteExpiredTaskAfter(CComBSTR(L"PT24H")); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } hr = pTaskSettings->put_Hidden(m_dwFlags & TASK_FLAG_HIDDEN ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pTaskSettings->put_WakeToRun(m_dwFlags & TASK_FLAG_SYSTEM_REQUIRED ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pTaskSettings->put_DisallowStartIfOnBatteries(m_dwFlags & TASK_FLAG_DONT_START_IF_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pTaskSettings->put_StopIfGoingOnBatteries(m_dwFlags & TASK_FLAG_KILL_IF_GOING_ON_BATTERIES ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Configure task priority. hr = pTaskSettings->put_Priority( @@ -285,58 +282,58 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) m_dwPriority == NORMAL_PRIORITY_CLASS ? 4 : m_dwPriority == BELOW_NORMAL_PRIORITY_CLASS ? 7 : m_dwPriority == IDLE_PRIORITY_CLASS ? 9 : 7); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Get task principal. hr = pTaskDefinition->get_Principal(&pPrincipal); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; if (m_sAccountName.IsEmpty()) { logonType = TASK_LOGON_SERVICE_ACCOUNT; - hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr; - hr = pPrincipal->put_UserId(CComBSTR(L"S-1-5-18")); if (FAILED(hr)) return hr; - hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) return hr; + hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish; + hr = pPrincipal->put_UserId(CComBSTR(L"S-1-5-18")); if (FAILED(hr)) goto finish; + hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish; } else if (m_dwFlags & TASK_FLAG_RUN_ONLY_IF_LOGGED_ON) { logonType = TASK_LOGON_INTERACTIVE_TOKEN; - hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr; - hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_LUA); if (FAILED(hr)) return hr; + hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish; + hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_LUA); if (FAILED(hr)) goto finish; } else { logonType = TASK_LOGON_PASSWORD; - hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) return hr; - hr = pPrincipal->put_UserId(CComBSTR(m_sAccountName)); if (FAILED(hr)) return hr; - hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) return hr; + hr = pPrincipal->put_LogonType(logonType); if (FAILED(hr)) goto finish; + hr = pPrincipal->put_UserId(CComBSTR(m_sAccountName)); if (FAILED(hr)) goto finish; + hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); if (FAILED(hr)) goto finish; } // Connect principal and action collection. hr = pPrincipal->put_Id(bstrContext); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pActionCollection->put_Context(bstrContext); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Configure idle settings. hr = pTaskSettings->put_RunOnlyIfIdle(m_dwFlags & TASK_FLAG_START_ONLY_IF_IDLE ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pTaskSettings->get_IdleSettings(&pIdleSettings); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; str.Format(L"PT%uS", m_wIdleMinutes*60); hr = pIdleSettings->put_IdleDuration(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; str.Format(L"PT%uS", m_wDeadlineMinutes*60); hr = pIdleSettings->put_WaitTimeout(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pIdleSettings->put_RestartOnIdle(m_dwFlags & TASK_FLAG_RESTART_ON_IDLE_RESUME ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pIdleSettings->put_StopOnIdleEnd(m_dwFlags & TASK_FLAG_KILL_ON_IDLE_END ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Configure task runtime limit. str.Format(L"PT%uS", m_dwMaxRuntimeMS != INFINITE ? (m_dwMaxRuntimeMS + 500) / 1000 : 0); hr = pTaskSettings->put_ExecutionTimeLimit(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Get task trigger colection. hr = pTaskDefinition->get_Triggers(&pTriggerCollection); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Add triggers. for (pos = m_lTriggers.GetHeadPosition(), iTrigger = 0; pos; iTrigger++) { @@ -346,82 +343,82 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) switch (ttData.TriggerType) { case TASK_TIME_TRIGGER_ONCE: { CComPtr pTriggerTime; - hr = pTriggerCollection->Create(TASK_TRIGGER_TIME, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerTime); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_TIME, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerTime); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerTime->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerTime->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_TIME_TRIGGER_DAILY: { CComPtr pTriggerDaily; - hr = pTriggerCollection->Create(TASK_TRIGGER_DAILY, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerDaily); if (FAILED(hr)) return hr; - hr = pTriggerDaily->put_DaysInterval(ttData.Type.Daily.DaysInterval); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_DAILY, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerDaily); if (FAILED(hr)) goto finish; + hr = pTriggerDaily->put_DaysInterval(ttData.Type.Daily.DaysInterval); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerDaily->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerDaily->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_TIME_TRIGGER_WEEKLY: { CComPtr pTriggerWeekly; - hr = pTriggerCollection->Create(TASK_TRIGGER_WEEKLY, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerWeekly); if (FAILED(hr)) return hr; - hr = pTriggerWeekly->put_WeeksInterval(ttData.Type.Weekly.WeeksInterval); if (FAILED(hr)) return hr; - hr = pTriggerWeekly->put_DaysOfWeek(ttData.Type.Weekly.rgfDaysOfTheWeek); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_WEEKLY, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerWeekly); if (FAILED(hr)) goto finish; + hr = pTriggerWeekly->put_WeeksInterval(ttData.Type.Weekly.WeeksInterval); if (FAILED(hr)) goto finish; + hr = pTriggerWeekly->put_DaysOfWeek(ttData.Type.Weekly.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerWeekly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerWeekly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_TIME_TRIGGER_MONTHLYDATE: { CComPtr pTriggerMonthly; - hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLY, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerMonthly); if (FAILED(hr)) return hr; - hr = pTriggerMonthly->put_DaysOfMonth(ttData.Type.MonthlyDate.rgfDays); if (FAILED(hr)) return hr; - hr = pTriggerMonthly->put_MonthsOfYear(ttData.Type.MonthlyDate.rgfMonths); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLY, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerMonthly); if (FAILED(hr)) goto finish; + hr = pTriggerMonthly->put_DaysOfMonth(ttData.Type.MonthlyDate.rgfDays); if (FAILED(hr)) goto finish; + hr = pTriggerMonthly->put_MonthsOfYear(ttData.Type.MonthlyDate.rgfMonths); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerMonthly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerMonthly->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_TIME_TRIGGER_MONTHLYDOW: { CComPtr pTriggerMonthlyDOW; - hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLYDOW, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerMonthlyDOW); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_MONTHLYDOW, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerMonthlyDOW); if (FAILED(hr)) goto finish; hr = pTriggerMonthlyDOW->put_WeeksOfMonth( ttData.Type.MonthlyDOW.wWhichWeek == TASK_FIRST_WEEK ? 0x01 : ttData.Type.MonthlyDOW.wWhichWeek == TASK_SECOND_WEEK ? 0x02 : ttData.Type.MonthlyDOW.wWhichWeek == TASK_THIRD_WEEK ? 0x04 : ttData.Type.MonthlyDOW.wWhichWeek == TASK_FOURTH_WEEK ? 0x08 : - ttData.Type.MonthlyDOW.wWhichWeek == TASK_LAST_WEEK ? 0x10 : 0x00); if (FAILED(hr)) return hr; - hr = pTriggerMonthlyDOW->put_DaysOfWeek(ttData.Type.MonthlyDOW.rgfDaysOfTheWeek); if (FAILED(hr)) return hr; - hr = pTriggerMonthlyDOW->put_MonthsOfYear(ttData.Type.MonthlyDOW.rgfMonths); if (FAILED(hr)) return hr; + ttData.Type.MonthlyDOW.wWhichWeek == TASK_LAST_WEEK ? 0x10 : 0x00); if (FAILED(hr)) goto finish; + hr = pTriggerMonthlyDOW->put_DaysOfWeek(ttData.Type.MonthlyDOW.rgfDaysOfTheWeek); if (FAILED(hr)) goto finish; + hr = pTriggerMonthlyDOW->put_MonthsOfYear(ttData.Type.MonthlyDOW.rgfMonths); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerMonthlyDOW->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerMonthlyDOW->put_RandomDelay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_EVENT_TRIGGER_ON_IDLE: { - hr = pTriggerCollection->Create(TASK_TRIGGER_IDLE, &pTrigger); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_IDLE, &pTrigger); if (FAILED(hr)) goto finish; break; } case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: { CComPtr pTriggerBoot; - hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerBoot); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerBoot); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerBoot->put_Delay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerBoot->put_Delay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } case TASK_EVENT_TRIGGER_AT_LOGON: { CComPtr pTriggerLogon; - hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); if (FAILED(hr)) return hr; - hr = pTrigger.QueryInterface(&pTriggerLogon); if (FAILED(hr)) return hr; + hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); if (FAILED(hr)) goto finish; + hr = pTrigger.QueryInterface(&pTriggerLogon); if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.wRandomMinutesInterval); - hr = pTriggerLogon->put_Delay(CComBSTR(str)); if (FAILED(hr)) return hr; + hr = pTriggerLogon->put_Delay(CComBSTR(str)); if (FAILED(hr)) goto finish; break; } } @@ -429,18 +426,18 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) // Set trigger ID. str.Format(L"%u", iTrigger); hr = pTrigger->put_Id(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Set trigger start date. str.Format(L"%04u-%02u-%02uT%02u:%02u:00", ttData.wBeginYear, ttData.wBeginMonth, ttData.wBeginDay, ttData.wStartHour, ttData.wStartMinute); hr = pTrigger->put_StartBoundary(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; if (ttData.rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) { // Set trigger end date. str.Format(L"%04u-%02u-%02u", ttData.wEndYear, ttData.wEndMonth, ttData.wEndDay); hr = pTrigger->put_EndBoundary(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } // Set trigger repetition duration and interval. @@ -448,26 +445,25 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) CComPtr pRepetitionPattern; hr = pTrigger->get_Repetition(&pRepetitionPattern); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.MinutesDuration); hr = pRepetitionPattern->put_Duration(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; str.Format(L"PT%uM", ttData.MinutesInterval); hr = pRepetitionPattern->put_Interval(CComBSTR(str)); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pRepetitionPattern->put_StopAtDurationEnd(ttData.rgFlags & TASK_TRIGGER_FLAG_KILL_AT_DURATION_END ? VARIANT_TRUE : VARIANT_FALSE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } // Enable/disable trigger. hr = pTrigger->put_Enabled(ttData.rgFlags & TASK_TRIGGER_FLAG_DISABLED ? VARIANT_FALSE : VARIANT_TRUE); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } // Get the task folder. - CComPtr pTaskFolder; hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; #ifdef _DEBUG CComBSTR xml; @@ -484,40 +480,44 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) logonType, // logonType vEmpty, // sddl &pTask); // ppTask - if (FAILED(hr)) return hr; } else { // Windows XP or older. + CComPtr pTaskScheduler; CComPtr pTask; + // Get task scheduler object. + hr = pTaskScheduler.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_ALL); + if (FAILED(hr)) goto finish; + // Create the new task. - hr = pSession->m_pTaskScheduler->NewWorkItem(m_sValue, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); + hr = pTaskScheduler->NewWorkItem(m_sValue, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); if (pSession->m_bRollbackEnabled) { // Order rollback action to delete the task. ITask::NewWorkItem() might made a blank task already. - pSession->m_olRollback.AddHead(new CMSITSCAOpDeleteTask(m_sValue)); + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskDelete(m_sValue)); } - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; // Set its properties. - hr = pTask->SetApplicationName (m_sApplicationName ); if (FAILED(hr)) return hr; - hr = pTask->SetParameters (m_sParameters ); if (FAILED(hr)) return hr; - hr = pTask->SetWorkingDirectory(m_sWorkingDirectory); if (FAILED(hr)) return hr; - hr = pTask->SetComment (m_sComment ); if (FAILED(hr)) return hr; + hr = pTask->SetApplicationName (m_sApplicationName ); if (FAILED(hr)) goto finish; + hr = pTask->SetParameters (m_sParameters ); if (FAILED(hr)) goto finish; + hr = pTask->SetWorkingDirectory(m_sWorkingDirectory); if (FAILED(hr)) goto finish; + hr = pTask->SetComment (m_sComment ); if (FAILED(hr)) goto finish; if (pSession->m_bRollbackEnabled && (m_dwFlags & TASK_FLAG_DISABLED) == 0) { // The task is supposed to be enabled. // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. - pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE)); + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); m_dwFlags |= TASK_FLAG_DISABLED; } - hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) return hr; - hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) return hr; + hr = pTask->SetFlags (m_dwFlags ); if (FAILED(hr)) goto finish; + hr = pTask->SetPriority (m_dwPriority ); if (FAILED(hr)) goto finish; if (!m_sAccountName.IsEmpty()) { hr = pTask->SetAccountInformation(m_sAccountName, m_sPassword.IsEmpty() ? NULL : m_sPassword); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } - hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) return hr; - hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) return hr; + hr = pTask->SetIdleWait (m_wIdleMinutes, m_wDeadlineMinutes); if (FAILED(hr)) goto finish; + hr = pTask->SetMaxRunTime(m_dwMaxRuntimeMS ); if (FAILED(hr)) goto finish; // Add triggers. for (pos = m_lTriggers.GetHeadPosition(); pos;) { @@ -526,25 +526,31 @@ HRESULT CMSITSCAOpCreateTask::Execute(CMSITSCASession *pSession) TASK_TRIGGER &ttData = m_lTriggers.GetNext(pos); hr = pTask->CreateTrigger(&wTriggerIdx, &pTrigger); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; hr = pTrigger->SetTrigger(&ttData); - if (FAILED(hr)) return hr; + if (FAILED(hr)) goto finish; } // Save the task. CComQIPtr pTaskFile(pTask); - if (!pTaskFile) return E_NOINTERFACE; - + if (!pTaskFile) { hr = E_NOINTERFACE; goto finish; } hr = pTaskFile->Save(NULL, TRUE); - if (FAILED(hr)) return hr; } - return S_OK; +finish: + if (FAILED(hr)) { + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_CREATE_FAILED) == ERROR_SUCCESS); + verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue ) == ERROR_SUCCESS); + verify(::MsiRecordSetInteger(hRecordProg, 3, hr ) == ERROR_SUCCESS); + ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + return hr; } -UINT CMSITSCAOpCreateTask::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord) +UINT CMSITSCAOpTaskCreate::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord) { UINT uiResult; int iValue; @@ -562,7 +568,10 @@ UINT CMSITSCAOpCreateTask::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord) m_sWorkingDirectory.Truncate(m_sWorkingDirectory.GetLength() - 1); } - uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sComment); + uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 10, m_sAuthor); + if (uiResult != ERROR_SUCCESS) return uiResult; + + uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 11, m_sComment); if (uiResult != ERROR_SUCCESS) return uiResult; m_dwFlags = ::MsiRecordGetInteger(hRecord, 6); @@ -577,20 +586,20 @@ UINT CMSITSCAOpCreateTask::SetFromRecord(MSIHANDLE hInstall, MSIHANDLE hRecord) uiResult = ::MsiRecordFormatStringW(hInstall, hRecord, 9, m_sPassword); if (uiResult != ERROR_SUCCESS) return uiResult; - iValue = ::MsiRecordGetInteger(hRecord, 11); + iValue = ::MsiRecordGetInteger(hRecord, 12); m_wIdleMinutes = iValue != MSI_NULL_INTEGER ? (WORD)iValue : 0; - iValue = ::MsiRecordGetInteger(hRecord, 12); + iValue = ::MsiRecordGetInteger(hRecord, 13); m_wDeadlineMinutes = iValue != MSI_NULL_INTEGER ? (WORD)iValue : 0; - m_dwMaxRuntimeMS = ::MsiRecordGetInteger(hRecord, 13); + m_dwMaxRuntimeMS = ::MsiRecordGetInteger(hRecord, 14); if (m_dwMaxRuntimeMS == MSI_NULL_INTEGER) return ERROR_INVALID_FIELD; - return S_OK; + return ERROR_SUCCESS; } -UINT CMSITSCAOpCreateTask::SetTriggersFromView(MSIHANDLE hView) +UINT CMSITSCAOpTaskCreate::SetTriggersFromView(MSIHANDLE hView) { for (;;) { UINT uiResult; @@ -716,180 +725,424 @@ UINT CMSITSCAOpCreateTask::SetTriggersFromView(MSIHANDLE hView) m_lTriggers.AddTail(ttData); } - return S_OK; + return ERROR_SUCCESS; } //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpDeleteTask +// CMSITSCAOpTaskDelete //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpDeleteTask::CMSITSCAOpDeleteTask(LPCWSTR pszTaskName, int iTicks) : - CMSITSCAOpSingleStringOperation(pszTaskName, iTicks) +CMSITSCAOpTaskDelete::CMSITSCAOpTaskDelete(LPCWSTR pszTaskName, int iTicks) : + CMSITSCAOpTypeSingleString(pszTaskName, iTicks) { } -HRESULT CMSITSCAOpDeleteTask::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpTaskDelete::Execute(CMSITSCASession *pSession) { assert(pSession); HRESULT hr; + CComPtr pService; - if (pSession->m_bRollbackEnabled) { - CComPtr pTask; - DWORD dwFlags; - CString sDisplayNameOrig; - UINT uiCount = 0; - - // Load the task. - hr = pSession->m_pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) return S_OK; - else if (FAILED(hr)) return hr; - - // Disable the task. - hr = pTask->GetFlags(&dwFlags); - if (FAILED(hr)) return hr; - if ((dwFlags & TASK_FLAG_DISABLED) == 0) { - // The task is enabled. - - // In case the task disabling fails halfway, try to re-enable it anyway on rollback. - pSession->m_olRollback.AddHead(new CMSITSCAOpEnableTask(m_sValue, TRUE)); - - // Disable it. - dwFlags |= TASK_FLAG_DISABLED; - hr = pTask->SetFlags(dwFlags); - if (FAILED(hr)) return hr; - } - - // Prepare a backup copy of task. - do { - sDisplayNameOrig.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); - hr = pSession->m_pTaskScheduler->AddWorkItem(sDisplayNameOrig, pTask); - } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); - // In case the backup copy creation failed halfway, try to delete its remains anyway on rollback. - pSession->m_olRollback.AddHead(new CMSITSCAOpDeleteTask(sDisplayNameOrig)); - if (FAILED(hr)) return hr; - - // Save the backup copy. - CComQIPtr pTaskFile(pTask); - if (!pTaskFile) return E_NOINTERFACE; - - hr = pTaskFile->Save(NULL, TRUE); - if (FAILED(hr)) return hr; - - // Order rollback action to restore from backup copy. - pSession->m_olRollback.AddHead(new CMSITSCAOpCopyTask(sDisplayNameOrig, m_sValue)); - - // Delete it. - hr = pSession->m_pTaskScheduler->Delete(m_sValue); - if (FAILED(hr)) return hr; - - // Order commit action to delete backup copy. - pSession->m_olCommit.AddTail(new CMSITSCAOpDeleteTask(sDisplayNameOrig)); - - return S_OK; - } else { - // Delete the task. - hr = pSession->m_pTaskScheduler->Delete(m_sValue); - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) return S_OK; - else return hr; - } -} - - -//////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpEnableTask -//////////////////////////////////////////////////////////////////////////// - -CMSITSCAOpEnableTask::CMSITSCAOpEnableTask(LPCWSTR pszTaskName, BOOL bEnable, int iTicks) : - m_bEnable(bEnable), - CMSITSCAOpSingleStringOperation(pszTaskName, iTicks) -{ -} - - -HRESULT CMSITSCAOpEnableTask::Execute(CMSITSCASession *pSession) -{ - assert(pSession); - HRESULT hr; - CComPtr pTask; - - // Load the task. - hr = pSession->m_pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); + hr = pService.CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER); if (SUCCEEDED(hr)) { - DWORD dwFlags; + // Windows Vista or newer. + CComVariant vEmpty; + CComPtr pTaskFolder; - // Get task's current flags. - hr = pTask->GetFlags(&dwFlags); - if (SUCCEEDED(hr)) { - // Modify flags. - if (m_bEnable) { - if (pSession->m_bRollbackEnabled && (dwFlags & TASK_FLAG_DISABLED)) { - // The task is disabled and supposed to be enabled. - // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. - pSession->m_olCommit.AddTail(new CMSITSCAOpEnableTask(m_sValue, TRUE)); - return S_OK; - } else - dwFlags &= ~TASK_FLAG_DISABLED; - } else { - if (pSession->m_bRollbackEnabled && !(dwFlags & TASK_FLAG_DISABLED)) { - // The task is enabled and we will disable it now. - // Order rollback to re-enable it. - pSession->m_olRollback.AddHead(new CMSITSCAOpEnableTask(m_sValue, TRUE)); - } - dwFlags |= TASK_FLAG_DISABLED; + // Connect to local task service. + hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); + if (FAILED(hr)) goto finish; + + // Get task folder. + hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); + if (FAILED(hr)) goto finish; + + if (pSession->m_bRollbackEnabled) { + CComPtr pTask, pTaskOrig; + CComPtr pTaskDefinition; + CComPtr pPrincipal; + VARIANT_BOOL bEnabled; + TASK_LOGON_TYPE logonType; + CComBSTR sSSDL; + CComVariant vSSDL; + CString sDisplayNameOrig; + UINT uiCount = 0; + + // Get the source task. + hr = pTaskFolder->GetTask(CComBSTR(m_sValue), &pTask); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; } + else if (FAILED(hr)) goto finish; + + // Disable the task. + hr = pTask->get_Enabled(&bEnabled); + if (FAILED(hr)) goto finish; + if (bEnabled) { + // The task is enabled. + + // In case the task disabling fails halfway, try to re-enable it anyway on rollback. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + + // Disable it. + hr = pTask->put_Enabled(VARIANT_FALSE); + if (FAILED(hr)) goto finish; } - // Set flags. - hr = pTask->SetFlags(dwFlags); - if (SUCCEEDED(hr)) { - // Save the task. - CComQIPtr pTaskFile(pTask); - hr = pTaskFile ? pTaskFile->Save(NULL, TRUE) : E_NOINTERFACE; + // Get task's definition. + hr = pTask->get_Definition(&pTaskDefinition); + if (FAILED(hr)) goto finish; + + // Get task principal. + hr = pTaskDefinition->get_Principal(&pPrincipal); + if (FAILED(hr)) goto finish; + + // Get task logon type. + hr = pPrincipal->get_LogonType(&logonType); + if (FAILED(hr)) goto finish; + + // Get task security descriptor. + hr = pTask->GetSecurityDescriptor(DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, &sSSDL); + if (hr == HRESULT_FROM_WIN32(ERROR_PRIVILEGE_NOT_HELD)) vSSDL.Clear(); + else if (FAILED(hr)) goto finish; + else { + V_VT (&vSSDL) = VT_BSTR; + V_BSTR(&vSSDL) = sSSDL.Detach(); } + + // Register a backup copy of task. + do { + sDisplayNameOrig.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); + hr = pTaskFolder->RegisterTaskDefinition( + CComBSTR(sDisplayNameOrig), // path + pTaskDefinition, // pDefinition + TASK_CREATE, // flags + vEmpty, // userId + vEmpty, // password + logonType, // logonType + vSSDL, // sddl + &pTaskOrig); // ppTask + } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); + // In case the backup copy creation failed halfway, try to delete its remains anyway on rollback. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskDelete(sDisplayNameOrig)); + if (FAILED(hr)) goto finish; + + // Order rollback action to restore from backup copy. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskCopy(sDisplayNameOrig, m_sValue)); + + // Delete it. + hr = pTaskFolder->DeleteTask(CComBSTR(m_sValue), 0); + if (FAILED(hr)) goto finish; + + // Order commit action to delete backup copy. + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskDelete(sDisplayNameOrig)); + } else { + // Delete the task. + hr = pTaskFolder->DeleteTask(CComBSTR(m_sValue), 0); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK; + } + } else { + // Windows XP or older. + CComPtr pTaskScheduler; + + // Get task scheduler object. + hr = pTaskScheduler.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_ALL); + if (FAILED(hr)) goto finish; + + if (pSession->m_bRollbackEnabled) { + CComPtr pTask; + DWORD dwFlags; + CString sDisplayNameOrig; + UINT uiCount = 0; + + // Load the task. + hr = pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; goto finish; } + else if (FAILED(hr)) goto finish; + + // Disable the task. + hr = pTask->GetFlags(&dwFlags); + if (FAILED(hr)) goto finish; + if ((dwFlags & TASK_FLAG_DISABLED) == 0) { + // The task is enabled. + + // In case the task disabling fails halfway, try to re-enable it anyway on rollback. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + + // Disable it. + dwFlags |= TASK_FLAG_DISABLED; + hr = pTask->SetFlags(dwFlags); + if (FAILED(hr)) goto finish; + } + + // Prepare a backup copy of task. + do { + sDisplayNameOrig.Format(L"%ls (orig %u)", (LPCWSTR)m_sValue, ++uiCount); + hr = pTaskScheduler->AddWorkItem(sDisplayNameOrig, pTask); + } while (hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); + // In case the backup copy creation failed halfway, try to delete its remains anyway on rollback. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskDelete(sDisplayNameOrig)); + if (FAILED(hr)) goto finish; + + // Save the backup copy. + CComQIPtr pTaskFile(pTask); + if (!pTaskFile) { hr = E_NOINTERFACE; goto finish; } + hr = pTaskFile->Save(NULL, TRUE); + if (FAILED(hr)) goto finish; + + // Order rollback action to restore from backup copy. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskCopy(sDisplayNameOrig, m_sValue)); + + // Delete it. + hr = pTaskScheduler->Delete(m_sValue); + if (FAILED(hr)) goto finish; + + // Order commit action to delete backup copy. + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskDelete(sDisplayNameOrig)); + } else { + // Delete the task. + hr = pTaskScheduler->Delete(m_sValue); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hr = S_OK; } } +finish: + if (FAILED(hr)) { + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_DELETE_FAILED) == ERROR_SUCCESS); + verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue ) == ERROR_SUCCESS); + verify(::MsiRecordSetInteger(hRecordProg, 3, hr ) == ERROR_SUCCESS); + ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } return hr; } //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpCopyTask +// CMSITSCAOpTaskEnable //////////////////////////////////////////////////////////////////////////// -CMSITSCAOpCopyTask::CMSITSCAOpCopyTask(LPCWSTR pszTaskSrc, LPCWSTR pszTaskDst, int iTicks) : - CMSITSCAOpSrcDstStringOperation(pszTaskSrc, pszTaskDst, iTicks) +CMSITSCAOpTaskEnable::CMSITSCAOpTaskEnable(LPCWSTR pszTaskName, BOOL bEnable, int iTicks) : + m_bEnable(bEnable), + CMSITSCAOpTypeSingleString(pszTaskName, iTicks) { } -HRESULT CMSITSCAOpCopyTask::Execute(CMSITSCASession *pSession) +HRESULT CMSITSCAOpTaskEnable::Execute(CMSITSCASession *pSession) { assert(pSession); HRESULT hr; - CComPtr pTask; + CComPtr pService; - // Load the source task. - hr = pSession->m_pTaskScheduler->Activate(m_sValue1, IID_ITask, (IUnknown**)&pTask); - if (FAILED(hr)) return hr; + hr = pService.CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER); + if (SUCCEEDED(hr)) { + // Windows Vista or newer. + CComVariant vEmpty; + CComPtr pTaskFolder; + CComPtr pTask; + VARIANT_BOOL bEnabled; - // Add with different name. - hr = pSession->m_pTaskScheduler->AddWorkItem(m_sValue2, pTask); - if (pSession->m_bRollbackEnabled) { - // Order rollback action to delete the new copy. ITask::AddWorkItem() might made a blank task already. - pSession->m_olRollback.AddHead(new CMSITSCAOpDeleteTask(m_sValue2)); + // Connect to local task service. + hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); + if (FAILED(hr)) goto finish; + + // Get task folder. + hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); + if (FAILED(hr)) goto finish; + + // Get task. + hr = pTaskFolder->GetTask(CComBSTR(m_sValue), &pTask); + if (FAILED(hr)) goto finish; + + // Get currently enabled state. + hr = pTask->get_Enabled(&bEnabled); + if (FAILED(hr)) goto finish; + + // Modify enable state. + if (m_bEnable) { + if (pSession->m_bRollbackEnabled && !bEnabled) { + // The task is disabled and supposed to be enabled. + // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + hr = S_OK; goto finish; + } else + bEnabled = VARIANT_TRUE; + } else { + if (pSession->m_bRollbackEnabled && bEnabled) { + // The task is enabled and we will disable it now. + // Order rollback to re-enable it. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + } + bEnabled = VARIANT_FALSE; + } + + // Set enable/disable. + hr = pTask->put_Enabled(bEnabled); + if (FAILED(hr)) goto finish; + } else { + // Windows XP or older. + CComPtr pTaskScheduler; + CComPtr pTask; + DWORD dwFlags; + + // Get task scheduler object. + hr = pTaskScheduler.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_ALL); + if (FAILED(hr)) goto finish; + + // Load the task. + hr = pTaskScheduler->Activate(m_sValue, IID_ITask, (IUnknown**)&pTask); + if (FAILED(hr)) goto finish; + + // Get task's current flags. + hr = pTask->GetFlags(&dwFlags); + if (FAILED(hr)) goto finish; + + // Modify flags. + if (m_bEnable) { + if (pSession->m_bRollbackEnabled && (dwFlags & TASK_FLAG_DISABLED)) { + // The task is disabled and supposed to be enabled. + // However, we shall enable it at commit to prevent it from accidentally starting in the very installation phase. + pSession->m_olCommit.AddTail(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + hr = S_OK; goto finish; + } else + dwFlags &= ~TASK_FLAG_DISABLED; + } else { + if (pSession->m_bRollbackEnabled && !(dwFlags & TASK_FLAG_DISABLED)) { + // The task is enabled and we will disable it now. + // Order rollback to re-enable it. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskEnable(m_sValue, TRUE)); + } + dwFlags |= TASK_FLAG_DISABLED; + } + + // Set flags. + hr = pTask->SetFlags(dwFlags); + if (FAILED(hr)) goto finish; + + // Save the task. + CComQIPtr pTaskFile(pTask); + if (!pTaskFile) { hr = E_NOINTERFACE; goto finish; } + hr = pTaskFile->Save(NULL, TRUE); + if (FAILED(hr)) goto finish; } - if (FAILED(hr)) return hr; - // Save the task. - CComQIPtr pTaskFile(pTask); - if (!pTaskFile) return E_NOINTERFACE; +finish: + if (FAILED(hr)) { + PMSIHANDLE hRecordProg = ::MsiCreateRecord(3); + verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_ENABLE_FAILED) == ERROR_SUCCESS); + verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue ) == ERROR_SUCCESS); + verify(::MsiRecordSetInteger(hRecordProg, 3, hr ) == ERROR_SUCCESS); + ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + return hr; +} - hr = pTaskFile->Save(NULL, TRUE); - if (FAILED(hr)) return hr; - return S_OK; +//////////////////////////////////////////////////////////////////////////// +// CMSITSCAOpTaskCopy +//////////////////////////////////////////////////////////////////////////// + +CMSITSCAOpTaskCopy::CMSITSCAOpTaskCopy(LPCWSTR pszTaskSrc, LPCWSTR pszTaskDst, int iTicks) : + CMSITSCAOpTypeSrcDstString(pszTaskSrc, pszTaskDst, iTicks) +{ +} + + +HRESULT CMSITSCAOpTaskCopy::Execute(CMSITSCASession *pSession) +{ + assert(pSession); + HRESULT hr; + CComPtr pService; + + hr = pService.CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER); + if (SUCCEEDED(hr)) { + // Windows Vista or newer. + CComVariant vEmpty; + CComPtr pTaskFolder; + CComPtr pTask, pTaskOrig; + CComPtr pTaskDefinition; + CComPtr pPrincipal; + TASK_LOGON_TYPE logonType; + CComBSTR sSSDL; + + // Connect to local task service. + hr = pService->Connect(vEmpty, vEmpty, vEmpty, vEmpty); + if (FAILED(hr)) goto finish; + + // Get task folder. + hr = pService->GetFolder(CComBSTR(L"\\"), &pTaskFolder); + if (FAILED(hr)) goto finish; + + // Get the source task. + hr = pTaskFolder->GetTask(CComBSTR(m_sValue1), &pTask); + if (FAILED(hr)) goto finish; + + // Get task's definition. + hr = pTask->get_Definition(&pTaskDefinition); + if (FAILED(hr)) goto finish; + + // Get task principal. + hr = pTaskDefinition->get_Principal(&pPrincipal); + if (FAILED(hr)) goto finish; + + // Get task logon type. + hr = pPrincipal->get_LogonType(&logonType); + if (FAILED(hr)) goto finish; + + // Get task security descriptor. + hr = pTask->GetSecurityDescriptor(DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, &sSSDL); + if (FAILED(hr)) goto finish; + + // Register a new task. + hr = pTaskFolder->RegisterTaskDefinition( + CComBSTR(m_sValue2), // path + pTaskDefinition, // pDefinition + TASK_CREATE, // flags + vEmpty, // userId + vEmpty, // password + logonType, // logonType + CComVariant(sSSDL), // sddl + &pTaskOrig); // ppTask + if (FAILED(hr)) goto finish; + } else { + // Windows XP or older. + CComPtr pTaskScheduler; + CComPtr pTask; + + // Get task scheduler object. + hr = pTaskScheduler.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_ALL); + if (FAILED(hr)) goto finish; + + // Load the source task. + hr = pTaskScheduler->Activate(m_sValue1, IID_ITask, (IUnknown**)&pTask); + if (FAILED(hr)) goto finish; + + // Add with different name. + hr = pTaskScheduler->AddWorkItem(m_sValue2, pTask); + if (pSession->m_bRollbackEnabled) { + // Order rollback action to delete the new copy. ITask::AddWorkItem() might made a blank task already. + pSession->m_olRollback.AddHead(new CMSITSCAOpTaskDelete(m_sValue2)); + } + if (FAILED(hr)) goto finish; + + // Save the task. + CComQIPtr pTaskFile(pTask); + if (!pTaskFile) { hr = E_NOINTERFACE; goto finish; } + hr = pTaskFile->Save(NULL, TRUE); + if (FAILED(hr)) goto finish; + } + +finish: + if (FAILED(hr)) { + PMSIHANDLE hRecordProg = ::MsiCreateRecord(4); + verify(::MsiRecordSetInteger(hRecordProg, 1, ERROR_INSTALL_TASK_COPY_FAILED) == ERROR_SUCCESS); + verify(::MsiRecordSetStringW(hRecordProg, 2, m_sValue1 ) == ERROR_SUCCESS); + verify(::MsiRecordSetStringW(hRecordProg, 3, m_sValue2 ) == ERROR_SUCCESS); + verify(::MsiRecordSetInteger(hRecordProg, 4, hr ) == ERROR_SUCCESS); + ::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_ERROR, hRecordProg); + } + return hr; } @@ -977,7 +1230,11 @@ HRESULT CMSITSCAOpList::Execute(CMSITSCASession *pSession) assert(pOp); hr = pOp->Execute(pSession); - if (!pSession->m_bContinueOnError && FAILED(hr)) return hr; + if (!pSession->m_bContinueOnError && FAILED(hr)) { + // Operation failed. Its Execute() method should have sent error message to Installer. + // Therefore, just quit here. + return hr; + } verify(::MsiRecordSetInteger(hRecordProg, 2, pOp->m_iTicks) == ERROR_SUCCESS); if (::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) diff --git a/MSICALib/MSITSCAOp.h b/MSICALib/MSITSCAOp.h index 1af2376..c444400 100644 --- a/MSICALib/MSITSCAOp.h +++ b/MSICALib/MSITSCAOp.h @@ -34,16 +34,16 @@ protected: //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpSingleStringOperation +// CMSITSCAOpTypeSingleString //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpSingleStringOperation : public CMSITSCAOp +class CMSITSCAOpTypeSingleString : public CMSITSCAOp { public: - CMSITSCAOpSingleStringOperation(LPCWSTR pszValue = L"", int iTicks = 0); + CMSITSCAOpTypeSingleString(LPCWSTR pszValue = L"", int iTicks = 0); - friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSingleStringOperation &op); - friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSingleStringOperation &op); + friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeSingleString &op); + friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeSingleString &op); protected: CStringW m_sValue; @@ -54,13 +54,13 @@ protected: // CMSITSCAOpDoubleStringOperation //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpSrcDstStringOperation : public CMSITSCAOp +class CMSITSCAOpTypeSrcDstString : public CMSITSCAOp { public: - CMSITSCAOpSrcDstStringOperation(LPCWSTR pszValue1 = L"", LPCWSTR pszValue2 = L"", int iTicks = 0); + CMSITSCAOpTypeSrcDstString(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); + friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeSrcDstString &op); + friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeSrcDstString &op); protected: CStringW m_sValue1; @@ -69,16 +69,16 @@ protected: //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpBooleanOperation +// CMSITSCAOpTypeBoolean //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpBooleanOperation : public CMSITSCAOp +class CMSITSCAOpTypeBoolean : public CMSITSCAOp { public: - CMSITSCAOpBooleanOperation(BOOL bValue = TRUE, int iTicks = 0); + CMSITSCAOpTypeBoolean(BOOL bValue = TRUE, int iTicks = 0); - friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpBooleanOperation &op); - friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpBooleanOperation &op); + friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeBoolean &op); + friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeBoolean &op); protected: BOOL m_bValue; @@ -86,62 +86,63 @@ protected: //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpEnableRollback +// CMSITSCAOpRollbackEnable //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpEnableRollback : public CMSITSCAOpBooleanOperation +class CMSITSCAOpRollbackEnable : public CMSITSCAOpTypeBoolean { public: - CMSITSCAOpEnableRollback(BOOL bEnable = TRUE, int iTicks = 0); + CMSITSCAOpRollbackEnable(BOOL bEnable = TRUE, int iTicks = 0); virtual HRESULT Execute(CMSITSCASession *pSession); }; //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpDeleteFile +// CMSITSCAOpFileDelete //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpDeleteFile : public CMSITSCAOpSingleStringOperation +class CMSITSCAOpFileDelete : public CMSITSCAOpTypeSingleString { public: - CMSITSCAOpDeleteFile(LPCWSTR pszFileName = L"", int iTicks = 0); + CMSITSCAOpFileDelete(LPCWSTR pszFileName = L"", int iTicks = 0); virtual HRESULT Execute(CMSITSCASession *pSession); }; //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpMoveFile +// CMSITSCAOpFileMove //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpMoveFile : public CMSITSCAOpSrcDstStringOperation +class CMSITSCAOpFileMove : public CMSITSCAOpTypeSrcDstString { public: - CMSITSCAOpMoveFile(LPCWSTR pszFileSrc = L"", LPCWSTR pszFileDst = L"", int iTicks = 0); + CMSITSCAOpFileMove(LPCWSTR pszFileSrc = L"", LPCWSTR pszFileDst = L"", int iTicks = 0); virtual HRESULT Execute(CMSITSCASession *pSession); }; //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpCreateTask +// CMSITSCAOpTaskCreate //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpCreateTask : public CMSITSCAOpSingleStringOperation +class CMSITSCAOpTaskCreate : public CMSITSCAOpTypeSingleString { public: - CMSITSCAOpCreateTask(LPCWSTR pszTaskName = L"", int iTicks = 0); - virtual ~CMSITSCAOpCreateTask(); + CMSITSCAOpTaskCreate(LPCWSTR pszTaskName = L"", int iTicks = 0); + virtual ~CMSITSCAOpTaskCreate(); 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); + friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTaskCreate &op); + friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTaskCreate &op); protected: CStringW m_sApplicationName; CStringW m_sParameters; CStringW m_sWorkingDirectory; + CStringW m_sAuthor; CStringW m_sComment; DWORD m_dwFlags; DWORD m_dwPriority; @@ -156,29 +157,29 @@ protected: //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpDeleteTask +// CMSITSCAOpTaskDelete //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpDeleteTask : public CMSITSCAOpSingleStringOperation +class CMSITSCAOpTaskDelete : public CMSITSCAOpTypeSingleString { public: - CMSITSCAOpDeleteTask(LPCWSTR pszTaskName = L"", int iTicks = 0); + CMSITSCAOpTaskDelete(LPCWSTR pszTaskName = L"", int iTicks = 0); virtual HRESULT Execute(CMSITSCASession *pSession); }; //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpEnableTask +// CMSITSCAOpTaskEnable //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpEnableTask : public CMSITSCAOpSingleStringOperation +class CMSITSCAOpTaskEnable : public CMSITSCAOpTypeSingleString { public: - CMSITSCAOpEnableTask(LPCWSTR pszTaskName = L"", BOOL bEnable = TRUE, int iTicks = 0); + CMSITSCAOpTaskEnable(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); + friend inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTaskEnable &op); + friend inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTaskEnable &op); protected: BOOL m_bEnable; @@ -186,13 +187,13 @@ protected: //////////////////////////////////////////////////////////////////////////// -// CMSITSCAOpCopyTask +// CMSITSCAOpTaskCopy //////////////////////////////////////////////////////////////////////////// -class CMSITSCAOpCopyTask : public CMSITSCAOpSrcDstStringOperation +class CMSITSCAOpTaskCopy : public CMSITSCAOpTypeSrcDstString { public: - CMSITSCAOpCopyTask(LPCWSTR pszTaskSrc = L"", LPCWSTR pszTaskDst = L"", int iTicks = 0); + CMSITSCAOpTaskCopy(LPCWSTR pszTaskSrc = L"", LPCWSTR pszTaskDst = L"", int iTicks = 0); virtual HRESULT Execute(CMSITSCASession *pSession); }; @@ -242,12 +243,11 @@ 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 + MSIHANDLE m_hInstall; // Installer handle + 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 }; @@ -267,7 +267,7 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOp &op) } -inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSingleStringOperation &op) +inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeSingleString &op) { HRESULT hr; @@ -278,7 +278,7 @@ inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSingleStringOperation &o } -inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSingleStringOperation &op) +inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeSingleString &op) { HRESULT hr; @@ -289,7 +289,7 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSingleStringOperation &op) } -inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSrcDstStringOperation &op) +inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeSrcDstString &op) { HRESULT hr; @@ -303,7 +303,7 @@ inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpSrcDstStringOperation &o } -inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSrcDstStringOperation &op) +inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeSrcDstString &op) { HRESULT hr; @@ -317,7 +317,7 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpSrcDstStringOperation &op) } -inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpBooleanOperation &op) +inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTypeBoolean &op) { HRESULT hr; @@ -328,7 +328,7 @@ inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpBooleanOperation &op) } -inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpBooleanOperation &op) +inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTypeBoolean &op) { int iValue; HRESULT hr; @@ -344,15 +344,16 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpBooleanOperation &op) } -inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpCreateTask &op) +inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTaskCreate &op) { HRESULT hr; POSITION pos; - hr = f << (const CMSITSCAOpSingleStringOperation&)op; if (FAILED(hr)) return hr; + hr = f << (const CMSITSCAOpTypeSingleString&)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; @@ -370,15 +371,16 @@ inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpCreateTask &op) } -inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpCreateTask &op) +inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTaskCreate &op) { HRESULT hr; DWORD dwValue; - hr = f >> (CMSITSCAOpSingleStringOperation&)op; if (FAILED(hr)) return hr; + hr = f >> (CMSITSCAOpTypeSingleString&)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; @@ -398,23 +400,23 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpCreateTask &op) } -inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpEnableTask &op) +inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpTaskEnable &op) { HRESULT hr; - hr = f << (const CMSITSCAOpSingleStringOperation&)op; + hr = f << (const CMSITSCAOpTypeSingleString&)op; if (FAILED(hr)) return hr; return f << (int)op.m_bEnable; } -inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpEnableTask &op) +inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpTaskEnable &op) { HRESULT hr; int iTemp; - hr = f >> (CMSITSCAOpSingleStringOperation&)op; + hr = f >> (CMSITSCAOpTypeSingleString&)op; if (FAILED(hr)) return hr; hr = f >> iTemp; @@ -438,20 +440,20 @@ inline HRESULT operator <<(CAtlFile &f, const CMSITSCAOpList &list) 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); + 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 { @@ -486,25 +488,25 @@ inline HRESULT operator >>(CAtlFile &f, CMSITSCAOpList &list) switch ((CMSITSCAOpList::OPERATION)iTemp) { case CMSITSCAOpList::OPERATION_ENABLE_ROLLBACK: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_DELETE_FILE: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_MOVE_FILE: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_CREATE_TASK: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_DELETE_TASK: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_ENABLE_TASK: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_COPY_TASK: - hr = list.LoadAndAddTail(f); + hr = list.LoadAndAddTail(f); break; case CMSITSCAOpList::OPERATION_SUBLIST: hr = list.LoadAndAddTail(f); diff --git a/MSICALib/Naredi.txt b/MSICALib/Naredi.txt deleted file mode 100644 index eeba3e9..0000000 --- a/MSICALib/Naredi.txt +++ /dev/null @@ -1,3 +0,0 @@ -- Naredi še o(ne)mogočanje opravil z uporabo Task Scheduler 2.0. -- Preizkusi vse nastavitve opravila in vrste sprožilcev, če se pravilno izdelajo. -- Tudi akcije deferred/commit/rollback naj pošiljajo obvestila o napakah. diff --git a/MSICALib/StdAfx.h b/MSICALib/StdAfx.h index 5552537..a6de284 100644 --- a/MSICALib/StdAfx.h +++ b/MSICALib/StdAfx.h @@ -20,7 +20,8 @@ #define _WIN32_WINNT 0x0501 // Include Windows XP symbols #define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h #ifdef _WINDLL -#define MSITSCA_DLL // Gradimo knjižnico DLL +#define MSITSCA_DLL // This is a DLL +//#ifdef ASSERT_TO_DEBUG // Enable false asserts to provide opportunity to attach debuger #endif #define _ATL_APARTMENT_THREADED #define _ATL_NO_AUTOMATIC_NAMESPACE diff --git a/MSICALib/res/en_GB.po b/MSICALib/res/en_GB.po index 6291f6e..5a6eb0e 100644 --- a/MSICALib/res/en_GB.po +++ b/MSICALib/res/en_GB.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: MSITSCA\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-24 14:20+0100\n" +"POT-Creation-Date: 2013-01-09 12:10+0100\n" "PO-Revision-Date: \n" "Last-Translator: Simon Rozman \n" "Language-Team: Amebis, d. o. o., Kamnik \n" @@ -36,6 +36,10 @@ msgstr "0x409" #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:3 #: ..\MSI/Sl.DebugU.x64.ActionText-2.idtx:3 #: ..\MSI/Sl.DebugU.x64.Error-2.idtx:3 +#: ..\MSI/Sl.ReleaseU.Win32.ActionText-2.idtx:3 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:3 +#: ..\MSI/Sl.ReleaseU.x64.ActionText-2.idtx:3 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:3 msgid "1250" msgstr "1252" @@ -72,44 +76,116 @@ msgstr "Copyright © Amebis, d. o. o., Kamnik, 2012" # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:8 ..\MSI/Sl.DebugU.x64.Error-2.idtx:8 -msgid "Pri brisanju datoteke »[2]« je prišlo do napake [3]." -msgstr "Error [3] deleting \"[2]\" file." +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:8 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:8 +msgid "" +"Pri brisanju datoteke »[2]« je prišlo do napake [3]. Obrnite se na svojo " +"tehniÄŤno sluĹľbo." +msgstr "Error [3] deleting \"[2]\" file. Contact your support personnel." + +# !!! Lektorirati !!! +#: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:11 ..\MSI/Sl.DebugU.x64.Error-2.idtx:11 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:11 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:11 +msgid "" +"Pri brisanju razporejenega opravila »[2]« je prišlo do napake [3]. Obrnite " +"se na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [3] deleting \"[2]\" scheduled task. Contact your support personnel." + +# !!! Lektorirati !!! +#: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:13 ..\MSI/Sl.DebugU.x64.Error-2.idtx:13 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:13 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:13 +msgid "" +"Pri kopiranju razporejenega opravila »[2]« v »[3]« je prišlo do napake [4]. " +"Obrnite se na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [4] copying \"[2]\" scheduled task to \"[3]\". Contact your support " +"personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:7 ..\MSI/Sl.DebugU.x64.Error-2.idtx:7 -msgid "Pri nastavljanju parametra »[2]« je prišlo do napake [3]." -msgstr "Error [3] setting \"[2]\" parameter." +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:7 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:7 +msgid "" +"Pri nastavljanju parametra »[2]« je prišlo do napake [3]. Obrnite se na " +"svojo tehniÄŤno sluĹľbo." +msgstr "Error [3] setting \"[2]\" parameter. Contact your support personnel." + +# !!! Lektorirati !!! +#: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:12 ..\MSI/Sl.DebugU.x64.Error-2.idtx:12 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:12 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:12 +msgid "" +"Pri o(ne)mogoÄŤanju razporejenega opravila »[2]« je prišlo do napake [3]. " +"Obrnite se na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [3] enabling/disabling \"[2]\" scheduled task. Contact your support " +"personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:4 ..\MSI/Sl.DebugU.x64.Error-2.idtx:4 -msgid "Pri odpiranju namestitvenega paketa je prišlo do napake." -msgstr "Error opening installation package." +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:4 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:4 +msgid "" +"Pri odpiranju namestitvenega paketa je prišlo do napake. Obrnite se na svojo " +"tehniÄŤno sluĹľbo." +msgstr "Error opening installation package. Contact your support personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:6 ..\MSI/Sl.DebugU.x64.Error-2.idtx:6 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:6 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:6 msgid "" "Pri pisanju v datoteko seznama razporejenih opravil »[2]« je prišlo do " -"napake [3]." -msgstr "Error [3] writing to \"[2]\" scheduled task list file." +"napake [3]. Obrnite se na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [3] writing to \"[2]\" scheduled task list file. Contact your support " +"personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:9 ..\MSI/Sl.DebugU.x64.Error-2.idtx:9 -msgid "Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]." -msgstr "Error [4] moving \"[2]\" file to \"[3]\"." +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:9 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:9 +msgid "" +"Pri premikanju datoteke »[2]« v »[3]« je prišlo do napake [4]. Obrnite se na " +"svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [4] moving \"[2]\" file to \"[3]\". Contact your support personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:5 ..\MSI/Sl.DebugU.x64.Error-2.idtx:5 -msgid "Pri pripravi seznama razvrščenih opravil je prišlo do napake [2]." -msgstr "Error [2] creating scheduled task list." +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:5 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:5 +msgid "" +"Pri pripravi seznama razvrščenih opravil je prišlo do napake [2]. Obrnite se " +"na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [2] creating scheduled task list. Contact your support personnel." + +# !!! Lektorirati !!! +#: ..\MSI/Sl.DebugU.Win32.Error-2.idtx:10 ..\MSI/Sl.DebugU.x64.Error-2.idtx:10 +#: ..\MSI/Sl.ReleaseU.Win32.Error-2.idtx:10 +#: ..\MSI/Sl.ReleaseU.x64.Error-2.idtx:10 +msgid "" +"Pri ustvarjanju razporejenega opravila »[2]« je prišlo do napake [3]. " +"Obrnite se na svojo tehniÄŤno sluĹľbo." +msgstr "" +"Error [3] creating \"[2]\" scheduled task. Contact your support personnel." # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.ActionText-2.idtx:4 #: ..\MSI/Sl.DebugU.x64.ActionText-2.idtx:4 +#: ..\MSI/Sl.ReleaseU.Win32.ActionText-2.idtx:4 +#: ..\MSI/Sl.ReleaseU.x64.ActionText-2.idtx:4 msgid "Razporejeno opravilo: [1]" msgstr "Scheduled task: [1]" # !!! Lektorirati !!! #: ..\MSI/Sl.DebugU.Win32.ActionText-2.idtx:4 #: ..\MSI/Sl.DebugU.x64.ActionText-2.idtx:4 +#: ..\MSI/Sl.ReleaseU.Win32.ActionText-2.idtx:4 +#: ..\MSI/Sl.ReleaseU.x64.ActionText-2.idtx:4 msgid "Registracija razporejenih opravil" msgstr "Registering scheduled tasks"