os/persistentdata/loggingservices/eventlogger/LogServ/src/logservsession.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "logservsession.h"
sl@0
    17
#include "LogNotify.h"
sl@0
    18
#include "LogServServer.h"
sl@0
    19
#include "logservpanic.h"
sl@0
    20
#include "LogServView.h"
sl@0
    21
#include "LogServOperationBase.h"
sl@0
    22
#include "LogServBackupInterface.h"
sl@0
    23
#include "LogServOperationFactory.h"
sl@0
    24
#include "LogServOperationManager.h"
sl@0
    25
#include "LogServDatabaseChangeInterface.h"
sl@0
    26
#include "LogServDatabaseChangeDefinition.h"
sl@0
    27
#include "LogServSqlStrings.h"
sl@0
    28
sl@0
    29
// Constants
sl@0
    30
const TInt KLogViewListGranuality = 5;
sl@0
    31
const TInt KLogServPendingGlobalChangesArrayGranularity = 3;
sl@0
    32
sl@0
    33
sl@0
    34
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    35
// -----> CLogServSession (source)
sl@0
    36
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    37
sl@0
    38
CLogServSession::CLogServSession(TLogServSessionId aSessionId, 
sl@0
    39
                                 MLogServSessionLifetimeObserver& aObserver, 
sl@0
    40
                                 MLogServBackupInterface& aBackupInterface, 
sl@0
    41
                                 MLogServTaskInterface& aTaskInterface, 
sl@0
    42
                                 MLogServOperationManager& aOperationManager, 
sl@0
    43
                                 MLogServDatabaseChangeInterface& aChangeInterface, 
sl@0
    44
                                 MLogServDatabaseTransactionInterface& aDatabase) :
sl@0
    45
    iSessionId(aSessionId), 
sl@0
    46
    iObserver(aObserver), 
sl@0
    47
    iBackupInterface(aBackupInterface), 
sl@0
    48
    iTaskInterface(aTaskInterface), 
sl@0
    49
    iOperationManager(aOperationManager), 
sl@0
    50
    iChangeInterface(aChangeInterface), 
sl@0
    51
    iDatabase(aDatabase), 
sl@0
    52
    iViewList(KLogViewListGranuality), 
sl@0
    53
    iPendingGlobalChanges(KLogServPendingGlobalChangesArrayGranularity)
sl@0
    54
	{
sl@0
    55
	iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventCreated); 
sl@0
    56
	}
sl@0
    57
sl@0
    58
CLogServSession::~CLogServSession()
sl@0
    59
	{
sl@0
    60
	LOGTEXT3("CLogServSession::~CLogServSession() - client logging off: %S, %d", &iClientThreadName, iSessionId);
sl@0
    61
sl@0
    62
	// Set second parameter to not complete the message, otherwise if the client has died a KERN-EXEC 44 will be generated.
sl@0
    63
	iOperationManager.OMCancel(iSessionId, EFalse);
sl@0
    64
	
sl@0
    65
	delete iPackage;
sl@0
    66
	delete iNotify;
sl@0
    67
sl@0
    68
	iChangeInterface.DCIRequestChangeNotificationsCancel(*this);
sl@0
    69
	//
sl@0
    70
	iViewList.ResetAndDestroy();
sl@0
    71
	iViewList.Close();
sl@0
    72
	iPendingGlobalChanges.Close();
sl@0
    73
	//
sl@0
    74
	iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventDestroyed); 
sl@0
    75
sl@0
    76
	LOGTEXT2("CLogServSession::~CLogServSession() - client dead %d", iSessionId);
sl@0
    77
	LOGTEXT("");
sl@0
    78
	}
sl@0
    79
sl@0
    80
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    81
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    82
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    83
sl@0
    84
void CLogServSession::DCOHandleGlobalChangeEventL(const TLogServDatabaseChangeDefinition& aChange)
sl@0
    85
	{
sl@0
    86
	if	(iExtendedNotificationRequested)
sl@0
    87
		User::LeaveIfError(iPendingGlobalChanges.Append(aChange));
sl@0
    88
	ExtendedNotifyCompleteL(KErrNone);
sl@0
    89
	}
sl@0
    90
sl@0
    91
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    92
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    93
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
    94
void CLogServSession::CreateL()
sl@0
    95
	{
sl@0
    96
	iPackage = CLogPackage::NewL();
sl@0
    97
sl@0
    98
	// Request change notifications
sl@0
    99
	iChangeInterface.DCIRequestChangeNotificationsL(*this);
sl@0
   100
	}
sl@0
   101
sl@0
   102
