messagingfw/scheduledsendmtm/schedulesendexe/src/SchSendExe.cpp
changeset 62 db3f5fa34ec7
parent 0 8e480a14352b
equal deleted inserted replaced
60:9f5ae1728557 62:db3f5fa34ec7
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #ifdef _DEBUG
       
    18 #undef _MSG_NO_LOGGING
       
    19 #endif
       
    20 
       
    21 
       
    22 #include <csch_cli.h>
       
    23 #include <msvapi.h>
       
    24 #include <msvschedulepackage.h>
       
    25 #include "SchSendExe.h"
       
    26 #include <msvschedulesend.h>
       
    27 #include <msvschedulesettings.h>
       
    28 #include <msvids.h>
       
    29 #include <msvuids.h>
       
    30 #include <tmsvschedulesettingsutils.h>
       
    31 #include <centralrepository.h>
       
    32 
       
    33 
       
    34 #ifndef _MSG_NO_LOGGING
       
    35 	#include <flogger.h>
       
    36 	_LIT(KSchSendExeLogFile, "SchSendExe.txt");
       
    37 	const TFileLoggingMode KSchSendExeLoggingMode = EFileLoggingModeAppend;
       
    38 #endif
       
    39 
       
    40 
       
    41 _LIT_SECURE_ID(KSchSendExeSid, 0x100056A1);
       
    42 _LIT_SECURE_ID(KTaskSchedulerSid, 0x10005399);
       
    43 
       
    44 _LIT(KSchSendThreadName, "SchSend");
       
    45 
       
    46 #include <u32std.h>
       
    47 #include <miutset.h>
       
    48 
       
    49 
       
    50 GLDEF_C TInt E32Main()
       
    51 	{
       
    52 	if(User::CreatorSecureId() != KTaskSchedulerSid)
       
    53 		{
       
    54 		// Not launched by Task Scheduler - exit
       
    55 		return KErrPermissionDenied;
       
    56 		}
       
    57 
       
    58 	TBuf<0x100> fileName;
       
    59 	RFile taskFile;
       
    60  	// Adopt the task file using the RFs handle into environment  slot 
       
    61  	// 1 and the RFile handle into slot 2
       
    62  	TInt err = taskFile.AdoptFromCreator(1,2);
       
    63  	if(KErrNone !=err)
       
    64  		{
       
    65  		return err;
       
    66  		}
       
    67  	taskFile.Name(fileName);
       
    68  	return Execute(fileName, taskFile);
       
    69  	
       
    70 	}
       
    71 
       
    72 
       
    73 
       
    74 TInt Execute(const TDesC& aFileName, RFile& aFile )
       
    75 	{
       
    76 	__UHEAP_MARK;
       
    77 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
    78 	SCHSENDLOG(CMsvSendExe::FLog(aFileName, _L("Processing file %S"), &aFileName));
       
    79 
       
    80 	TRAPD(leaveValue, DoExecuteL(aFileName, aFile ));
       
    81 
       
    82 	if (leaveValue != KErrNone)
       
    83 		{
       
    84 		// DoExecuteL will only leave in the unlikely event that available memory is too low
       
    85 		// to create an instance of the active scheduler or the CMsvSendExe object or in the
       
    86 		// event that we cannot rename the thread. Once the CMsvSendObject has been created
       
    87 		// leaves are handled cleanly by the object. We could retry the call to DoExecuteL,
       
    88 		// but it's unlikely to succeed a second time around.
       
    89 		}
       
    90 
       
    91 	SCHSENDLOG(CMsvSendExe::FLog(aFileName, _L("DoExecuteL completed with error %d"), leaveValue));
       
    92 
       
    93 	delete cleanup;
       
    94 	__UHEAP_MARKEND;
       
    95 	
       
    96 	return leaveValue;
       
    97 
       
    98 	}
       
    99 
       
   100 void DoExecuteL(const TDesC& aFileName, RFile& aFile )
       
   101 	{
       
   102 	CleanupClosePushL(aFile);
       
   103 
       
   104 	User::LeaveIfError(User::RenameThread(KSchSendThreadName));
       
   105 
       
   106 	CActiveScheduler* activeSch = new (ELeave) CActiveScheduler();
       
   107 	CleanupStack::PushL(activeSch);
       
   108 
       
   109 	CActiveScheduler::Install(activeSch);
       
   110 
       
   111 	CMsvSendExe::StartLC(aFileName, aFile );
       
   112 
       
   113 	CleanupStack::PopAndDestroy(3, &aFile);
       
   114 	}
       
   115 
       
   116 //
       
   117 // CMsvSendExe Implementation
       
   118 //
       
   119 
       
   120 /**
       
   121 
       
   122 The CMsvSendExe Constructor
       
   123 
       
   124 @return			
       
   125 @internalAll
       
   126 @param				 aFile
       
   127 */
       
   128 CMsvSendExe::CMsvSendExe(const TDesC& aFileName, RFile& aFile )
       
   129 	: CActive(KDefaultPriority), iFileName(aFileName), iTaskFile(aFile )
       
   130 	{
       
   131 	//Add this to the Active Scheduler.
       
   132 	//This is a requirement if a class is derived from CActive
       
   133 	CActiveScheduler::Add(this);
       
   134 	iCreated.UniversalTime();
       
   135 	}
       
   136 
       
   137 CMsvSendExe::~CMsvSendExe()
       
   138 /*
       
   139 	CMsvSendExe Destructor
       
   140 */
       
   141 	{
       
   142 	Cancel();
       
   143 	delete iSession;
       
   144 
       
   145 	iOperations.ResetAndDestroy();
       
   146 	iPackages.Reset();
       
   147 	}
       
   148 
       
   149 
       
   150 /**
       
   151 
       
   152 The CMsvSendExe::StartLC method
       
   153 1. Constructs CMsvSendExe
       
   154 2. Processes the task scheduler file
       
   155 3. Attempts to send the messages
       
   156 
       
   157 @return			
       
   158 @internalAll
       
   159 @param				 aFile File containing the task information
       
   160 */
       
   161 CMsvSendExe* CMsvSendExe::StartLC(const TDesC& aFileName, RFile& aFile )
       
   162 	{
       
   163 	CMsvSendExe* self = new (ELeave) CMsvSendExe(aFileName,aFile );
       
   164 
       
   165 	CleanupStack::PushL(self);
       
   166 
       
   167 	self->ConstructL();
       
   168 	return self;
       
   169 	}
       
   170 
       
   171 void CMsvSendExe::ConstructL()
       
   172 	{
       
   173 	TRAPD(err, ProcessFileL());
       
   174 	
       
   175 	if(err == KErrPermissionDenied)
       
   176 		{
       
   177 		//security violation
       
   178 		User::Leave(err);
       
   179 		}
       
   180 
       
   181 	if (err != KErrNone)
       
   182 		RescheduleAllL(err);
       
   183 
       
   184 	}
       
   185 
       
   186 void CMsvSendExe::ProcessFileL()
       
   187 /*
       
   188 	ProcessFileL
       
   189 */
       
   190 	{
       
   191 	RetrievePackagesL();
       
   192 	RetrieveMessagesL();
       
   193 
       
   194 	if (iOperations.Count())
       
   195 		{
       
   196 		CallMtmL();
       
   197 		iActiveSchedulerWait.Start();
       
   198 		}
       
   199 	else
       
   200 		{
       
   201 		SCHSENDLOG(FLog(iFileName, _L("\tNO msg to send!")));
       
   202 		}
       
   203 	}
       
   204 
       
   205 
       
   206 void CMsvSendExe::RetrievePackagesL()
       
   207 	{
       
   208 	
       
   209 	//open the filestore 	
       
   210 	CFileStore* store = CDirectFileStore::FromLC(iTaskFile);//pushes store
       
   211 
       
   212 	RStoreReadStream instream;
       
   213 	instream.OpenLC(*store,store->Root());//pushes instream
       
   214 
       
   215 	//get task count
       
   216 	TInt taskCount = instream.ReadInt32L();
       
   217 
       
   218 	SCHSENDLOG(FLog(iFileName, _L("\tTask Count=%d"), taskCount));
       
   219 
       
   220 	for (TInt curTask = 0; curTask < taskCount; curTask++)
       
   221 		{
       
   222 		CScheduledTask* task = CScheduledTask::NewLC(instream);
       
   223 
       
   224 		AddPackageL(*task);
       
   225 
       
   226 		CleanupStack::PopAndDestroy(task);
       
   227 		}
       
   228 
       
   229 	CleanupStack::PopAndDestroy(2, store);
       
   230 	}
       
   231 
       
   232 #ifndef _MSG_NO_LOGGING
       
   233 void CMsvSendExe::FLog(const TDesC& aFileName, TRefByValue<const TDesC16> aFmt, ...)
       
   234 	{
       
   235 	VA_LIST list;
       
   236 	VA_START(list, aFmt);
       
   237 
       
   238 	TParse parse;
       
   239 	parse.Set(aFileName, NULL, NULL);
       
   240 
       
   241 	TBuf<256> buf;
       
   242 	buf.Append(parse.Name());
       
   243 	buf.Append(_L(": "));
       
   244 	buf.AppendFormatList(aFmt, list);
       
   245 
       
   246 	RFileLogger::Write(KSchSendLogDir, KSchSendExeLogFile, KSchSendExeLoggingMode,
       
   247 				buf);
       
   248 	}
       
   249 #endif
       
   250 
       
   251 
       
   252 /**
       
   253 
       
   254 The CMsvSendExe::CallMtmL method
       
   255 Attempts to send the messages in the operation selection
       
   256 
       
   257 @internalAll
       
   258 */
       
   259 void CMsvSendExe::CallMtmL()
       
   260 	{
       
   261 	__ASSERT_DEBUG(iOperations.Count(), gPanic(ENoMessagesInSelection));
       
   262 
       
   263 	TInt count = iOperations.Count();
       
   264 
       
   265 	while (count--)
       
   266 		{
       
   267 		CMsvSendExeActive& active = *iOperations[count];
       
   268 		SCHSENDLOG(FLog(iFileName, _L("\tStarting operation for %d msgs (Mtm=%d CommandId=%d)"), active.MsgCount(), active.Mtm().iUid, active.Package().iCommandId));
       
   269 		active.StartL();
       
   270 		SCHSENDLOG(FLog(iFileName, _L("\tStarted (Mtm=%d CommandId=%d)"), active.Mtm().iUid, active.Package().iCommandId));
       
   271 		}
       
   272 
       
   273 	iStatus = KRequestPending;
       
   274 	SetActive();
       
   275 	}
       
   276 
       
   277 
       
   278 /**
       
   279 
       
   280 The CMsvSendExe::DoCancel method
       
   281 Cancels all outstanding operations and stops the active scheduler.
       
   282 
       
   283 @return			
       
   284 @internalAll
       
   285 */
       
   286 void CMsvSendExe::DoCancel()
       
   287 	{
       
   288 	SCHSENDLOG(FLog(iFileName, _L("\tOperations cancelled"), iStatus.Int()));
       
   289 
       
   290 	TInt count = iOperations.Count();
       
   291 	while (count--)
       
   292 		iOperations[count]->Cancel();
       
   293 
       
   294 	iActiveSchedulerWait.AsyncStop();
       
   295 	}
       
   296 
       
   297 
       
   298 /**
       
   299 
       
   300 The CMsvSendExe::RunL method
       
   301 Called when all operations in iOperations have completed.
       
   302 Stops the active scheduler.
       
   303 
       
   304 @return			
       
   305 @internalAll
       
   306 */
       
   307 void CMsvSendExe::RunL()
       
   308 	{
       
   309 	SCHSENDLOG(FLog(iFileName, _L("All operations completed")));
       
   310 	iActiveSchedulerWait.AsyncStop();
       
   311 	}
       
   312 
       
   313 void CMsvSendExe::AddPackageL(const CScheduledTask& aTask)
       
   314 	{
       
   315 	TMsvSchedulePackage pkg;
       
   316 	TSecurityInfo securityInfo = aTask.SecurityInfo();
       
   317 	
       
   318 	if( (securityInfo.iSecureId.iId != KSchSendExeSid) && (securityInfo.iSecureId.iId != KMsvServerId) )
       
   319 		{
       
   320 		if( PlatSec::ConfigSetting(PlatSec::EPlatSecDiagnotics) )
       
   321 			{
       
   322              _LIT(KMessage,"CMsvSendExe::AddPackageL ERROR %d");
       
   323              RDebug::Print(KMessage,  KErrPermissionDenied);
       
   324 			}
       
   325 		if( PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement) )
       
   326 			{
       
   327 			//security violation
       
   328 			User::Leave(KErrPermissionDenied);
       
   329 			}
       
   330 		}
       
   331 
       
   332 	
       
   333 	pkg.UnpackL(aTask.Info(), aTask.Data());
       
   334 	User::LeaveIfError(iPackages.Append(pkg));
       
   335 	}
       
   336 
       
   337 /**
       
   338 
       
   339 The CMsvSendExe::RetrieveMessagesL method
       
   340 Retrieves the message selection from the task file.
       
   341 
       
   342 @internalAll
       
   343 */
       
   344 void CMsvSendExe::RetrieveMessagesL()
       
   345 	{
       
   346 	iSession = CMsvSession::OpenSyncL(*this);
       
   347 	TInt count = iPackages.Count();
       
   348 
       
   349 	while(count--)
       
   350 		{
       
   351 
       
   352 		AddTaskL(iPackages[count]);
       
   353 
       
   354 		iPackages.Remove(count);
       
   355 		}
       
   356 	}
       
   357 
       
   358 
       
   359 void CMsvSendExe::AddTaskL(const TMsvSchedulePackage& aPackage)
       
   360 	{
       
   361 	CMsvEntry* cEntry = NULL;
       
   362 	TRAPD(err, cEntry = iSession->GetEntryL(aPackage.iId));
       
   363 
       
   364 	if (err != KErrNotFound)
       
   365 		{
       
   366 		User::LeaveIfError(err);
       
   367 		CleanupStack::PushL(cEntry);
       
   368 
       
   369 		TMsvEntry entry = cEntry->Entry();
       
   370 		const TInt sendState = entry.SendingState();
       
   371 
       
   372 		//Only send the message if sending state is Scheduled or Resend.
       
   373 		if (entry.Scheduled() && (sendState == KMsvSendStateScheduled || sendState == KMsvSendStateResend))
       
   374 			{
       
   375 			entry.SetSendingState(KMsvSendStateWaiting);
       
   376 
       
   377 			// Fix for DEF000924: Need to be able to send/cancel an sms while another is being sent
       
   378 			if (entry.iServiceId == KMsvLocalServiceIndexEntryId && entry.iRelatedId != KMsvNullIndexEntryId)
       
   379 				{
       
   380 				SCHSENDLOG(  FLog(iFileName, _L("Changing service from %x to %x"), entry.iServiceId, entry.iRelatedId));
       
   381 				entry.iServiceId = entry.iRelatedId;
       
   382 				}
       
   383 			else
       
   384 				{
       
   385 				SCHSENDLOG(  FLog(iFileName, _L("Not changing service from %x (related=%x)"), entry.iServiceId, entry.iRelatedId));
       
   386 				}
       
   387 			// End of fix
       
   388 
       
   389  			cEntry->ChangeL(entry);
       
   390 			AddTaskL(aPackage, entry.iMtm);
       
   391 			SCHSENDLOG(FLog(iFileName, _L("\t\tMsg=%d [Mtm=%d SendState=%d]"), aPackage.iId, entry.iMtm.iUid, entry.SendingState()));
       
   392 			}
       
   393 		else
       
   394 			{
       
   395 			SCHSENDLOG(FLog(iFileName, _L("\t\tIGNORING Msg=%d (Mtm=%d SendState=%d Scheduled=%d)"), aPackage.iId, entry.iMtm.iUid, sendState, entry.Scheduled()));
       
   396 			}
       
   397 
       
   398 		CleanupStack::PopAndDestroy(cEntry);
       
   399 		}
       
   400 	else
       
   401 		{
       
   402 		SCHSENDLOG(FLog(iFileName, _L("\t\tIGNORING Msg=%d: NOT FOUND"), aPackage.iId));
       
   403 		}
       
   404 	}
       
   405 
       
   406 /**
       
   407 
       
   408 The CMsvSendExe::AddTaskL method
       
   409 Finds a CMsvSendExeActive in iOperations that corresponds to aPackage and aMtm.
       
   410 If not found, then creates a new CMsvSendExeActive, and appends it to iOperations.
       
   411 Then the message in aPackage is appended to the CMsvSendExeActive.
       
   412 
       
   413 @internalAll
       
   414 @param				aPackage	Information about what operation to start
       
   415 @param				aMtm		The MTM of the message identified in aPackage
       
   416 */
       
   417 void CMsvSendExe::AddTaskL(const TMsvSchedulePackage& aPackage, const TUid& aMtm)
       
   418 	{
       
   419 	//Add the task to an object in iOperations
       
   420 
       
   421 	CMsvSendExeActive* active = NULL;
       
   422 	TInt count = iOperations.Count();
       
   423 
       
   424 	while (active == NULL && count--)
       
   425 		{
       
   426 		CMsvSendExeActive* tempActive = iOperations[count];
       
   427 
       
   428 		if (tempActive->Mtm() == aMtm &&
       
   429 			tempActive->Package().iCommandId == aPackage.iCommandId &&
       
   430 			tempActive->Package().iParameter == aPackage.iParameter &&
       
   431 			tempActive->Package().iPollProgress == aPackage.iPollProgress)
       
   432 			active = tempActive;
       
   433 		}
       
   434 
       
   435 	if (active == NULL)
       
   436 		{
       
   437 		active = CMsvSendExeActive::NewLC(*iSession, *this, aPackage, aMtm, Priority());
       
   438 		User::LeaveIfError(iOperations.Append(active));
       
   439 		CleanupStack::Pop(active);
       
   440 		}
       
   441 
       
   442 	active->AppendL(aPackage.iId);
       
   443 	}
       
   444 
       
   445 
       
   446 /**
       
   447 
       
   448 The CMsvSendExe::OperationComplete method
       
   449 Called by a CMsvSendExeActive when it completes
       
   450 If all operations in iOperations are complete, then CMsvSendExe completes itself
       
   451 
       
   452 @return			
       
   453 @internalAll
       
   454 @param				 aActive The operation that has just completed
       
   455 @param				 aError  
       
   456 */
       
   457 void CMsvSendExe::OperationComplete(const CMsvSendExeActive& aActive, TInt aError)
       
   458 	{
       
   459 	SCHSENDLOG(FLog(iFileName, _L("\tOperation Complete (Mtm=%d CommandId=%d Err=%d)"), aActive.Mtm().iUid, aActive.Package().iCommandId, aError));
       
   460 
       
   461 	if (aError != KErrNone)
       
   462 		RescheduleOnError(aActive, aError);
       
   463 
       
   464 #ifdef _DEBUG
       
   465 	iOperationsComplete++;
       
   466 #endif
       
   467 
       
   468 	__ASSERT_DEBUG(!aActive.IsActive(), gPanic(EOperationCompletedTooSoon));
       
   469 
       
   470 	TInt count = iOperations.Count();
       
   471 
       
   472 	while (count--)
       
   473 		{
       
   474 		if (iOperations[count]->IsActive())
       
   475 			{
       
   476 			__ASSERT_DEBUG(iOperationsComplete < iOperations.Count(), gPanic(ETooManyOperationsCompleted));
       
   477 			return;
       
   478 			}
       
   479 		}
       
   480 
       
   481 	TRequestStatus* status = &iStatus;
       
   482 	User::RequestComplete(status, KErrNone);
       
   483 	}
       
   484 
       
   485 _LIT(KSchSendExePanic, "SchSendExe");
       
   486 
       
   487 GLDEF_C void gPanic(TSchSendExePanic aPanic)
       
   488 	{
       
   489 	User::Panic(KSchSendExePanic,aPanic);
       
   490 	}
       
   491 
       
   492 GLDEF_C void gPanic(TInt aPanic)
       
   493 	{
       
   494 	User::Panic(KSchSendExePanic,aPanic);
       
   495 	}
       
   496 
       
   497 
       
   498 void CMsvSendExe::RescheduleOnError(const CMsvSendExeActive& aActive, TInt aError)
       
   499 	{
       
   500 	SCHSENDLOG(FLog(iFileName, _L("\tRescheduleOnError (Mtm=%d CommandId=%d InCount=%d)"), aActive.Mtm().iUid, aActive.Package().iCommandId, aActive.Selection().Count()));
       
   501 	RescheduleOnError(aActive.Selection(), aActive.Package(), aError);
       
   502 	}
       
   503 
       
   504 void CMsvSendExe::RescheduleAllL(TInt aError)
       
   505 	{
       
   506 	SCHSENDLOG(FLog(iFileName, _L("\tRescheduleAllL [aError=%d]"), aError));
       
   507 	RScheduler scheduler;
       
   508 	TSchedulerItemRef ref;
       
   509 	ref.iHandle = KErrNotFound;
       
   510 	TInt count = 0;
       
   511 	TInt err = KErrNone;
       
   512 	TTime start;
       
   513 	start.UniversalTime();
       
   514 
       
   515 	TInt activeCount = iOperations.Count();
       
   516 	while (activeCount--)
       
   517 		{
       
   518 		CMsvSendExeActive& active = *iOperations[activeCount];
       
   519 		active.Cancel();
       
   520 		TRAP(err, DoResheduleOnErrorL(scheduler, active.Selection(), active.Package(), aError, ref, count, start)); //ignore error
       
   521 		FailOnError(active.Selection(), aError);
       
   522 		}
       
   523 
       
   524 	activeCount = iPackages.Count();
       
   525 	CMsvEntrySelection* sel = new (ELeave) CMsvEntrySelection;
       
   526 	CleanupStack::PushL(sel);
       
   527 	while (activeCount--)
       
   528 		{
       
   529 		const TMsvSchedulePackage& package = iPackages[activeCount];
       
   530 		sel->Reset();
       
   531 		sel->AppendL(package.iId);
       
   532 		TRAP(err, DoResheduleOnErrorL(scheduler, *sel, package, aError, ref, count, start)); //ignore error
       
   533 		FailOnError(*sel, aError);
       
   534 		}
       
   535 	CleanupStack::PopAndDestroy(sel);
       
   536 
       
   537 	CompleteReschedule(scheduler, ref, count);
       
   538 	}
       
   539 
       
   540 void CMsvSendExe::CompleteReschedule(RScheduler& aScheduler, const TSchedulerItemRef& aRef, TInt aCount)
       
   541 	{
       
   542 	if (aCount != 0)
       
   543 		{
       
   544 		aScheduler.EnableSchedule(aRef.iHandle);
       
   545 		}
       
   546 	else if (aRef.iHandle != KErrNotFound)
       
   547 		{
       
   548 		aScheduler.DeleteSchedule(aRef.iHandle);
       
   549 		}
       
   550 	aScheduler.Close();
       
   551 
       
   552 	SCHSENDLOG(FLog(iFileName, _L("\tCompleteReschedule [Ref=%d OutCount=%d]"), aRef.iHandle, aCount));
       
   553 	}
       
   554 
       
   555 void CMsvSendExe::RescheduleOnError(const CMsvEntrySelection& aSelection, const TMsvSchedulePackage& aPackage, TInt aError)
       
   556 	{
       
   557 	RScheduler scheduler;
       
   558 	TTime start;
       
   559 	start.UniversalTime();
       
   560 	TSchedulerItemRef ref;
       
   561 	ref.iHandle = KErrNotFound;
       
   562 	TInt count = 0;
       
   563 	TRAPD(err, DoResheduleOnErrorL(scheduler, aSelection, aPackage, aError, ref, count, start)); //ignore error
       
   564 
       
   565 	CompleteReschedule(scheduler, ref, count);
       
   566 	FailOnError(aSelection, aError); //fails outstanding messages that weren't rescheduled. Ignore error
       
   567 	}
       
   568 
       
   569 
       
   570 void CMsvSendExe::DoResheduleOnErrorL(RScheduler& aScheduler, const CMsvEntrySelection& aSelection, const TMsvSchedulePackage& aPackage, TInt aError, TSchedulerItemRef& aRef, TInt& aCount, TTime& aStartTime)
       
   571 	{
       
   572 	SCHSENDLOG(FLog(iFileName, _L("\tDoRescheduleOnError [aError=%d]"), aError));
       
   573 
       
   574 	CMsvScheduleSettings* settings = CMsvScheduleSettings::NewL();
       
   575 	CleanupStack::PushL(settings);
       
   576 
       
   577 	TMsvSchedulePackage package(aPackage);
       
   578 	TInt selCount = aSelection.Count();
       
   579 	TTaskInfo info;
       
   580 	TInt err = KErrNone;
       
   581 
       
   582 	//Schedule each message
       
   583 	while (selCount--)
       
   584 		{
       
   585 		const TMsvId id = aSelection[selCount];
       
   586 
       
   587 		TBool scheduleMessage = ETrue;
       
   588 		CMsvEntry* cEntry = NULL;
       
   589 		TMsvEntry entry;
       
   590 
       
   591 		if (iSession != NULL)
       
   592 			TRAP(err, cEntry = iSession->GetEntryL(id));
       
   593 
       
   594 		SCHSENDLOG(FLog(iFileName, _L("\t\tScheduling Task [Id=%d Err=%d iSession=0x%X cEntry=0x%X]..."), id, err, iSession, cEntry));
       
   595 
       
   596 		if (cEntry != NULL)
       
   597 			{
       
   598 			CleanupStack::PushL(cEntry);
       
   599 			entry = cEntry->Entry();
       
   600 			switch (entry.SendingState())
       
   601 				{
       
   602 				case KMsvSendStateWaiting:
       
   603 				case KMsvSendStateScheduled:
       
   604 				case KMsvSendStateResend:
       
   605 
       
   606 					scheduleMessage = ETrue;
       
   607 					break;
       
   608 
       
   609 				case KMsvSendStateFailed:
       
   610 				case KMsvSendStateSent:
       
   611 				case KMsvSendStateSuspended:
       
   612 				default:
       
   613 
       
   614 					scheduleMessage = EFalse;
       
   615 					SCHSENDLOG(FLog(iFileName, _L("\t\tNot Scheduled Task [Id=%d State=%d Err=%d]"), id, entry.SendingState(), entry.iError));
       
   616 					break;
       
   617 				}
       
   618 			} //end if
       
   619 
       
   620 		if (scheduleMessage)
       
   621 			{
       
   622 			if (aRef.iHandle == KErrNotFound)
       
   623 				{
       
   624 				//Find or create the schedule
       
   625 				if (cEntry != NULL)
       
   626 					{
       
   627 					TRAP(err, RestoreScheduleSettingsL(entry.iServiceId, entry.iMtm, *settings)); //use default if err != KErrNone
       
   628 					SCHSENDLOG(FLog(iFileName, _L("\t\tRestoreScheduleSettings [Err=%d]"), err));
       
   629 					}
       
   630 
       
   631 				CMsvScheduleSend::ConnectAndRegisterL(aScheduler, *settings);
       
   632 				
       
   633 				if (FindorCreateScheduleL(aScheduler, aStartTime, *settings, aRef))
       
   634 					aCount++;
       
   635 				
       
   636 				User::LeaveIfError(aScheduler.DisableSchedule(aRef.iHandle));
       
   637 				}
       
   638 			
       
   639 			//Schedule the message
       
   640 			package.iId = id;
       
   641 			CMsvScheduleSend::ScheduleEntryL(aScheduler, aRef, package, info);
       
   642 			SCHSENDLOG(FLog(iFileName, _L("\t\tScheduleEntryL [Id=%d Task=%d]"), id, info.iTaskId));
       
   643 
       
   644 			if (cEntry != NULL)
       
   645 				{
       
   646 				//Update the message
       
   647 				entry.iError = aError;
       
   648 				TRAP(err, UpdateEntryL(*cEntry, entry, aRef, info, aStartTime));
       
   649 				SCHSENDLOG(FLog(iFileName, _L("\t\tEntry updated [Err=%d]"), err));
       
   650 				}
       
   651 
       
   652 			aCount++;
       
   653 
       
   654 			SCHSENDLOG(FLog(iFileName, _L("\t\tScheduled Task Complete [Id=%d Task=%d]"), id, info.iTaskId));
       
   655 			}
       
   656 
       
   657 		if (cEntry)
       
   658 			CleanupStack::PopAndDestroy(cEntry);
       
   659 		} //end while
       
   660 
       
   661 	CleanupStack::PopAndDestroy(settings);
       
   662 	}
       
   663 
       
   664 TBool CMsvSendExe::FindorCreateScheduleL(RScheduler& aScheduler, TTime& aStartTime, const CMsvScheduleSettings& aSettings, TSchedulerItemRef& aRef)
       
   665 	{
       
   666 	aStartTime.UniversalTime();
       
   667 	aStartTime += (TTimeIntervalMicroSeconds32) (KSchSendExeMinReschedule - KMsvSendExeOneMinute);
       
   668 	TInt err = KErrNotFound;
       
   669 	const TInt max = (KSchSendExeMaxReschedule - KSchSendExeMinReschedule) / KMsvSendExeOneMinute;
       
   670 
       
   671 	for (TInt i = 0; err != KErrNone && i < max; i++)
       
   672 		{
       
   673 		aStartTime += (TTimeIntervalMicroSeconds32) KMsvSendExeOneMinute;
       
   674 		CMsvScheduleSend::RoundUpToMinute(aStartTime);
       
   675 		TRAP(err, CMsvScheduleSend::FindScheduleL(aScheduler, aStartTime, aRef));
       
   676 		}
       
   677 
       
   678 	if (err != KErrNone)
       
   679 		{
       
   680 		CMsvScheduleSend::CreateScheduleL(aScheduler, aSettings, aStartTime, aSettings.ValidityPeriod(), aRef);
       
   681 		SCHSENDLOG(FLog(iFileName, _L("\t\tSchedule Created (Ref=%d) for:"), aRef.iHandle));
       
   682 		}
       
   683 	else
       
   684 		SCHSENDLOG(FLog(iFileName, _L("\t\tSchedule Found (Ref=%d) for:"), aRef.iHandle));
       
   685 
       
   686 #ifndef _MSG_NO_LOGGING
       
   687 	TBuf<32> bufDate;
       
   688 	aStartTime.FormatL(bufDate, _L("%D%M%Y%/0%1%/1%2%/2%3%/3 %-B%:0%J%:1%T%:2%S%.%*C4%:3%+B"));
       
   689 	SCHSENDLOG(FLog(iFileName, _L("\t\t%S"), &bufDate));
       
   690 #endif
       
   691 
       
   692 	return (err == KErrNone);
       
   693 	}
       
   694 
       
   695 void CMsvSendExe::RestoreScheduleSettingsL(TMsvId aServiceId, const TUid& aMtm, CMsvScheduleSettings& aSettings)
       
   696 	{
       
   697 	TMsvSelectionOrdering order;
       
   698 	order.SetShowInvisibleEntries(ETrue);
       
   699 	CMsvEntry* cEntry = CMsvEntry::NewL(*iSession, KMsvRootIndexEntryId, order);
       
   700 	CleanupStack::PushL(cEntry);
       
   701 
       
   702 	if (aServiceId == KMsvLocalServiceIndexEntryId)
       
   703 		{
       
   704 		const TInt count = cEntry->Count();
       
   705 
       
   706 		for (TInt i = 0; i < count; i++)
       
   707 			{
       
   708 			const TMsvEntry& entry = (*cEntry)[i];
       
   709 			if (entry.iType == KUidMsvServiceEntry && entry.iMtm == aMtm)
       
   710 				{
       
   711 				aServiceId = entry.Id();
       
   712 				break;
       
   713 				}
       
   714 			}
       
   715 		}
       
   716 
       
   717 	if (aServiceId == KMsvLocalServiceIndexEntryId)
       
   718 		User::Leave(KErrNotFound);
       
   719 	
       
   720 	CRepository* repository = CRepository::NewLC(aMtm);
       
   721 	TMsvScheduleSettingsUtils::LoadScheduleSettingsL(aSettings, *repository);
       
   722 	CleanupStack::PopAndDestroy(2, cEntry); // repository, cEntry
       
   723 	}
       
   724 
       
   725 void CMsvSendExe::FailOnError(const CMsvEntrySelection& aSelection, TInt aError)
       
   726 	{
       
   727 	if (iSession == NULL)
       
   728 		return;
       
   729 
       
   730 	TInt selCount = aSelection.Count();
       
   731 	TInt err = KErrNone;
       
   732 	CMsvEntry* cEntry = NULL;
       
   733 
       
   734 	while (selCount--)
       
   735 		{
       
   736 		const TMsvId id = aSelection[selCount];
       
   737 		TRAP(err, cEntry = iSession->GetEntryL(id));
       
   738 		//no need for the cleanup stack
       
   739 
       
   740 		if (err == KErrNone)
       
   741 			{
       
   742 			TMsvEntry entry(cEntry->Entry());
       
   743 			switch (entry.SendingState())
       
   744 				{
       
   745 				case KMsvSendStateWaiting:
       
   746 				case KMsvSendStateScheduled:
       
   747 				case KMsvSendStateResend:
       
   748 
       
   749 					if (entry.iDate < iCreated)
       
   750 						{
       
   751 						//Message has not been rescheduled
       
   752 						entry.SetSendingState(KMsvSendStateFailed);
       
   753 						entry.SetScheduled(EFalse);
       
   754 						entry.SetFailed(ETrue);
       
   755 						entry.iError = aError;
       
   756 						TRAP(err, cEntry->ChangeL(entry)); //ignore error
       
   757 						}
       
   758 
       
   759 					break;
       
   760 
       
   761 				default:
       
   762 					break;
       
   763 				}
       
   764 
       
   765 			delete cEntry;
       
   766 			cEntry = NULL;
       
   767 			} //end if
       
   768 		} //end while
       
   769 	}
       
   770 
       
   771 void CMsvSendExe::UpdateEntryL(CMsvEntry& aMsvEntry, TMsvEntry& aEntry, const TSchedulerItemRef& aRef, const TTaskInfo& aInfo, const TTime& aStartTime)
       
   772 	{
       
   773 	CMsvStore* store = aMsvEntry.EditStoreL();
       
   774 	CleanupStack::PushL(store);
       
   775 
       
   776 	TMsvEntryScheduleData data;
       
   777 	data.RestoreL(*store);
       
   778 
       
   779 	CMsvScheduleSend::UpdateEntryAfterSchedule(aRef, aInfo, aStartTime, KMsvSendStateResend, aEntry, data);
       
   780 
       
   781 	data.StoreL(*store);
       
   782 	store->CommitL();
       
   783 
       
   784 	CleanupStack::PopAndDestroy(store);
       
   785 	aMsvEntry.ChangeL(aEntry);
       
   786 	}
       
   787