--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/taskscheduler/SCHSVR/SCHEXEC.CPP Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,237 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+// system includes
+#include <schtask.h>
+
+// User includes
+#include "SCHEXEC.H"
+#include "SchLogger.h"
+#include "SCHLOG.h"
+#include "taskfile.h"
+
+//Delay ensuring this thread is be preempted allowing client cleanup
+//in case task file cannot be deleted
+const TInt KClientCleanupDelay = 10000;
+
+CTaskExecutor::CTaskExecutor(CSchLogManager& aSchLogManager)
+: CActive(EPriorityStandard),
+ iSchLogManager(aSchLogManager)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+CTaskExecutor::~CTaskExecutor()
+ {
+ LOGSTRING("CTaskExecutor::~CTaskExecutor - start");
+ iProcess.Close();
+
+ //
+ delete iClientFileName;
+ delete iTaskFileName;
+ delete iLogErrorMessage;
+ LOGSTRING("CTaskExecutor::~CTaskExecutor - end");
+ }
+
+
+void CTaskExecutor::ConstructL(const TDesC& aTaskFileName,
+ const TDesC& aClientFileName,
+ const TDesC& aErrorMessage)
+ {
+ LOGSTRING("CTaskExecutor::ConstructL - start");
+ // Store filename
+ iTaskFileName = aTaskFileName.AllocL();
+ iClientFileName = aClientFileName.AllocL();
+
+ // In case there is an error...
+ iLogErrorMessage = aErrorMessage.AllocL();
+
+ LOGSTRING("CTaskExecutor::ConstructL - end");
+ }
+
+
+CTaskExecutor* CTaskExecutor::NewLC(const TDesC& aErrorMessage,
+ const TDesC& aTaskFileName,
+ const TDesC& aClientFileName,
+ CSchLogManager& aSchLogManager)
+ {
+ LOGSTRING("CTaskExecutor::NewLC");
+ CTaskExecutor* self = new(ELeave) CTaskExecutor(aSchLogManager);
+ CleanupStack::PushL(self);
+ self->ConstructL(aTaskFileName, aClientFileName, aErrorMessage);
+ return self;
+ }
+
+void CTaskExecutor::RunL()
+ {
+ LOGSTRING3("CTaskExecutor::RunL - task finished running [client: %S, task: %S]", iClientFileName, iTaskFileName);
+ //
+ // RunL is called when the process/thread terminates
+ // so that any error conditions can be handled.
+ TInt exitReason = iProcess.ExitReason();
+ LOGSTRING2("CTaskExecutor::RunL - process exit reason was: %d", exitReason);
+
+ // Close the process/thread
+ iProcess.Close();
+
+ // Check for error code
+ if (exitReason != KErrNone)
+ {
+ // Submit a log entry to record the error.
+ LOGSTRING2("CTaskExecutor::RunL - recording unclean process exit (%d) in the log engine", exitReason);
+ if(iLogErrorMessage)
+ iSchLogManager.LogError(*iLogErrorMessage,exitReason);
+ else
+ iSchLogManager.LogError(exitReason);
+ }
+
+ // Clean up the file. Only delete it here once task process has finished.
+ // If task process never started then file is deleted in CClientProxy code.
+ User::LeaveIfError(iFsSession.Connect());
+ CleanupClosePushL(iFsSession);
+
+ TInt fileDeleteErr = iFsSession.Delete(*iTaskFileName);
+
+ // If unable to delete file wait and try again
+ if (fileDeleteErr != KErrNone)
+ {
+
+ //Allow thread to be preempted to allow for cleanup of iProcess
+ User::After(KClientCleanupDelay);
+
+ fileDeleteErr = iFsSession.Delete(*iTaskFileName);
+
+ // If still unable to delete file record the fact
+ if (fileDeleteErr != KErrNone)
+ {
+ if(iLogErrorMessage)
+ {
+ iSchLogManager.LogError(*iLogErrorMessage, fileDeleteErr);
+ }
+ else
+ {
+ iSchLogManager.LogError(fileDeleteErr);
+ }
+ }
+ }
+
+ //Calls iFsSession::Close() so no need to call explicitly
+ CleanupStack::PopAndDestroy();
+
+ // Delete outselves since we've finished
+ LOGSTRING("CTaskExecutor::RunL - deleting ourself");
+ delete this;
+ }
+
+void CTaskExecutor::DoCancel()
+ {
+ LOGSTRING("CTaskExecutor::DoCancel - start");
+ iProcess.LogonCancel(iStatus);
+ // Delete file and ourselves since we can't do anything else.
+ // We are in a bad state if we reach here but at least make the most of it.
+ LOGSTRING("CTaskExecutor::DoCancel - deleting ourself");
+
+ //Connect to file session
+ TInt err = iFsSession.Connect();
+
+ if(err == KErrNone)
+ {
+ err = iFsSession.Delete(*iTaskFileName);
+ }
+
+ // If unable to delete file record the fact
+ if (err != KErrNone)
+ {
+ if(iLogErrorMessage)
+ {
+ iSchLogManager.LogError(*iLogErrorMessage, err);
+ }
+ else
+ {
+ iSchLogManager.LogError(err);
+ }
+ }
+
+ //Close the file session
+ iFsSession.Close();
+
+ delete this;
+ LOGSTRING("CTaskExecutor::DoCancel - end");
+ }
+
+void CTaskExecutor::ExecuteL()
+ {
+ // If this leaves, CClientProxy should handle error....
+ // CTaskScheduler::ExecuteClients() traps the leave and then calls
+ // CClientProxy::FailToExecute() to handle the error.
+#ifdef __SCHLOGGING__
+ {
+ TTime time; time.HomeTime();
+ TDateTime due = time.DateTime();
+ LOGSTRING8("CTaskExecutor::ExecuteL - Executing tasks at: [%02d/%02d/%d] @ %02d:%02d:%02d.%05d", due.Day(), (TInt) due.Month() + 1, due.Year(), due.Hour(), due.Minute(), due.Second(), due.MicroSecond());
+ }
+#endif
+
+ // Create a new process and pass the name of the task file as the command line argument
+ // (data for the target exe).
+ LOGSTRING("CTaskExecutor::ExecuteL - creating process");
+ TInt err = iProcess.Create(*iClientFileName, KNullDesC);
+
+ // Will check the error, report the problem and leave (if err<KErrNone)
+ // otherwise does nothing.
+ LOGSTRING("CTaskExecutor::ExecuteL - checking process creation error code");
+ CheckErrorAndLeaveL(err);
+
+ // connect to new file session to avoid possible security
+ // consequences if lauched process tries to use passed file in
+ // subversive way.
+ User::LeaveIfError(iFsSession.Connect());
+ CleanupClosePushL(iFsSession);
+ User::LeaveIfError(iFsSession.ShareProtected());
+
+ User::LeaveIfError(iTaskFile.Open(iFsSession, *iTaskFileName, EFileRead));
+ CleanupClosePushL(iTaskFile);
+
+ // transfer file handle to launched process
+ err = iTaskFile.TransferToProcess(iProcess, KTaskFsHandleIndex, KTaskFileHandleIndex);
+
+ //Close task file and session handles
+ //Calls iFsSession::Close() and iTaskFile::Close() so no need to call explicitly
+ CleanupStack::PopAndDestroy(2);
+
+ CheckErrorAndLeaveL(err);
+
+ // Asynchronous logon: completes when process terminates with process exit code
+ iProcess.Logon(iStatus);
+ iProcess.Resume();
+
+ SetActive();
+ LOGSTRING("CTaskExecutor::ExecuteL - end");
+
+ }
+
+void CTaskExecutor::CheckErrorAndLeaveL(TInt aError)
+ {
+ if (aError < KErrNone)
+ {
+ if(iLogErrorMessage)
+ iSchLogManager.LogError(*iLogErrorMessage,aError);
+ else
+ iSchLogManager.LogError(aError);
+ User::Leave(aError);
+ }
+ }
+