//
sl@0
   103
//  Handle a client request.
sl@0
   104
//
sl@0
   105
//  Leaving is handled by CLogServ::RunError() which reports the error code to the client
sl@0
   106
//  Note: operation add themselves to the server active queue in their constructor
sl@0
   107
//  The server active object owns them and deletes them when necessary
sl@0
   108
//  So the iffy looking code below won't actually leak memory
sl@0
   109
//
sl@0
   110
void CLogServSession::ServiceL(const RMessage2& aMessage)
sl@0
   111
	{
sl@0
   112
	LOGTEXT3("CLogServSession::ServiceL(%S, %d)", &iClientThreadName, aMessage.Function());
sl@0
   113
sl@0
   114
	switch(aMessage.Function())
sl@0
   115
		{
sl@0
   116
	/**
sl@0
   117
	 * Overall operation management
sl@0
   118
	 */
sl@0
   119
	case ELogOperationGetResult:
sl@0
   120
	case ELogOperationCancel:
sl@0
   121
	case ELogOperationInitiate:
sl@0
   122
		ServiceOperationFunctionL(aMessage);
sl@0
   123
		break;
sl@0
   124
sl@0
   125
	/**
sl@0
   126
	 * Notification related
sl@0
   127
	 */
sl@0
   128
	case ELogNotify:
sl@0
   129
		{
sl@0
   130
		if	(!iNotify)
sl@0
   131
			{
sl@0
   132
			iNotify = CLogNotify::NewL(iBackupInterface, iChangeInterface, Server().Priority());
sl@0
   133
sl@0
   134
		#ifdef LOGGING_ENABLED
sl@0
   135
			iNotify->SetClientThreadName(iClientThreadName);
sl@0
   136
		#endif
sl@0
   137
			}
sl@0
   138
		
sl@0
   139
		if	(!iNotify->IsActive())
sl@0
   140
			{
sl@0
   141
			const TTimeIntervalMicroSeconds32 delayTime = reinterpret_cast<TInt>(aMessage.Ptr0());
sl@0
   142
			
sl@0
   143
			//Validate time value
sl@0
   144
			if(delayTime.Int() < 0)
sl@0
   145
				{
sl@0
   146
				User::Leave(KErrArgument);
sl@0
   147
				}
sl@0
   148
			iNotify->Notify(delayTime, aMessage);
sl@0
   149
			}
sl@0
   150
		else
sl@0
   151
			::PanicClientL(aMessage, ELogAlreadyActive19);
sl@0
   152
		break;
sl@0
   153
		}
sl@0
   154
	case ELogNotifyCancel:
sl@0
   155
		{
sl@0
   156
		if	(iNotify)
sl@0
   157
			iNotify->Cancel();
sl@0
   158
		aMessage.Complete(KErrCancel);
sl@0
   159
		break;
sl@0
   160
		}
sl@0
   161
	case ELogNotifyExtended:
sl@0
   162
		{
sl@0
   163
		if	(iExtendedNotificationMessage == RMessage2())
sl@0
   164
			{
sl@0
   165
			iExtendedNotificationMessage = aMessage;
sl@0
   166
			iExtendedNotificationRequested = ETrue;
sl@0
   167
			}
sl@0
   168
		else
sl@0
   169
			::PanicClientL(aMessage, ELogExtendedMessageAlreadyActive);
sl@0
   170
		break;
sl@0
   171
		}
sl@0
   172
	case ELogNotifyExtendedCancel:
sl@0
   173
		{
sl@0
   174
        if	(iExtendedNotificationMessage != RMessage2())
sl@0
   175
			ExtendedNotifyCompleteL(KErrCancel);
sl@0
   176
		//
sl@0
   177
		iExtendedNotificationRequested = EFalse;
sl@0
   178
		iPendingGlobalChanges.Reset();
sl@0
   179
		iPendingGlobalChanges.GranularCompress();
sl@0
   180
		//
sl@0
   181
		aMessage.Complete(KErrCancel);
sl@0
   182
		break;
sl@0
   183
		}
sl@0
   184
sl@0
   185
	/**
sl@0
   186
	 * View functionality
sl@0
   187
	 */
sl@0
   188
	case ELogViewCreate:
sl@0
   189
	case ELogViewDelete:
sl@0
   190
	case ELogViewCount:
sl@0
   191
	case ELogViewOperationInitiate:
sl@0
   192
	case ELogViewChangeNotificationsRequest:
sl@0
   193
	case ELogViewChangeNotificationsCancel:
sl@0
   194
	case ELogViewFetchChanges:
sl@0
   195
	case ELogViewNotifyLockStatusChange:
sl@0
   196
	case ELogViewNotifyLockStatusChangeCancel:
sl@0
   197
		ServiceViewFunctionL(aMessage);
sl@0
   198
		break;
sl@0
   199
sl@0
   200
	/** 
sl@0
   201
	 * Misc. (debug) functionality
sl@0
   202
	 */
sl@0
   203
#ifdef _DEBUG
sl@0
   204
	case ELogMakeTransient:
sl@0
   205
		{
sl@0
   206
		Server().MakeTransient((TBool)aMessage.Ptr0());
sl@0
   207
		aMessage.Complete(KErrNone);
sl@0
   208
		break;
sl@0
   209
		}
sl@0
   210
	case ELogIsServerReady:
sl@0
   211
		{
sl@0
   212
		const TBool serverReady = (iBackupInterface.BIErrorValueForCurrentState() == KErrNone);
sl@0
   213
		aMessage.Complete(serverReady);
sl@0
   214
		break;
sl@0
   215
		}
sl@0
   216
	case ELogSetHeapFail:
sl@0
   217
		{
sl@0
   218
		User::__DbgSetAllocFail(RHeap::EUser, RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1());
sl@0
   219
		aMessage.Complete(KErrNone);
sl@0
   220
		break;
sl@0
   221
		}
sl@0
   222
#endif// _DEBUG
sl@0
   223
	/**
sl@0
   224
	 * Unknown operations
sl@0
   225
	 */
sl@0
   226
	default:
sl@0
   227
		::PanicClientL(aMessage, ELogIllegalFunction);
sl@0
   228
		break;
sl@0
   229
		}
sl@0
   230
	}
sl@0
   231
sl@0
   232
/**
sl@0
   233
If aError is KErrBadDescriptor, then panic the client, else - default error handling.
sl@0
   234
KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
sl@0
   235
descriptor to the server.
sl@0
   236
*/
sl@0
   237
void CLogServSession::ServiceError(const RMessage2& aMessage,TInt aError)
sl@0
   238
	{
sl@0
   239
	if(aError == KErrBadDescriptor)
sl@0
   240
		{
sl@0
   241
		//The __LOGPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
sl@0
   242
		//from a leaving call will terminate the server.
sl@0
   243
		aMessage.Panic(KLogServ, ELogBadDescriptor);
sl@0
   244
		}
sl@0
   245
	CSession2::ServiceError(aMessage, aError);
sl@0
   246
	}
sl@0
   247
	
sl@0
   248
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   249
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   250
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   251
sl@0
   252
CLogServServer& CLogServSession::Server() const
sl@0
   253
	{
sl@0
   254
	return *static_cast<CLogServServer*>(const_cast<CServer2*>(CSession2::Server()));
sl@0
   255
	}
sl@0
   256
sl@0
   257
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   258
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   259
/////////////////////////////////////////////////////////////////////////////////////////
sl@0
   260
sl@0
   261
sl@0
   262
CLogServViewBase& CLogServSession::ViewByIdL(TUint32 aViewId)
sl@0
   263
	{
sl@0
   264
	const TInt index = ViewPositionById(aViewId);
sl@0
   265
	User::LeaveIfError(index);
sl@0
   266
	return *iViewList[index];
sl@0
   267
	}
sl@0
   268
sl@0
   269
TInt CLogServSession::ViewPositionById(TUint32 aViewId) const
sl@0
   270
	{
sl@0
   271
	const TInt count = iViewList.Count();
sl@0
   272
	for(TInt i=0; i<count; i++)
sl@0
   273
		{
sl@0
   274
		const CLogServViewBase& view = *iViewList[i];
sl@0
   275
		if	(view.ViewId() == aViewId)
sl@0
   276
			return i;
sl@0
   277
		}
sl@0
   278
	return KErrNotFound;
sl@0
   279
	}
sl@0
   280
sl@0
   281
sl@0
   282
void CLogServSession::ReadClientServerDataL(TLogClientServerData& aClientServerData,
sl@0
   283
		const RMessage2 &aMessage, TInt aMinOperation, TInt aMaxOperation)
sl@0
   284
	{
sl@0
   285
sl@0
   286
	TInt length = aMessage.GetDesLengthL(0);
sl@0
   287
	if(length != sizeof(TLogClientServerData))
sl@0
   288
		{
sl@0
   289
		User::Leave(KErrBadDescriptor);
sl@0
   290
		}
sl@0
   291
	
sl@0
   292
	TPckg<TLogClientServerData> pData(aClientServerData);
sl@0
   293
	aMessage.ReadL(0, pData);
sl@0
   294
	
sl@0
   295
	//Validate Operation Type
sl@0
   296
	if((aClientServerData.iOperationType < aMinOperation) ||
sl@0
   297
			(aClientServerData.iOperationType > aMaxOperation))
sl@0
   298
		{
sl@0
   299
		User::Leave(KErrArgument);
sl@0
   300
		}
sl@0
   301
	}
sl@0
   302
sl@0
   303
void CLogServSession::ServiceViewFunctionL(const RMessage2& aMessage)
sl@0
   304
	{
sl@0
   305
	switch(aMessage.Function())
sl@0
   306
		{
sl@0
   307
	case ELogViewCreate:
sl@0
   308
		{
sl@0
   309
		iViewList.ReserveL(iViewList.Count() + 1);
sl@0
   310
		// Type is first parameter, view id is second
sl@0
   311
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   312
		const TLogViewType type = static_cast<TLogViewType>(aMessage.Int1());
sl@0
   313
		
sl@0
   314
		//Validate type value
sl@0
   315
		if((type < ELogViewTypeEvent)||(type > ELogViewTypeDuplicate))
sl@0
   316
			{
sl@0
   317
			User::Leave(KErrArgument);
sl@0
   318
			}
sl@0
   319
		
sl@0
   320
		// Ask the factory to create it
sl@0
   321
		CLogServViewBase* view = LogServFactory::NewViewL(type, id, iDatabase, iBackupInterface, *iPackage, aMessage);
sl@0
   322
		TInt err = iViewList.Append(view);
sl@0
   323
        __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
sl@0
   324
		aMessage.Complete(err);
sl@0
   325
		break;
sl@0
   326
		}
sl@0
   327
	case ELogViewDelete:
sl@0
   328
		{
sl@0
   329
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   330
		TInt indexAndError = ViewPositionById(id);
sl@0
   331
		if	(indexAndError >= 0)
sl@0
   332
			{
sl@0
   333
			delete iViewList[indexAndError];
sl@0
   334
			iViewList.Remove(indexAndError);
sl@0
   335
			indexAndError = KErrNone;
sl@0
   336
			}
sl@0
   337
		aMessage.Complete(indexAndError);
sl@0
   338
		break;
sl@0
   339
		}
sl@0
   340
	case ELogViewCount:
sl@0
   341
		{
sl@0
   342
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   343
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   344
		const TInt count = view.Count();
sl@0
   345
		aMessage.Complete(count);
sl@0
   346
		break;
sl@0
   347
		}
sl@0
   348
	case ELogViewOperationInitiate:
sl@0
   349
		{
sl@0
   350
		// We don't allow any operations during a backup
sl@0
   351
		iBackupInterface.BIValidateStateForDatabaseOperationL();
sl@0
   352
		//
sl@0
   353
		TLogClientServerData clientServerData;
sl@0
   354
		ReadClientServerDataL(clientServerData,aMessage, 
sl@0
   355
				ELogOperationViewSetup, ELogOperationViewWindowFetch);
sl@0
   356
sl@0
   357
		//
sl@0
   358
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int1());
sl@0
   359
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   360
sl@0
   361
		// Create operation. Operations are owned by the operation manager (they are added to a queue)
sl@0
   362
		// when the objects are created, so this does not leak any memory.
sl@0
   363
		CLogServOperationBase* operation = LogServFactory::NewViewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId, view);
sl@0
   364
		(void) operation;
sl@0
   365
		break;
sl@0
   366
		}
sl@0
   367
	case ELogViewChangeNotificationsRequest:
sl@0
   368
		{
sl@0
   369
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   370
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   371
		view.RequestChangeNotifications(aMessage);
sl@0
   372
		break;
sl@0
   373
		}
sl@0
   374
	case ELogViewChangeNotificationsCancel:
sl@0
   375
		{
sl@0
   376
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   377
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   378
		view.RequestChangeNotificationsCancel();
sl@0
   379
		aMessage.Complete(KErrNone);
sl@0
   380
		break;
sl@0
   381
		}
sl@0
   382
	case ELogViewFetchChanges:
sl@0
   383
		{
sl@0
   384
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   385
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   386
		view.RequestChangesL(aMessage);
sl@0
   387
		aMessage.Complete(KErrNone);
sl@0
   388
		break;
sl@0
   389
		}
sl@0
   390
	case ELogViewNotifyLockStatusChange:
sl@0
   391
		{
sl@0
   392
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   393
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   394
		view.RequestLockStatusChanges(aMessage);
sl@0
   395
		break;
sl@0
   396
		}
sl@0
   397
	case ELogViewNotifyLockStatusChangeCancel:
sl@0
   398
		{
sl@0
   399
		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
sl@0
   400
		CLogServViewBase& view = ViewByIdL(id);
sl@0
   401
		view.RequestLockStatusChangesCancel();
sl@0
   402
		aMessage.Complete(KErrNone);
sl@0
   403
		break;
sl@0
   404
		}
sl@0
   405
		}
sl@0
   406
	}
sl@0
   407
sl@0
   408
void CLogServSession::ServiceOperationFunctionL(const RMessage2& aMessage)
sl@0
   409
	{
sl@0
   410
	// We don't allow any operations during a backup
sl@0
   411
	iBackupInterface.BIValidateStateForDatabaseOperationL();
sl@0
   412
	//
sl@0
   413
	TLogClientServerData clientServerData;
sl@0
   414
	ReadClientServerDataL(clientServerData,aMessage, ELogOperationEventAdd,ELogOperationMaintain);
sl@0
   415
	//
sl@0
   416
	const TInt function = aMessage.Function();
sl@0
   417
	//
sl@0
   418
	const TLogOperationId& operationId = clientServerData.iOperationId;
sl@0
   419
	#ifdef LOGGING_ENABLED
sl@0
   420
	const TLogOperationType& operationType = clientServerData.iOperationType;
sl@0
   421
	#endif
sl@0
   422
	LOGTEXT4("CLogServSession::ServiceOperationFunctionL() - Operation function for client %S: Id: %d, Type: %d", &iClientThreadName, operationId, operationType);
sl@0
   423
	//
sl@0
   424
	switch(function)
sl@0
   425
		{
sl@0
   426
	case ELogOperationGetResult:
sl@0
   427
		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - getting result");
sl@0
   428
		iOperationManager.OMGetResultL(operationId, iSessionId, aMessage);
sl@0
   429
		aMessage.Complete(KErrNone);
sl@0
   430
		break;
sl@0
   431
	case ELogOperationCancel:
sl@0
   432
		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - cancelling");
sl@0
   433
		iOperationManager.OMCancel(operationId, iSessionId, ETrue);
sl@0
   434
		aMessage.Complete(KErrCancel);
sl@0
   435
		break;
sl@0
   436
	case ELogOperationInitiate:
sl@0
   437
		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - initiating");
sl@0
   438
		// Create operation. Operations are owned by the operation manager (they are added to a queue)
sl@0
   439
		// when the objects are created, so this does not leak any memory.
sl@0
   440
		CLogServOperationBase* operation = LogServFactory::NewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId);
sl@0
   441
		(void) operation;
sl@0
   442
		break;
sl@0
   443
		}
sl@0
   444
	LOGTEXT("CLogServSession::ServiceOperationFunctionL() - end");
sl@0
   445
	}
sl@0
   446
sl@0
   447
void CLogServSession::ExtendedNotifyCompleteL(TInt aCompletionCode)
sl@0
   448
	{
sl@0
   449
	const TInt count = iPendingGlobalChanges.Count();
sl@0
   450
    if	(iExtendedNotificationMessage != RMessage2() && (count || aCompletionCode < KErrNone))
sl@0
   451
		{
sl@0
   452
		if	(aCompletionCode >= KErrNone && count)
sl@0
   453
			{
sl@0
   454
			const TLogServDatabaseChangeDefinition& change = iPendingGlobalChanges[0];
sl@0
   455
			//
sl@0
   456
			const TPckgBuf<TInt> pContext(change.iChangeType.iUid);
sl@0
   457
			const TPckg<TInt> pParam1(change.iChangeParam1);
sl@0
   458
			const TPckg<TInt> pParam2(change.iChangeParam2);
sl@0
   459
			const TPckg<TInt> pParam3(change.iChangeParam3);
sl@0
   460
			//
sl@0
   461
			iExtendedNotificationMessage.WriteL(0, pContext);
sl@0
   462
			iExtendedNotificationMessage.WriteL(1, pParam1);
sl@0
   463
			iExtendedNotificationMessage.WriteL(2, pParam2);
sl@0
   464
			iExtendedNotificationMessage.WriteL(3, pParam3);
sl@0
   465
			//
sl@0
   466
			iPendingGlobalChanges.Remove(0);
sl@0
   467
			}
sl@0
   468
		//
sl@0
   469
		iExtendedNotificationMessage.Complete(aCompletionCode);
sl@0
   470
		}
sl@0
   471
	}