os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_request.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 the License "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
// f32\sfile\sf_request.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "sf_std.h"
sl@0
    19
#include "sf_file_cache.h"
sl@0
    20
#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
sl@0
    21
#include "sf_notifier.h"
sl@0
    22
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION	
sl@0
    23
sl@0
    24
sl@0
    25
TParse dummyP;
sl@0
    26
RMessage2 dummyM;
sl@0
    27
sl@0
    28
CFsClientMessageRequest* RequestAllocator::iFreeHead;				
sl@0
    29
CFsClientMessageRequest* RequestAllocator::iCloseHead;
sl@0
    30
TInt RequestAllocator::iAllocNum;
sl@0
    31
TInt RequestAllocator::iAllocNumOperation;
sl@0
    32
TMsgOperation* RequestAllocator::iFreeHeadSupOp;
sl@0
    33
sl@0
    34
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
    35
TInt RequestAllocator::iAllocated;
sl@0
    36
#endif
sl@0
    37
RFastLock RequestAllocator::iCacheLock;
sl@0
    38
sl@0
    39
void RequestAllocator::Initialise()
sl@0
    40
	{	
sl@0
    41
	iFreeHead=NULL;  
sl@0
    42
	iCloseHead=NULL; 
sl@0
    43
	iAllocNum=0; 
sl@0
    44
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
    45
	iAllocated=0;
sl@0
    46
#endif
sl@0
    47
	iAllocNumOperation=0;
sl@0
    48
	iFreeHeadSupOp=NULL;
sl@0
    49
	}
sl@0
    50
sl@0
    51
TInt RequestAllocator::AllocRequest(TInt aNum)
sl@0
    52
//
sl@0
    53
//	Allocates a group of request objects
sl@0
    54
//
sl@0
    55
	{
sl@0
    56
    TInt i;
sl@0
    57
	if(iAllocNum < KMaxRequestAllocated)
sl@0
    58
		{
sl@0
    59
		__CACHE_PRINT(_L("RequestAllocator::AllocRequest() Not reached the limit"));
sl@0
    60
		CFsClientMessageRequest* list;
sl@0
    61
		CFsClientMessageRequest* start;
sl@0
    62
		list = new CFsClientMessageRequest[KAllocReqBlock];
sl@0
    63
		start = list;
sl@0
    64
		if(!list)
sl@0
    65
			return KErrNoMemory;
sl@0
    66
		
sl@0
    67
		// Make sure the constructors are called for every element in the array
sl@0
    68
		// - some compilers don't do this
sl@0
    69
		for(TInt j=0; j<KAllocReqBlock; j++)
sl@0
    70
			{
sl@0
    71
			CFsClientMessageRequest* request = &list[j];
sl@0
    72
			new(request) CFsClientMessageRequest();
sl@0
    73
			}
sl@0
    74
sl@0
    75
		iAllocNum += KAllocReqBlock;
sl@0
    76
		CFsClientMessageRequest* last;
sl@0
    77
		for(i=1;i<KAllocReqBlock;i++)
sl@0
    78
			{
sl@0
    79
			last = list;
sl@0
    80
			list++;
sl@0
    81
			last->iNext = list;
sl@0
    82
			}
sl@0
    83
		list->iNext = iFreeHead;
sl@0
    84
		iFreeHead = start;
sl@0
    85
		return KErrNone;
sl@0
    86
		}
sl@0
    87
	else
sl@0
    88
		{
sl@0
    89
		__CACHE_PRINT1(_L("RequestAllocator::AllocRequest() Limit exceeded Count = %d"),aNum);
sl@0
    90
		CFsClientMessageRequest* request;
sl@0
    91
		for(i=0;i<aNum;i++)
sl@0
    92
			{
sl@0
    93
			request=new CFsClientMessageRequest;
sl@0
    94
			if(!request)
sl@0
    95
				return KErrNoMemory;
sl@0
    96
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
    97
			iAllocated++;
sl@0
    98
#endif
sl@0
    99
			request->SetAllocated();
sl@0
   100
			request->iNext=iFreeHead;
sl@0
   101
			iFreeHead=request;
sl@0
   102
			}
sl@0
   103
		return KErrNone;
sl@0
   104
		}
sl@0
   105
	}
sl@0
   106
sl@0
   107
void RequestAllocator::FreeRequest(CFsClientMessageRequest* aRequest)
sl@0
   108
//
sl@0
   109
//free request 
sl@0
   110
//
sl@0
   111
	{
sl@0
   112
	__CACHE_PRINT1(_L("PLUGIN: RequestAllocator::FreeRequest for %x"), aRequest);
sl@0
   113
	if(aRequest->IsAllocated())
sl@0
   114
		{
sl@0
   115
		__CACHE_PRINT(_L("RequestAllocator::FreeRequest() Allocated request"));
sl@0
   116
		delete(aRequest);
sl@0
   117
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   118
		iAllocated--;
sl@0
   119
#endif
sl@0
   120
		return;
sl@0
   121
		}
sl@0
   122
	
sl@0
   123
	__CACHE_PRINT(_L("RequestAllocator::FreeRequest() returning to free list"));
sl@0
   124
	iCacheLock.Wait();
sl@0
   125
	aRequest->iNext = iFreeHead;
sl@0
   126
	iFreeHead=aRequest;
sl@0
   127
	aRequest->SetSubstedDrive(NULL);
sl@0
   128
	iCacheLock.Signal();
sl@0
   129
	}
sl@0
   130
sl@0
   131
void RequestAllocator::OpenSubFailed(CSessionFs* aSession)
sl@0
   132
//
sl@0
   133
//	Move requst from closed list to free list
sl@0
   134
//
sl@0
   135
	{
sl@0
   136
	__ASSERT_DEBUG(iCloseHead!=NULL,Fault(ERequestAllocatorOpenSubFailed)); // On arriving here Close Queue is supposed to be empty
sl@0
   137
	__ASSERT_ALWAYS(aSession!=NULL,Fault(ERequestAllocatorOpenSubFailed));
sl@0
   138
	if (iCloseHead==NULL)
sl@0
   139
		{
sl@0
   140
		return;
sl@0
   141
		}
sl@0
   142
	iCacheLock.Wait();
sl@0
   143
	CFsClientMessageRequest* rp = iCloseHead;
sl@0
   144
	iCloseHead = rp->iNext;
sl@0
   145
	
sl@0
   146
	// dec the number of closed requests owned by this session
sl@0
   147
	aSession->CloseRequestCountDec();
sl@0
   148
sl@0
   149
	rp->iNext = NULL;
sl@0
   150
	if(rp->IsAllocated())
sl@0
   151
		{
sl@0
   152
		__CACHE_PRINT(_L("RequestAllocator::OpenSubFailed() Allocated request"));
sl@0
   153
		delete(rp);
sl@0
   154
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   155
		iAllocated--;
sl@0
   156
#endif
sl@0
   157
		}
sl@0
   158
	else
sl@0
   159
		{
sl@0
   160
		__CACHE_PRINT(_L("RequestAllocator::OpenSubFailed()"));
sl@0
   161
		if(iFreeHead)
sl@0
   162
			{
sl@0
   163
			rp->iNext = iFreeHead;
sl@0
   164
			}
sl@0
   165
		else
sl@0
   166
			{
sl@0
   167
			rp->iNext = NULL;
sl@0
   168
			}
sl@0
   169
sl@0
   170
		iFreeHead = rp;		
sl@0
   171
		}
sl@0
   172
	iCacheLock.Signal();
sl@0
   173
	}
sl@0
   174
sl@0
   175
TInt RequestAllocator::GetMessageRequest(const TOperation& aOperation,const RMessage2& aMessage,CFsClientMessageRequest* &aRequest)
sl@0
   176
//
sl@0
   177
//	tries to get a pre allocated message from the cache. Failing that allocates one indivisualy 
sl@0
   178
//	
sl@0
   179
	{
sl@0
   180
	if(aOperation.IsOpenSubSess())
sl@0
   181
		{
sl@0
   182
		__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() Open sub-sess"));
sl@0
   183
		iCacheLock.Wait();
sl@0
   184
		if(iFreeHead == NULL || iFreeHead->iNext == NULL)
sl@0
   185
			{
sl@0
   186
			if(AllocRequest(2)!= KErrNone)
sl@0
   187
				{
sl@0
   188
				iCacheLock.Signal();
sl@0
   189
				return KErrNoMemory;
sl@0
   190
				}
sl@0
   191
			}
sl@0
   192
		aRequest= iFreeHead;						//get our request from free head
sl@0
   193
		iFreeHead = iFreeHead->iNext->iNext;	//set next but one as new free head read for next
sl@0
   194
sl@0
   195
		aRequest->iNext->iNext = NULL;				//seperate our request and close from free list
sl@0
   196
		CFsClientMessageRequest* CRp = aRequest->iNext;
sl@0
   197
		aRequest->iNext = NULL;
sl@0
   198
		if(iCloseHead)
sl@0
   199
			{
sl@0
   200
			CRp->iNext = iCloseHead;		//set second one as a reserved (tail) close request
sl@0
   201
			iCloseHead = CRp;
sl@0
   202
			}
sl@0
   203
		else
sl@0
   204
			iCloseHead = CRp;
sl@0
   205
		
sl@0
   206
		((CSessionFs*) aMessage.Session())->CloseRequestCountInc();
sl@0
   207
		}
sl@0
   208
	else if(aOperation.IsCloseSubSess())
sl@0
   209
		{
sl@0
   210
		__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() Close sub-sess"));
sl@0
   211
sl@0
   212
		CFsObject* pO = SessionObjectFromHandle(aMessage.Int3(),0,reinterpret_cast<CSessionFs*>(aMessage.Session()));
sl@0
   213
		if(!pO)
sl@0
   214
			return KErrBadHandle;
sl@0
   215
sl@0
   216
		CObjPromotion* pm = (CObjPromotion*)pO;
sl@0
   217
		TInt function = aMessage.Function();
sl@0
   218
		switch(function & KIpcFunctionMask)
sl@0
   219
			{
sl@0
   220
			case EFsFormatSubClose:
sl@0
   221
				{
sl@0
   222
				if(pm->UniqueID() != Formats->UniqueID())
sl@0
   223
					{
sl@0
   224
					return KErrBadHandle;
sl@0
   225
					}
sl@0
   226
				break;
sl@0
   227
				}
sl@0
   228
			case EFsDirSubClose:
sl@0
   229
				{
sl@0
   230
				if(pm->UniqueID() != Dirs->UniqueID())
sl@0
   231
					{
sl@0
   232
					return KErrBadHandle;
sl@0
   233
					}
sl@0
   234
				break;
sl@0
   235
				}
sl@0
   236
			case EFsFileSubClose:
sl@0
   237
				{
sl@0
   238
				if(pm->UniqueID() != FileShares->UniqueID())
sl@0
   239
					{
sl@0
   240
					return KErrBadHandle;
sl@0
   241
					}
sl@0
   242
				break;
sl@0
   243
				}
sl@0
   244
			case EFsRawSubClose:
sl@0
   245
				{
sl@0
   246
				if(pm->UniqueID() != RawDisks->UniqueID())
sl@0
   247
					{
sl@0
   248
					return KErrBadHandle;
sl@0
   249
					}
sl@0
   250
				break;
sl@0
   251
				}
sl@0
   252
			case EFsPluginSubClose:
sl@0
   253
				{
sl@0
   254
				if(pm->UniqueID() != FsPluginManager::iPluginConns->UniqueID())
sl@0
   255
					{
sl@0
   256
					return KErrBadHandle;
sl@0
   257
					}
sl@0
   258
				break;
sl@0
   259
				}
sl@0
   260
#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION					
sl@0
   261
			case EFsNotificationSubClose:
sl@0
   262
				{
sl@0
   263
				if(pm->UniqueID() != FsNotificationManager::iNotifyRequests->UniqueID())
sl@0
   264
					{
sl@0
   265
					return KErrBadHandle;
sl@0
   266
					}
sl@0
   267
				break;
sl@0
   268
				}
sl@0
   269
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION					
sl@0
   270
			default:
sl@0
   271
				Fault(ECloseSubBadMessage);
sl@0
   272
			}
sl@0
   273
sl@0
   274
		iCacheLock.Wait();
sl@0
   275
		aRequest = iCloseHead;
sl@0
   276
		iCloseHead = aRequest->iNext;
sl@0
   277
		((CSessionFs*) aMessage.Session())->CloseRequestCountDec();
sl@0
   278
		aRequest->iNext = NULL;
sl@0
   279
sl@0
   280
		if((function & KIpcFunctionMask)!= EFsPluginSubClose &&
sl@0
   281
			(function & KIpcFunctionMask)!= EFsNotificationSubClose)
sl@0
   282
			{
sl@0
   283
			aRequest->SetDrive(&TheDrives[((CFsDispatchObject*)pO)->DriveNumber()]);
sl@0
   284
			}
sl@0
   285
sl@0
   286
		aRequest->SetScratchValue((TUint)pO);
sl@0
   287
		}
sl@0
   288
	else
sl@0
   289
		{
sl@0
   290
		__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() "));
sl@0
   291
		iCacheLock.Wait();
sl@0
   292
		if(!iFreeHead)
sl@0
   293
			{
sl@0
   294
			if(AllocRequest(1) != KErrNone)
sl@0
   295
				{
sl@0
   296
				iCacheLock.Signal();
sl@0
   297
				return KErrNoMemory; 
sl@0
   298
				}
sl@0
   299
			}
sl@0
   300
		aRequest = iFreeHead;						
sl@0
   301
		iFreeHead = aRequest->iNext;
sl@0
   302
		aRequest->iNext= NULL;
sl@0
   303
		}
sl@0
   304
sl@0
   305
	aRequest->Init();
sl@0
   306
sl@0
   307
	iCacheLock.Signal();
sl@0
   308
sl@0
   309
	// pre-allocate any TParse objects needed by this request
sl@0
   310
	if (aRequest->AllocParseObjects(aOperation) != KErrNone)
sl@0
   311
		{
sl@0
   312
		aRequest->Free();
sl@0
   313
		return KErrNoMemory; 
sl@0
   314
		}
sl@0
   315
sl@0
   316
	__CACHE_PRINT1(_L("--RequestAllocator::GetMessageRequest() allocated %08x"), aRequest);
sl@0
   317
sl@0
   318
	return KErrNone;
sl@0
   319
	}	
sl@0
   320
sl@0
   321
sl@0
   322
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   323
TInt RequestAllocator::CloseCount()
sl@0
   324
	{TInt count=0;
sl@0
   325
	CFsClientMessageRequest* list=iCloseHead;
sl@0
   326
	while(list!=NULL)
sl@0
   327
		{
sl@0
   328
		count++;
sl@0
   329
		list=list->iNext;
sl@0
   330
		}
sl@0
   331
	return(count);
sl@0
   332
	} 
sl@0
   333
TInt RequestAllocator::FreeCount()
sl@0
   334
	{
sl@0
   335
	TInt count=0;
sl@0
   336
	CFsClientMessageRequest* list=iFreeHead;
sl@0
   337
	while(list!=NULL)
sl@0
   338
		{
sl@0
   339
		count++;
sl@0
   340
		list=list->iNext;
sl@0
   341
		}
sl@0
   342
	return(count);}
sl@0
   343
#endif
sl@0
   344
sl@0
   345
TInt RequestAllocator::AllocOperation()
sl@0
   346
//
sl@0
   347
//	Allocates a group of TMsgOperation objects
sl@0
   348
//
sl@0
   349
// Must be called with iCacheLock held
sl@0
   350
	{
sl@0
   351
    TInt i;
sl@0
   352
	if(iAllocNumOperation < KMaxOperationAllocated)
sl@0
   353
		{
sl@0
   354
		__CACHE_PRINT(_L("RequestAllocator::AllocOperation() Not reached the limit"));
sl@0
   355
		TMsgOperation* list;
sl@0
   356
		TMsgOperation* start;
sl@0
   357
		list = new TMsgOperation[KAllocReqBlock];
sl@0
   358
		start = list;
sl@0
   359
		if(!list)
sl@0
   360
			return KErrNoMemory;
sl@0
   361
		
sl@0
   362
		for(TInt j=0; j<KAllocReqBlock; j++)
sl@0
   363
			{
sl@0
   364
			TMsgOperation* request = &list[j];
sl@0
   365
			request->iIsAllocated = EFalse;
sl@0
   366
			}
sl@0
   367
sl@0
   368
		iAllocNumOperation += KAllocReqBlock;
sl@0
   369
		TMsgOperation* last;
sl@0
   370
		for(i=1;i<KAllocReqBlock;i++)
sl@0
   371
			{
sl@0
   372
			last = list;
sl@0
   373
			list++;
sl@0
   374
			last->iNext = list;
sl@0
   375
			}
sl@0
   376
		list->iNext = iFreeHeadSupOp;
sl@0
   377
		iFreeHeadSupOp = start;
sl@0
   378
		return KErrNone;
sl@0
   379
		}
sl@0
   380
	else
sl@0
   381
		{
sl@0
   382
		__CACHE_PRINT(_L("RequestAllocator::AllocOperation() Limit exceeded"));
sl@0
   383
		TMsgOperation* request;
sl@0
   384
sl@0
   385
		request=new TMsgOperation;
sl@0
   386
		if(!request)
sl@0
   387
			return KErrNoMemory;
sl@0
   388
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   389
		iAllocated++;
sl@0
   390
#endif
sl@0
   391
		request->iIsAllocated = ETrue;
sl@0
   392
		request->iNext=iFreeHeadSupOp;
sl@0
   393
		iFreeHeadSupOp=request;
sl@0
   394
sl@0
   395
		return KErrNone;
sl@0
   396
		}
sl@0
   397
	}
sl@0
   398
TInt RequestAllocator::GetOperation(TMsgOperation* &aOperation)
sl@0
   399
//
sl@0
   400
//	tries to get a pre allocated subop from the cache. Failing that allocates one individualy 
sl@0
   401
//	
sl@0
   402
	{
sl@0
   403
sl@0
   404
	__CACHE_PRINT(_L("RequestAllocator::GetOperation() "));
sl@0
   405
	iCacheLock.Wait();
sl@0
   406
	if(!iFreeHeadSupOp)
sl@0
   407
		{
sl@0
   408
		if(AllocOperation() != KErrNone)
sl@0
   409
			{
sl@0
   410
			iCacheLock.Signal();
sl@0
   411
			return KErrNoMemory; 
sl@0
   412
			}
sl@0
   413
		}
sl@0
   414
	aOperation = iFreeHeadSupOp;						
sl@0
   415
	iFreeHeadSupOp = aOperation->iNext;
sl@0
   416
	aOperation->iNext = aOperation->iPrev = NULL;
sl@0
   417
sl@0
   418
	iCacheLock.Signal();
sl@0
   419
	return KErrNone;
sl@0
   420
	}	
sl@0
   421
sl@0
   422
void RequestAllocator::FreeOperation(TMsgOperation* aOperation)
sl@0
   423
//
sl@0
   424
// free Operation
sl@0
   425
//
sl@0
   426
	{
sl@0
   427
	if(aOperation->iIsAllocated)
sl@0
   428
		{
sl@0
   429
		__CACHE_PRINT(_L("RequestAllocator::FreeOperation() Allocated subop"));
sl@0
   430
		delete(aOperation);
sl@0
   431
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   432
		iAllocated--;
sl@0
   433
#endif
sl@0
   434
		return;
sl@0
   435
		}
sl@0
   436
	
sl@0
   437
	__CACHE_PRINT(_L("RequestAllocator::FreeOperation() returning to free list"));
sl@0
   438
	iCacheLock.Wait();
sl@0
   439
	aOperation->iNext = iFreeHeadSupOp;	// NB backward link only used when request in in use
sl@0
   440
	iFreeHeadSupOp = aOperation;
sl@0
   441
sl@0
   442
	iCacheLock.Signal();
sl@0
   443
	}
sl@0
   444
sl@0
   445
sl@0
   446
CFsRequest::CFsRequest()
sl@0
   447
//
sl@0
   448
//
sl@0
   449
//
sl@0
   450
	: iOperation(NULL),iDriveNumber(KDriveInvalid)
sl@0
   451
	{}
sl@0
   452
sl@0
   453
CFsRequest::~CFsRequest()
sl@0
   454
//
sl@0
   455
//
sl@0
   456
//
sl@0
   457
	{}
sl@0
   458
sl@0
   459
void CFsRequest::Set(const TOperation& aOperation,CSessionFs* aSession)
sl@0
   460
//
sl@0
   461
//
sl@0
   462
//
sl@0
   463
	{
sl@0
   464
sl@0
   465
	SetState(EReqStateInitialise);
sl@0
   466
sl@0
   467
	iOperation     = const_cast<TOperation*>(&aOperation);
sl@0
   468
	iSession       = aSession;
sl@0
   469
	iIsCompleted   = aOperation.IsCompleted();
sl@0
   470
	iError         = KErrNone;
sl@0
   471
	iDriveNumber   = KDriveInvalid;
sl@0
   472
	iCurrentPlugin = NULL;
sl@0
   473
	iOwnerPlugin   = NULL;
sl@0
   474
	iDirectToDrive = EFalse;
sl@0
   475
	iClientThreadId= 0;
sl@0
   476
	iFlags &= ~(EFreeChanged | EPostInterceptEnabled | EPostOperation | EFsObjectOpen);
sl@0
   477
	iScratchValue = 0;
sl@0
   478
	}
sl@0
   479
sl@0
   480
void CFsRequest::Set(CSessionFs* aSession)
sl@0
   481
//
sl@0
   482
//
sl@0
   483
//
sl@0
   484
	{
sl@0
   485
	__ASSERT_DEBUG(iOperation,Fault(EBaseRequestSet1));
sl@0
   486
sl@0
   487
	SetState(EReqStateInitialise);
sl@0
   488
sl@0
   489
	iSession       = aSession;
sl@0
   490
	iIsCompleted   = iOperation->IsCompleted();
sl@0
   491
	iError         = KErrNone;
sl@0
   492
	iDriveNumber   = KDriveInvalid;
sl@0
   493
	iCurrentPlugin = NULL;
sl@0
   494
	iOwnerPlugin   = NULL;
sl@0
   495
	iDirectToDrive = EFalse;
sl@0
   496
	iClientThreadId= 0;
sl@0
   497
	iFlags &= ~(EFreeChanged | EPostInterceptEnabled | EPostOperation | EFsObjectOpen);
sl@0
   498
	iScratchValue = 0;
sl@0
   499
	}
sl@0
   500
sl@0
   501
sl@0
   502
TParse& CFsRequest::Src()
sl@0
   503
//
sl@0
   504
//
sl@0
   505
//
sl@0
   506
	{
sl@0
   507
	Fault(EBaseRequestSrc);
sl@0
   508
	return(dummyP);
sl@0
   509
	}
sl@0
   510
sl@0
   511
TParse& CFsRequest::Dest()
sl@0
   512
//
sl@0
   513
//
sl@0
   514
//
sl@0
   515
	{
sl@0
   516
	Fault(EBaseRequestDest);
sl@0
   517
	return(dummyP);
sl@0
   518
	}
sl@0
   519
sl@0
   520
TDrive* CFsRequest::Drive()
sl@0
   521
//
sl@0
   522
//
sl@0
   523
//
sl@0
   524
	{
sl@0
   525
	Fault(EBaseRequestDrive);
sl@0
   526
	return(NULL);
sl@0
   527
	}
sl@0
   528
sl@0
   529
TDrive* CFsRequest::SubstedDrive()
sl@0
   530
//
sl@0
   531
//
sl@0
   532
//
sl@0
   533
	{
sl@0
   534
	Fault(EBaseRequestSubstedDrive);
sl@0
   535
	return(NULL);
sl@0
   536
	}
sl@0
   537
sl@0
   538
void CFsRequest::SetDrive(TDrive* /*aDrive*/)
sl@0
   539
//
sl@0
   540
//
sl@0
   541
//
sl@0
   542
	{
sl@0
   543
	Fault(EBaseRequestSetDrive);
sl@0
   544
	}
sl@0
   545
sl@0
   546
void CFsRequest::SetSubstedDrive(TDrive* /*aDrive*/)
sl@0
   547
//
sl@0
   548
//
sl@0
   549
//
sl@0
   550
	{
sl@0
   551
	Fault(EBaseRequestSetSubstedDrive);
sl@0
   552
	}
sl@0
   553
sl@0
   554
TInt CFsRequest::GetSlot(TFsPluginRequest::TF32ArgType aType)
sl@0
   555
	{
sl@0
   556
	if(iOperation->Arg(0) == aType) return 0;
sl@0
   557
	if(iOperation->Arg(1) == aType) return 1;
sl@0
   558
	if(iOperation->Arg(2) == aType) return 2;
sl@0
   559
	if(iOperation->Arg(3) == aType) return 3;
sl@0
   560
	
sl@0
   561
	return(-1);
sl@0
   562
	}
sl@0
   563
sl@0
   564
sl@0
   565
TBool CFsMessageRequest::IsNotifierSpecific() const
sl@0
   566
	{
sl@0
   567
#ifndef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
   568
	return EFalse;
sl@0
   569
#else
sl@0
   570
	TInt function = iOperation->iFunction;
sl@0
   571
	return(	function == EFsNotificationAdd      || 
sl@0
   572
			function == EFsNotificationBuffer ||
sl@0
   573
			function == EFsNotificationCancel ||
sl@0
   574
			function == EFsNotificationOpen ||
sl@0
   575
			function == EFsNotificationRemove ||
sl@0
   576
			function == EFsNotificationRequest ||
sl@0
   577
			function == EFsNotificationSubClose);
sl@0
   578
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
   579
	}
sl@0
   580
sl@0
   581
sl@0
   582
TBool CFsMessageRequest::IsNotifierSupported() const
sl@0
   583
	{
sl@0
   584
#ifndef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
   585
	return EFalse;
sl@0
   586
#else
sl@0
   587
	TInt function = iOperation->iFunction;
sl@0
   588
	return(	function == EFsDelete || 
sl@0
   589
			function == EFsRmDir || 
sl@0
   590
			function == EFsMkDir || 
sl@0
   591
			function == EFsFormatNext || 
sl@0
   592
			function == EFsFileCreate ||
sl@0
   593
			function == EFsFileReplace ||
sl@0
   594
			function == EFsFileRename ||
sl@0
   595
			function == EFsRename ||
sl@0
   596
			function == EFsReplace ||
sl@0
   597
			function == EFsSetDriveName ||
sl@0
   598
			function == EFsSetVolume ||
sl@0
   599
			function == EFsSetEntry ||
sl@0
   600
			function == EFsFileSetAtt ||
sl@0
   601
			function == EFsFileSet ||
sl@0
   602
			function == EFsMountFileSystem ||
sl@0
   603
			function == EFsDismountFileSystem ||
sl@0
   604
			function == EFsFileSetSize ||
sl@0
   605
			function == EFsFileWrite ||
sl@0
   606
			function == EFsFileWriteDirty ||
sl@0
   607
			function == EFsRawDiskWrite ||
sl@0
   608
			function == EFsMountFileSystemScan);
sl@0
   609
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
   610
	}
sl@0
   611
sl@0
   612
sl@0
   613
TInt CFsRequest::Read(TFsPluginRequest::TF32ArgType aType, TInt& aVal)
sl@0
   614
	{
sl@0
   615
	if(iOperation->Arg(0) == aType) { aVal = Message().Int0(); return KErrNone; }
sl@0
   616
	if(iOperation->Arg(1) == aType) { aVal = Message().Int1(); return KErrNone; }
sl@0
   617
	if(iOperation->Arg(2) == aType) { aVal = Message().Int2(); return KErrNone; }
sl@0
   618
	if(iOperation->Arg(3) == aType) { aVal = Message().Int3(); return KErrNone; }
sl@0
   619
	
sl@0
   620
	return KErrNotSupported;
sl@0
   621
	}
sl@0
   622
sl@0
   623
sl@0
   624
TInt CFsRequest::Read(TFsPluginRequest::TF32ArgType aType, TUint& aVal)
sl@0
   625
	{
sl@0
   626
	if(iOperation->Arg(0) == aType) { aVal = (TUint)Message().Int0(); return KErrNone; }
sl@0
   627
	if(iOperation->Arg(1) == aType) { aVal = (TUint)Message().Int1(); return KErrNone; }
sl@0
   628
	if(iOperation->Arg(2) == aType) { aVal = (TUint)Message().Int2(); return KErrNone; }
sl@0
   629
	if(iOperation->Arg(3) == aType) { aVal = (TUint)Message().Int3(); return KErrNone; }
sl@0
   630
	
sl@0
   631
	return KErrNotSupported;
sl@0
   632
	}
sl@0
   633
sl@0
   634
TInt CFsRequest::Read(TFsPluginRequest::TF32ArgType aType, TInt64& aVal)
sl@0
   635
	{
sl@0
   636
	TPckg<TInt64> pkVal(aVal);
sl@0
   637
	// EFsFileLock, EFsFileUnLock, EFsFileSeek and EFsFileSetSize need special treatment
sl@0
   638
	if(iOperation->Arg(0) == aType)
sl@0
   639
		{
sl@0
   640
		if((iOperation->Function()==EFsFileLock)   ||
sl@0
   641
		   (iOperation->Function()==EFsFileUnLock)   )
sl@0
   642
			{
sl@0
   643
			if(IsDescData(KMsgPtr0))
sl@0
   644
				Read(KMsgPtr0,pkVal);
sl@0
   645
			else
sl@0
   646
				aVal = MAKE_TINT64(0, Message().Int0());	// Position is unsigned value
sl@0
   647
			return KErrNone;
sl@0
   648
			}
sl@0
   649
		
sl@0
   650
		if((iOperation->Function()==EFsFileSeek)    ||		// Seek offset (input paramater)
sl@0
   651
		   (iOperation->Function()==EFsFileSize)    ||		// Size (output paramater)
sl@0
   652
		   (iOperation->Function()==EFsFileSetSize)   )		// Size to be set (input paramater)
sl@0
   653
			{
sl@0
   654
			if(IsDescData(KMsgPtr0))
sl@0
   655
				Read(KMsgPtr0,pkVal);
sl@0
   656
			else
sl@0
   657
				aVal = Message().Int0();	// Seek offset / Size is signed value
sl@0
   658
			return KErrNone;
sl@0
   659
			}
sl@0
   660
		
sl@0
   661
		aVal = Message().Int0();
sl@0
   662
		return KErrNone; 
sl@0
   663
		}
sl@0
   664
	
sl@0
   665
	// EFsFileLock and EFsFileUnLock need special treatment
sl@0
   666
	if(iOperation->Arg(1) == aType) 
sl@0
   667
		{
sl@0
   668
		if((iOperation->Function()==EFsFileLock)   ||
sl@0
   669
		   (iOperation->Function()==EFsFileUnLock)   )
sl@0
   670
			{
sl@0
   671
			if(IsDescData(KMsgPtr1))
sl@0
   672
				Read(KMsgPtr1,pkVal);
sl@0
   673
			else
sl@0
   674
				aVal = MAKE_TINT64(0, Message().Int1());	// Length is unsigned value
sl@0
   675
			return KErrNone; 
sl@0
   676
			}
sl@0
   677
		
sl@0
   678
		aVal = Message().Int1();
sl@0
   679
		return KErrNone; 
sl@0
   680
		}
sl@0
   681
	
sl@0
   682
	// EFsFileRead, EFsFileWrite, EFsFileSeek and EFsReadFileSection need special treatment
sl@0
   683
	if(iOperation->Arg(2) == aType) 
sl@0
   684
		{
sl@0
   685
		if((iOperation->Function()==EFsFileRead)  ||
sl@0
   686
		   (iOperation->Function()==EFsFileWrite)   )
sl@0
   687
			{
sl@0
   688
			if(IsDescData(KMsgPtr2))
sl@0
   689
				Read(KMsgPtr2,pkVal);
sl@0
   690
			else
sl@0
   691
				{
sl@0
   692
				if(Message().Int2() == (TInt)I64LOW(KCurrentPosition64))
sl@0
   693
					aVal = KCurrentPosition64;				// Position is KCurrentPosition64 (-1)
sl@0
   694
				else
sl@0
   695
					aVal = MAKE_TINT64(0,Message().Int2());	// Position is unsigned value
sl@0
   696
				}
sl@0
   697
			return KErrNone; 
sl@0
   698
			}
sl@0
   699
		
sl@0
   700
		if(iOperation->Function()==EFsFileSeek)
sl@0
   701
			{
sl@0
   702
			if(IsDescData(KMsgPtr2))
sl@0
   703
				Read(KMsgPtr2,pkVal);
sl@0
   704
			else
sl@0
   705
				aVal = Message().Int2();	// New position is signed value
sl@0
   706
			return KErrNone;
sl@0
   707
			}
sl@0
   708
		
sl@0
   709
		if(iOperation->Function()==EFsReadFileSection)
sl@0
   710
			{
sl@0
   711
			if(IsDescData(KMsgPtr2))
sl@0
   712
			Read(KMsgPtr2,pkVal);
sl@0
   713
			else
sl@0
   714
			aVal = MAKE_TINT64(0,Message().Int2()); // Position is unsigned value
sl@0
   715
			return KErrNone;
sl@0
   716
			}
sl@0
   717
		
sl@0
   718
		aVal = Message().Int2();		
sl@0
   719
		return KErrNone; 
sl@0
   720
		}
sl@0
   721
	
sl@0
   722
	if(iOperation->Arg(3) == aType) 
sl@0
   723
		{
sl@0
   724
		aVal = Message().Int3();
sl@0
   725
		return KErrNone;
sl@0
   726
		}
sl@0
   727
	
sl@0
   728
	return KErrNotSupported;
sl@0
   729
	}
sl@0
   730
sl@0
   731
void CFsRequest::SetAndOpenScratchValue(const TInt64& aValue)
sl@0
   732
	{
sl@0
   733
	if (IsFsObjectOpen())
sl@0
   734
		{
sl@0
   735
		((CFsDispatchObject*) I64LOW(iScratchValue))->Close();
sl@0
   736
		SetFsObjectOpen(EFalse);
sl@0
   737
		}
sl@0
   738
	if (I64LOW(aValue) && iOperation && (iOperation->iFlags & EFileShare))
sl@0
   739
		{
sl@0
   740
		((CFsDispatchObject*) I64LOW(aValue))->Open();
sl@0
   741
		SetFsObjectOpen(ETrue);
sl@0
   742
		}
sl@0
   743
	iScratchValue = aValue;
sl@0
   744
	}
sl@0
   745
sl@0
   746
sl@0
   747
TInt CFsRequest::Read(TFsPluginRequest::TF32ArgType aType, TDes8& aDes, TInt aOffset)
sl@0
   748
	{
sl@0
   749
	TInt slot = GetSlot(aType);
sl@0
   750
	if(slot >= 0)
sl@0
   751
		return Read(slot, aDes, aOffset);
sl@0
   752
	return KErrNotSupported;
sl@0
   753
	}
sl@0
   754
sl@0
   755
sl@0
   756
TInt CFsRequest::Read(TFsPluginRequest::TF32ArgType aType, TDes16& aDes, TInt aOffset)
sl@0
   757
	{
sl@0
   758
	TInt slot = GetSlot(aType);
sl@0
   759
	if(slot >= 0)
sl@0
   760
		return Read(slot, aDes, aOffset);
sl@0
   761
	return KErrNotSupported;
sl@0
   762
	}
sl@0
   763
sl@0
   764
sl@0
   765
TInt CFsRequest::Write(TFsPluginRequest::TF32ArgType aType, const TDesC8& aDes, TInt aOffset)
sl@0
   766
	{
sl@0
   767
	TInt slot = GetSlot(aType);
sl@0
   768
	if(slot >= 0)
sl@0
   769
		return Write(slot, aDes, aOffset);
sl@0
   770
	return KErrNotSupported;
sl@0
   771
	}
sl@0
   772
sl@0
   773
sl@0
   774
TInt CFsRequest::Write(TFsPluginRequest::TF32ArgType aType, const TDesC16& aDes, TInt aOffset)
sl@0
   775
	{
sl@0
   776
	TInt slot = GetSlot(aType);
sl@0
   777
	if(slot >= 0)
sl@0
   778
		return Write(slot, aDes, aOffset);
sl@0
   779
	return KErrNotSupported;
sl@0
   780
	}
sl@0
   781
sl@0
   782
sl@0
   783
TInt CFsRequest::Read(const TInt aMsgPtr,TDes8 &aDes)
sl@0
   784
	{
sl@0
   785
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   786
		{
sl@0
   787
		TDesC8* pDes = (TDesC8*) ((const RLocalMessage*) &Message())->Arg(aMsgPtr);
sl@0
   788
		if (aDes.MaxLength() < pDes->Length())
sl@0
   789
			return KErrTooBig;
sl@0
   790
		aDes.Copy(*pDes);
sl@0
   791
		return KErrNone;
sl@0
   792
		}
sl@0
   793
sl@0
   794
	return Message().Read(aMsgPtr,aDes,0);
sl@0
   795
	}
sl@0
   796
sl@0
   797
sl@0
   798
TInt CFsRequest::Read(const TInt aMsgPtr,TDes8 &aDes,TInt anOffset)
sl@0
   799
	{
sl@0
   800
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   801
		{
sl@0
   802
		TDesC8* pDes = (TDesC8*) ((const RLocalMessage*) &Message())->Arg(aMsgPtr);
sl@0
   803
		if (aDes.MaxLength() < pDes->Length() + anOffset)
sl@0
   804
			return KErrTooBig;
sl@0
   805
		aDes.SetLength(pDes->Length() + anOffset);
sl@0
   806
		aDes.MidTPtr(anOffset).Copy(*pDes);
sl@0
   807
		return KErrNone;
sl@0
   808
		}
sl@0
   809
sl@0
   810
	return Message().Read(aMsgPtr,aDes,anOffset);
sl@0
   811
	}
sl@0
   812
sl@0
   813
sl@0
   814
TInt CFsRequest::Read(const TInt aMsgPtr,TDes16 &aDes)
sl@0
   815
	{
sl@0
   816
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   817
		{
sl@0
   818
		TDesC16* pDes = (TDesC16*) ((const RLocalMessage*) &Message())->Arg(aMsgPtr);
sl@0
   819
		if (aDes.MaxLength() < pDes->Length())
sl@0
   820
			return KErrTooBig;
sl@0
   821
		aDes.Copy(*pDes);
sl@0
   822
		return KErrNone;
sl@0
   823
		}
sl@0
   824
sl@0
   825
	return Message().Read(aMsgPtr,aDes,0);
sl@0
   826
	}
sl@0
   827
sl@0
   828
sl@0
   829
TInt CFsRequest::Read(const TInt aMsgPtr,TDes16 &aDes,TInt anOffset)
sl@0
   830
	{
sl@0
   831
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   832
		{
sl@0
   833
		TDesC16* pDes = (TDesC16*) ((const RLocalMessage*) &Message())->Arg(aMsgPtr);
sl@0
   834
		if (aDes.MaxLength() < pDes->Length() + anOffset)
sl@0
   835
			return KErrTooBig;
sl@0
   836
		aDes.SetLength(pDes->Length() + anOffset);
sl@0
   837
		aDes.MidTPtr(anOffset).Copy(*pDes);
sl@0
   838
		return KErrNone;
sl@0
   839
		}
sl@0
   840
sl@0
   841
	return Message().Read(aMsgPtr,aDes,anOffset);
sl@0
   842
	}
sl@0
   843
sl@0
   844
sl@0
   845
TInt CFsRequest::Write(const TInt aMsgNum,const TDesC8 &aDes)
sl@0
   846
	{
sl@0
   847
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   848
		{
sl@0
   849
		TDes8* pDes = (TDes8*) ((const RLocalMessage*) &Message())->Arg(aMsgNum);
sl@0
   850
		if (pDes->MaxLength() < aDes.Length())
sl@0
   851
			return KErrTooBig;
sl@0
   852
		pDes->Copy(aDes);
sl@0
   853
		return KErrNone;
sl@0
   854
		}
sl@0
   855
sl@0
   856
	return Message().Write(aMsgNum,aDes,0);
sl@0
   857
	}
sl@0
   858
sl@0
   859
sl@0
   860
TInt CFsRequest::Write(const TInt aMsgNum,const TDesC8 &aDes,TInt anOffset)
sl@0
   861
	{
sl@0
   862
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   863
		{
sl@0
   864
		TDes8* pDes = (TDes8*) ((const RLocalMessage*) &Message())->Arg(aMsgNum);
sl@0
   865
		if (pDes->MaxLength() < aDes.Length() + anOffset)
sl@0
   866
			return KErrTooBig;
sl@0
   867
		pDes->SetLength(aDes.Length() + anOffset);
sl@0
   868
		pDes->MidTPtr(anOffset).Copy(aDes);
sl@0
   869
		return KErrNone;
sl@0
   870
		}
sl@0
   871
sl@0
   872
	return Message().Write(aMsgNum,aDes,anOffset);
sl@0
   873
	}
sl@0
   874
sl@0
   875
sl@0
   876
TInt CFsRequest::Write(const TInt aMsgNum,const TDesC16 &aDes)
sl@0
   877
	{
sl@0
   878
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   879
		{
sl@0
   880
		TDes16* pDes = (TDes16*) ((const RLocalMessage*) &Message())->Arg(aMsgNum);
sl@0
   881
		if (pDes->MaxLength() < aDes.Length())
sl@0
   882
			return KErrTooBig;
sl@0
   883
		pDes->Copy(aDes);
sl@0
   884
		return KErrNone;
sl@0
   885
		}
sl@0
   886
sl@0
   887
	return Message().Write(aMsgNum,aDes,0);
sl@0
   888
	}
sl@0
   889
sl@0
   890
sl@0
   891
TInt CFsRequest::Write(const TInt aMsgNum,const TDesC16 &aDes,TInt anOffset)
sl@0
   892
	{
sl@0
   893
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   894
		{
sl@0
   895
		TDes16* pDes = (TDes16*) ((const RLocalMessage*) &Message())->Arg(aMsgNum);
sl@0
   896
		if (pDes->MaxLength() < aDes.Length() + anOffset)
sl@0
   897
			return KErrTooBig;
sl@0
   898
		pDes->SetLength(aDes.Length() + anOffset);
sl@0
   899
		pDes->MidTPtr(anOffset).Copy(aDes);
sl@0
   900
		return KErrNone;
sl@0
   901
		}
sl@0
   902
sl@0
   903
	return Message().Write(aMsgNum,aDes,anOffset);
sl@0
   904
	}
sl@0
   905
sl@0
   906
sl@0
   907
void CFsRequest::ReadL(const TInt aMsgPtr,TDes8 &aDes)
sl@0
   908
	{ User::LeaveIfError(Read(aMsgPtr,aDes)); }
sl@0
   909
sl@0
   910
void CFsRequest::ReadL(const TInt aMsgPtr,TDes8 &aDes,TInt anOffset)
sl@0
   911
	{ User::LeaveIfError(Read(aMsgPtr,aDes,anOffset)); }
sl@0
   912
sl@0
   913
void CFsRequest::ReadL(const TInt aMsgPtr,TDes16 &aDes)
sl@0
   914
	{ User::LeaveIfError(Read(aMsgPtr,aDes)); }
sl@0
   915
sl@0
   916
void CFsRequest::ReadL(const TInt aMsgPtr,TDes16 &aDes,TInt anOffset)
sl@0
   917
	{ User::LeaveIfError(Read(aMsgPtr,aDes,anOffset)); }
sl@0
   918
sl@0
   919
void CFsRequest::WriteL(const TInt aMsgNum,const TDesC8 &aDes)
sl@0
   920
	{ User::LeaveIfError(Write(aMsgNum,aDes)); }
sl@0
   921
sl@0
   922
void CFsRequest::WriteL(const TInt aMsgNum,const TDesC8 &aDes,TInt anOffset)
sl@0
   923
	{ User::LeaveIfError(Write(aMsgNum,aDes,anOffset)); }
sl@0
   924
sl@0
   925
void CFsRequest::WriteL(const TInt aMsgNum,const TDesC16 &aDes)
sl@0
   926
	{ User::LeaveIfError(Write(aMsgNum,aDes)); }
sl@0
   927
sl@0
   928
void CFsRequest::WriteL(const TInt aMsgNum,const TDesC16 &aDes,TInt anOffset)
sl@0
   929
	{ User::LeaveIfError(Write(aMsgNum,aDes,anOffset)); }
sl@0
   930
sl@0
   931
sl@0
   932
/**
sl@0
   933
    @param  aMsgNum message argument index 
sl@0
   934
    @return client side descriptor length 
sl@0
   935
*/
sl@0
   936
TInt CFsRequest::GetDesLength(const TInt aMsgNum)
sl@0
   937
	{
sl@0
   938
	if (Message().Handle() == KLocalMessageHandle)
sl@0
   939
		{
sl@0
   940
		TDes8* pDes = (TDes8*) ((const RLocalMessage*) &Message())->Arg(aMsgNum);
sl@0
   941
		return pDes->Length();
sl@0
   942
		}
sl@0
   943
	else
sl@0
   944
		{
sl@0
   945
		return Message().GetDesLength(aMsgNum);
sl@0
   946
		}
sl@0
   947
	}
sl@0
   948
sl@0
   949
const RMessage2& CFsRequest::Message()
sl@0
   950
//
sl@0
   951
//
sl@0
   952
//
sl@0
   953
	{
sl@0
   954
	Fault(EBaseRequestMessage);
sl@0
   955
	return(dummyM);
sl@0
   956
	}
sl@0
   957
sl@0
   958
sl@0
   959
sl@0
   960
void CFsMessageRequest::Set(const RMessage2& aMessage,CSessionFs* aSession)
sl@0
   961
//
sl@0
   962
// For reuseable request
sl@0
   963
//
sl@0
   964
	{
sl@0
   965
	iMessage=aMessage;
sl@0
   966
	iDrive=NULL;
sl@0
   967
	iSubstedDrive=NULL;
sl@0
   968
	CFsRequest::Set(aSession);
sl@0
   969
	SetFreeChanged(EFalse);
sl@0
   970
	EnablePostIntercept(ETrue);
sl@0
   971
	}
sl@0
   972
sl@0
   973
	
sl@0
   974
void CFsMessageRequest::Set(const RMessage2& aMessage,const TOperation& aOperation,CSessionFs* aSession)
sl@0
   975
//
sl@0
   976
//
sl@0
   977
//
sl@0
   978
	{
sl@0
   979
	iCurrentPlugin=NULL;
sl@0
   980
	iMessage=aMessage;
sl@0
   981
	iDrive=NULL;
sl@0
   982
	iSubstedDrive=NULL;
sl@0
   983
	CFsRequest::Set(aOperation,aSession);
sl@0
   984
	SetFreeChanged(EFalse);
sl@0
   985
	EnablePostIntercept(ETrue);
sl@0
   986
	}
sl@0
   987
sl@0
   988
void CFsMessageRequest::Set(const TOperation& aOperation)
sl@0
   989
	{
sl@0
   990
	iOperation=const_cast<TOperation*>(&aOperation);
sl@0
   991
	}
sl@0
   992
sl@0
   993
void CFsMessageRequest::Process()
sl@0
   994
//
sl@0
   995
// Process the request - (passing to a plugin or a drive thread)
sl@0
   996
//
sl@0
   997
	{
sl@0
   998
	__THRD_PRINT3(_L("CFsMessageRequest::Process() req %08x state %d plugin 0x%x"), this, iReqState, iCurrentPlugin);
sl@0
   999
	
sl@0
  1000
	// initialise request - if not initialised already
sl@0
  1001
	if (iReqState == EReqStateInitialise)
sl@0
  1002
		{
sl@0
  1003
		TInt r = DoInitialise();
sl@0
  1004
		if (r == EReqActionComplete)
sl@0
  1005
			{
sl@0
  1006
			return;
sl@0
  1007
			}
sl@0
  1008
		else if (r == EReqActionBusy)	// request postponed ?
sl@0
  1009
			{
sl@0
  1010
			SetState(EReqStateInitialise);
sl@0
  1011
			Dispatch(EFalse);
sl@0
  1012
			return;
sl@0
  1013
			}
sl@0
  1014
		else if (r == KErrNone && iCurrentPlugin)		// dispatch to plugin thread ?
sl@0
  1015
			{
sl@0
  1016
			Dispatch(EFalse);
sl@0
  1017
			return;
sl@0
  1018
			}
sl@0
  1019
		}
sl@0
  1020
sl@0
  1021
	if(iCurrentPlugin)
sl@0
  1022
		{
sl@0
  1023
		if (IsPostOperation())
sl@0
  1024
			{
sl@0
  1025
			ProcessPostOperation();
sl@0
  1026
			return;
sl@0
  1027
			}
sl@0
  1028
			
sl@0
  1029
		if(!IsPluginSpecific())
sl@0
  1030
			{
sl@0
  1031
			ProcessPreOperation();
sl@0
  1032
			return;
sl@0
  1033
			}
sl@0
  1034
		}
sl@0
  1035
sl@0
  1036
	
sl@0
  1037
	// Is there a PostInitialise function ?
sl@0
  1038
	if (iReqState == EReqStatePostInitialise)
sl@0
  1039
		{
sl@0
  1040
		TInt r = PostInitialise();
sl@0
  1041
		if (r == EReqActionComplete)
sl@0
  1042
			{
sl@0
  1043
			return;
sl@0
  1044
			}
sl@0
  1045
		else if (r == EReqActionBusy)	// request postponed ?
sl@0
  1046
			{
sl@0
  1047
			SetState(EReqStatePostInitialise);
sl@0
  1048
			Dispatch(EFalse);
sl@0
  1049
			return;
sl@0
  1050
			}
sl@0
  1051
		}
sl@0
  1052
sl@0
  1053
	ProcessDriveOperation();
sl@0
  1054
	}
sl@0
  1055
	
sl@0
  1056
void CFsMessageRequest::ProcessPostOperation()
sl@0
  1057
//
sl@0
  1058
// Process the message in post operation mode (handled by the current plugin)
sl@0
  1059
//
sl@0
  1060
	{
sl@0
  1061
	TInt err = KErrNone;
sl@0
  1062
	if(!iCurrentPlugin->IsPluginThread(*this))
sl@0
  1063
		{
sl@0
  1064
		// The request hasn't come from this plugin so it's safe to dispatch		
sl@0
  1065
		TFsPluginRequest request(this);
sl@0
  1066
		TRAPD(leaveValue, err = iCurrentPlugin->DoRequestL(request));
sl@0
  1067
		if(leaveValue != KErrNone)
sl@0
  1068
			{
sl@0
  1069
			Panic(KFsClient,leaveValue);
sl@0
  1070
			if(iOperation->IsOpenSubSess())		
sl@0
  1071
				RequestAllocator::OpenSubFailed(Session());
sl@0
  1072
			Free();
sl@0
  1073
			return;
sl@0
  1074
			}
sl@0
  1075
sl@0
  1076
		if(!IsExpectedResult(err))
sl@0
  1077
			{
sl@0
  1078
			Complete(err);
sl@0
  1079
			return;
sl@0
  1080
			}
sl@0
  1081
		}
sl@0
  1082
	
sl@0
  1083
	// Find the previous plugin in the chain and dispatch
sl@0
  1084
	//  - If no more plugins are interested in this message, then complete
sl@0
  1085
	FsPluginManager::PrevPlugin(iCurrentPlugin, this, ETrue);
sl@0
  1086
	if(iCurrentPlugin == NULL)
sl@0
  1087
		{
sl@0
  1088
		Complete(GetError());
sl@0
  1089
		return;
sl@0
  1090
		}
sl@0
  1091
sl@0
  1092
	Dispatch();
sl@0
  1093
	return;
sl@0
  1094
	}
sl@0
  1095
	
sl@0
  1096
sl@0
  1097
void CFsMessageRequest::ProcessPreOperation()
sl@0
  1098
//
sl@0
  1099
// Process the message in pre operation mode (handled by the current plugin)
sl@0
  1100
//
sl@0
  1101
	{
sl@0
  1102
	TInt err = KErrNone;
sl@0
  1103
	if(!iCurrentPlugin->IsPluginThread(*this))
sl@0
  1104
		{
sl@0
  1105
		// The request hasn't come from this plugin so it's safe to dispatch		
sl@0
  1106
		TFsPluginRequest request(this);		
sl@0
  1107
		TRAPD(leaveValue, err = iCurrentPlugin->DoRequestL(request));
sl@0
  1108
		__PLUGIN_PRINT1(_L("PLUGIN: CFsMessageRequest:: %x processed by plugin"), this);
sl@0
  1109
sl@0
  1110
		if((iOperation->Function() == EFsDismountPlugin) && (err !=  KErrPermissionDenied))
sl@0
  1111
			{
sl@0
  1112
			TRAP(leaveValue, err = iOperation->DoRequestL(this));
sl@0
  1113
			}
sl@0
  1114
sl@0
  1115
		if(leaveValue != KErrNone)
sl@0
  1116
			{
sl@0
  1117
			Panic(KFsClient,leaveValue);
sl@0
  1118
			if(iOperation->IsOpenSubSess())		//this should be close subsession
sl@0
  1119
				RequestAllocator::OpenSubFailed(Session());	//need a close subsession fail
sl@0
  1120
			Free();
sl@0
  1121
			return;
sl@0
  1122
			}
sl@0
  1123
		}
sl@0
  1124
sl@0
  1125
	if(err == KErrNone)
sl@0
  1126
		{
sl@0
  1127
		// Find the next plugin in the chain and dispatch
sl@0
  1128
		//  - If no more plugins are interested in this message, 
sl@0
  1129
		//	  then Dispatch() will process the request in drive/main thread context.
sl@0
  1130
		FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1131
		if(iCurrentPlugin && IsPostOperation())
sl@0
  1132
			SetPostOperation(EFalse);
sl@0
  1133
		Dispatch();
sl@0
  1134
		return;
sl@0
  1135
		}
sl@0
  1136
	// KErrCompletion may be returned by the plugin to 
sl@0
  1137
	// indicate that it has process the message itself (do post-intercept)
sl@0
  1138
	else if (err == KErrCompletion)
sl@0
  1139
		{
sl@0
  1140
		// Find the previous plugin in the chain and dispatch
sl@0
  1141
		//  - If no more plugins are interested in this message, then complete
sl@0
  1142
		FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1143
		if(iCurrentPlugin != NULL)
sl@0
  1144
			{
sl@0
  1145
			SetPostOperation(ETrue);
sl@0
  1146
			err = KErrNone;
sl@0
  1147
			Dispatch();
sl@0
  1148
			return;
sl@0
  1149
			}
sl@0
  1150
		else
sl@0
  1151
			{
sl@0
  1152
			err = KErrNone;	
sl@0
  1153
			}
sl@0
  1154
		}
sl@0
  1155
		
sl@0
  1156
	Complete(err);
sl@0
  1157
	return;
sl@0
  1158
	}
sl@0
  1159
sl@0
  1160
sl@0
  1161
void CFsMessageRequest::ProcessDriveOperation()
sl@0
  1162
//
sl@0
  1163
// Process the message in drive (or main thread) context
sl@0
  1164
//
sl@0
  1165
	{
sl@0
  1166
sl@0
  1167
	// A new request is to be processed - kick off the inactivity/finalisation timer...
sl@0
  1168
	FsThreadManager::StartFinalisationTimer(iDriveNumber);
sl@0
  1169
sl@0
  1170
	TInt err = KErrNone;
sl@0
  1171
	
sl@0
  1172
	TRAPD(leaveValue, err = iOperation->DoRequestL(this));
sl@0
  1173
sl@0
  1174
	// Cancel hung state if a request from the drive thread has finished
sl@0
  1175
	FsThreadManager::SetDriveHung(DriveNumber(), EFalse);
sl@0
  1176
sl@0
  1177
	if(leaveValue != KErrNone)
sl@0
  1178
		{
sl@0
  1179
		Panic(KFsClient,leaveValue);
sl@0
  1180
		if(iOperation->IsOpenSubSess()) 
sl@0
  1181
			RequestAllocator::OpenSubFailed(Session());
sl@0
  1182
		Free();
sl@0
  1183
		return;
sl@0
  1184
		}
sl@0
  1185
		
sl@0
  1186
	// request postponed ? (e.g. if a page used by file cache is busy,
sl@0
  1187
	// or because of fair scheduling).
sl@0
  1188
	if (err == EReqActionBusy)
sl@0
  1189
		{
sl@0
  1190
		Dispatch();
sl@0
  1191
		return;
sl@0
  1192
		}
sl@0
  1193
sl@0
  1194
	iLastError = err;
sl@0
  1195
sl@0
  1196
	if(!IsExpectedResult(err) || IsPluginSpecific())
sl@0
  1197
		{
sl@0
  1198
		// no need to call DoNotify here since that requires err==KErrNone
sl@0
  1199
		Complete(err);
sl@0
  1200
		return;
sl@0
  1201
		}
sl@0
  1202
sl@0
  1203
	SetError(err);
sl@0
  1204
sl@0
  1205
sl@0
  1206
	// Start issuing the post-operation requests starting from the bottom of the chain
sl@0
  1207
	iCurrentPlugin = NULL;
sl@0
  1208
	if (PostInterceptEnabled())
sl@0
  1209
		{
sl@0
  1210
		FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1211
		if(iCurrentPlugin && !iCurrentPlugin->IsPluginThread(*this))
sl@0
  1212
			{
sl@0
  1213
			SetPostOperation(ETrue);
sl@0
  1214
			if (DispatchToPlugin())
sl@0
  1215
				return;
sl@0
  1216
			}
sl@0
  1217
		}		
sl@0
  1218
sl@0
  1219
	Complete(GetError());
sl@0
  1220
	return;
sl@0
  1221
	}
sl@0
  1222
sl@0
  1223
void CFsMessageRequest::Complete(TInt aError)
sl@0
  1224
//
sl@0
  1225
//
sl@0
  1226
//
sl@0
  1227
	{
sl@0
  1228
	__THRD_PRINT2(_L("----- CFsMessageRequest::Complete() req %08x with %d"), this, aError);
sl@0
  1229
sl@0
  1230
	if (aError==KErrNoMemory)
sl@0
  1231
		{
sl@0
  1232
		if (iDrive)	// Not all message requests are associated with a drive!
sl@0
  1233
			{
sl@0
  1234
			TDriveInfo di;
sl@0
  1235
			iDrive->DriveInfo(di);
sl@0
  1236
			if (di.iType == EMediaRam)
sl@0
  1237
				aError = KErrNoMemory;
sl@0
  1238
			}
sl@0
  1239
		}
sl@0
  1240
	if(aError!=KErrNone)
sl@0
  1241
		{
sl@0
  1242
		if(iOperation->IsOpenSubSess())
sl@0
  1243
			RequestAllocator::OpenSubFailed(Session());
sl@0
  1244
		}
sl@0
  1245
sl@0
  1246
	iLastError = aError;
sl@0
  1247
sl@0
  1248
	// Call the current MessageOp's completion routine - if this returns EReqActionComplete, 
sl@0
  1249
	// then pop the request and call the next MessageOps's completion routine.
sl@0
  1250
	// Do this until there are no more MessageOp's on the stack.
sl@0
  1251
	//
sl@0
  1252
	// Completion return codes:
sl@0
  1253
	// EReqActionOwnedByPlugin:			DON'T dispatch message again, DON'T complete message 
sl@0
  1254
	// EReqActionComplete:				DON'T dispatch message again, DO complete message
sl@0
  1255
	// EReqActionContinue:				DO dispatch message again, DON'T complete message
sl@0
  1256
	// EReqActionBusy					DO dispatch message again, DON'T complete message, 
sl@0
  1257
	TInt completeErr;
sl@0
  1258
sl@0
  1259
	for (completeErr = EReqActionComplete; CurrentOperationPtr() != NULL && completeErr == EReqActionComplete; )
sl@0
  1260
		{
sl@0
  1261
		// Get the completion routine from the current TMsgOperation and then pop it
sl@0
  1262
		TFsRequestFunc doComplete = CurrentOperation().iComplete;
sl@0
  1263
		PopOperation();
sl@0
  1264
		
sl@0
  1265
		// Check that a completion routine is supplied if this isn't the last TMsgOperation
sl@0
  1266
		__ASSERT_ALWAYS(iCurrentOperation == NULL || doComplete != NULL, Fault(EBadOperationIndex));
sl@0
  1267
sl@0
  1268
		// Call the completion routine
sl@0
  1269
		if (doComplete)
sl@0
  1270
			completeErr = doComplete(this);
sl@0
  1271
sl@0
  1272
		// Check return code is valid
sl@0
  1273
		__ASSERT_DEBUG(completeErr == EReqActionContinue || completeErr == EReqActionBusy || completeErr == EReqActionComplete || completeErr == EReqActionOwnedByPlugin, Fault(EBadOperationCompletionCode));
sl@0
  1274
		}
sl@0
  1275
sl@0
  1276
	// a set of flags to determine what actions to take for each return code
sl@0
  1277
	enum 
sl@0
  1278
		{
sl@0
  1279
		EDispatch			= 0x01,	// dispatch request
sl@0
  1280
		EComplete			= 0x02,	// complete request
sl@0
  1281
		EFree				 =0x04,	// free request
sl@0
  1282
		EResetPostInitialised	= 0x08,	// call iPostInitialise again
sl@0
  1283
		EDispatchToFront	= 0x10	// dispatch to back of drive thread queue
sl@0
  1284
		};
sl@0
  1285
	const TUint actions[8] = 
sl@0
  1286
		{
sl@0
  1287
		// 0 - EReqActionContinue
sl@0
  1288
		EDispatch,											
sl@0
  1289
		// 1 - unused
sl@0
  1290
		0,
sl@0
  1291
		// 2 - unused
sl@0
  1292
		0,
sl@0
  1293
		// 3 - unused
sl@0
  1294
		0,
sl@0
  1295
		// 4 - EReqActionCompleteAndDispatch
sl@0
  1296
		EDispatch | EComplete | EResetPostInitialised | EDispatchToFront,
sl@0
  1297
		// 5 - EReqActionOwnedByPlugin
sl@0
  1298
		0,													
sl@0
  1299
		// 6 - EReqActionBusy
sl@0
  1300
		EDispatch | EResetPostInitialised,					
sl@0
  1301
		// 7 - EReqActionComplete
sl@0
  1302
		EComplete | EFree,
sl@0
  1303
		};
sl@0
  1304
sl@0
  1305
	TUint actionFlags = actions[((TUint32) completeErr) & 0x00000007];
sl@0
  1306
sl@0
  1307
	// To dispatch to drive thread and intercept before DoRequestL() 
sl@0
  1308
	// we must re-call iPostInitialise(), so reset iPostInitialised flag
sl@0
  1309
	if (actionFlags & EResetPostInitialised)
sl@0
  1310
		{
sl@0
  1311
		// can only postpone the request if there's a PostInitialise() function
sl@0
  1312
		__ASSERT_DEBUG(iOperation->iPostInitialise , Fault(EBadOperationCompletionCode));
sl@0
  1313
		SetState(EReqStatePostInitialise);
sl@0
  1314
		}
sl@0
  1315
sl@0
  1316
sl@0
  1317
sl@0
  1318
	TInt dispatchError = KErrNone;
sl@0
  1319
	TBool completeMessage = (iLastError != KErrNone) || (iIsCompleted && (actionFlags & EComplete));
sl@0
  1320
sl@0
  1321
	// Need to lock drive to prevent both file server and drive thread from completing the same message (!)
sl@0
  1322
	// or the dispatched thread from freeing the message before the first thread has completed it
sl@0
  1323
	TDrive* drive = iDrive;
sl@0
  1324
	if (drive) 
sl@0
  1325
		drive->Lock();
sl@0
  1326
sl@0
  1327
	// don't go back up plugin chain once message has been completed
sl@0
  1328
	if (completeMessage)
sl@0
  1329
		EnablePostIntercept(EFalse);
sl@0
  1330
sl@0
  1331
	if (actionFlags & EDispatch)
sl@0
  1332
		{
sl@0
  1333
		__ASSERT_DEBUG(((actionFlags & EFree) == 0), Fault(EInvalidCompletionFlags));
sl@0
  1334
		__ASSERT_DEBUG (iCurrentPlugin == NULL, Fault(EInvalidMsgState));
sl@0
  1335
		dispatchError = DispatchToDrive(EFalse, actionFlags & EDispatchToFront);
sl@0
  1336
		}
sl@0
  1337
sl@0
  1338
	
sl@0
  1339
	if ((actionFlags & EComplete) && IsExpectedResult(iLastError) && !IsPluginSpecific() && !IsNotifierSpecific())
sl@0
  1340
		DoNotify(KErrNone);
sl@0
  1341
sl@0
  1342
sl@0
  1343
	if (completeMessage)
sl@0
  1344
		{
sl@0
  1345
		iIsCompleted = EFalse;
sl@0
  1346
		TInt msgHandle = Message().Handle();
sl@0
  1347
		if ((msgHandle != KLocalMessageHandle) && (msgHandle != 0))
sl@0
  1348
			Message().Complete(iLastError);
sl@0
  1349
		if (IsPluginRequest())
sl@0
  1350
			CFsPlugin::Complete(this, iLastError);
sl@0
  1351
		}
sl@0
  1352
sl@0
  1353
	if(iOperation->Function() == EFsFileSubClose)
sl@0
  1354
		{
sl@0
  1355
		HBufC* pFileName = (HBufC*) I64HIGH(ScratchValue64());
sl@0
  1356
		if(pFileName)
sl@0
  1357
			{
sl@0
  1358
			delete pFileName;
sl@0
  1359
			SetScratchValue(NULL);
sl@0
  1360
			}
sl@0
  1361
		}
sl@0
  1362
sl@0
  1363
	if (drive) 
sl@0
  1364
		drive->UnLock();
sl@0
  1365
sl@0
  1366
	if (actionFlags & EFree)
sl@0
  1367
		Free();
sl@0
  1368
sl@0
  1369
	// if the dispatch failed, then continue with popping MessageOps from the stack.
sl@0
  1370
	if (dispatchError != KErrNone)
sl@0
  1371
		Complete(dispatchError);
sl@0
  1372
	}
sl@0
  1373
sl@0
  1374
void CFsMessageRequest::DoNotify(TInt aError)
sl@0
  1375
//
sl@0
  1376
//
sl@0
  1377
//
sl@0
  1378
	{
sl@0
  1379
	__PRINT1(_L("----- CFsMessageRequest::DoNotify() with %d"),aError);
sl@0
  1380
sl@0
  1381
	TInt driveNumber = DriveNumber();
sl@0
  1382
sl@0
  1383
	if(aError==KErrNone)
sl@0
  1384
		{
sl@0
  1385
		if(!(FsNotify::IsChangeQueEmpty(driveNumber)))
sl@0
  1386
			FsNotify::HandleChange(this,driveNumber);	
sl@0
  1387
		if ((driveNumber != KDriveInvalid) && !(FsNotify::IsDiskSpaceQueEmpty(driveNumber)))
sl@0
  1388
			FsNotify::HandleDiskSpace(this, DriveNumber());
sl@0
  1389
	
sl@0
  1390
#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
  1391
		if 	(iOperation->iFunction == EFsFileWrite)
sl@0
  1392
			{
sl@0
  1393
			CFileShare* share = (CFileShare*) this->ScratchValue();
sl@0
  1394
			CFileCB* file = &share->File();
sl@0
  1395
			CFileCache* fileCache = file->FileCache();
sl@0
  1396
			
sl@0
  1397
			// Manage notifications for write with no cache or a write-through
sl@0
  1398
			if (!fileCache || !fileCache->IsDirty())
sl@0
  1399
				{
sl@0
  1400
				FsNotificationManager::HandleChange((CFsClientMessageRequest&)*this);
sl@0
  1401
				}
sl@0
  1402
			}
sl@0
  1403
		else if((iOperation->iFunction == EFsFileWriteDirty) && FsNotificationManager::IsInitialised())
sl@0
  1404
			{
sl@0
  1405
			CFileShare* share;
sl@0
  1406
			CFileCB* file;
sl@0
  1407
			GetFileFromScratch(this, share, file);
sl@0
  1408
sl@0
  1409
			TFileName path;
sl@0
  1410
			path.Append(file->DriveNumber() + 'A');
sl@0
  1411
			path.Append(':');
sl@0
  1412
			path.Append(file->FileName().Des());
sl@0
  1413
			
sl@0
  1414
			// Manage notifications for write with caching enabled
sl@0
  1415
			FsNotificationManager::HandleChange((CFsClientMessageRequest*)this, path, TFsNotification::EFileChange);
sl@0
  1416
			}
sl@0
  1417
		else if(IsNotifierSupported())
sl@0
  1418
			{
sl@0
  1419
			FsNotificationManager::HandleChange((CFsClientMessageRequest&)*this);
sl@0
  1420
			}
sl@0
  1421
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
sl@0
  1422
		}
sl@0
  1423
	}
sl@0
  1424
sl@0
  1425
sl@0
  1426
void CFsMessageRequest::Free()
sl@0
  1427
//
sl@0
  1428
//
sl@0
  1429
//
sl@0
  1430
	{
sl@0
  1431
	__THRD_PRINT1(_L("CFsMessageRequest::Free() isAllocated=%d"), IsAllocated());
sl@0
  1432
sl@0
  1433
	SetScratchValue(0);	// this should close the CFsObject
sl@0
  1434
sl@0
  1435
	if(!IsAllocated())
sl@0
  1436
		delete(this);
sl@0
  1437
	else iOperation = NULL;
sl@0
  1438
sl@0
  1439
	}
sl@0
  1440
sl@0
  1441
TInt CFsMessageRequest::DoInitialise()
sl@0
  1442
//
sl@0
  1443
// returns KErrNone if Initialise succeeded normally
sl@0
  1444
// or      EReqActionComplete if request completed already
sl@0
  1445
// or      EReqActionBusy if request needs dispatching & initialising again
sl@0
  1446
//
sl@0
  1447
	{
sl@0
  1448
	TInt r = KErrNone;
sl@0
  1449
sl@0
  1450
	SetState(iOperation->iPostInitialise ? EReqStatePostInitialise : EReqStateDoRequest);
sl@0
  1451
	r=Initialise();
sl@0
  1452
	if(r==KErrBadHandle)
sl@0
  1453
		{
sl@0
  1454
		// bad subsession handle so panic client
sl@0
  1455
		_LIT(KPanic,"Panic");
sl@0
  1456
		Panic(KPanic,r);
sl@0
  1457
		if(iOperation->IsOpenSubSess())			//this should be close subsession
sl@0
  1458
			RequestAllocator::OpenSubFailed(Session());	//need a close subsession fail
sl@0
  1459
		Free();
sl@0
  1460
		r = EReqActionComplete;
sl@0
  1461
		}
sl@0
  1462
	else if (r == EReqActionComplete)	// completed synchronously in Initialise() function ?
sl@0
  1463
		{
sl@0
  1464
		Complete(KErrNone);
sl@0
  1465
		}
sl@0
  1466
	else if (r == EReqActionBusy || r == EReqActionPending)	// request postponed or owned by file share ?
sl@0
  1467
		{
sl@0
  1468
		}
sl@0
  1469
	else if (r != KErrNone)			// error 
sl@0
  1470
		{
sl@0
  1471
		Complete(r);
sl@0
  1472
		r = EReqActionComplete;
sl@0
  1473
		}
sl@0
  1474
sl@0
  1475
	return r;
sl@0
  1476
	}
sl@0
  1477
sl@0
  1478
TInt CFsMessageRequest::PostInitialise()
sl@0
  1479
//
sl@0
  1480
// returns KErrNone if PostInitialise() succeeded normally
sl@0
  1481
// or      EReqActionComplete if request completed already
sl@0
  1482
// or      EReqActionBusy if request needs dispatching & initialising again
sl@0
  1483
//
sl@0
  1484
	{
sl@0
  1485
	TInt r = KErrNone;
sl@0
  1486
sl@0
  1487
	SetState(EReqStateDoRequest);
sl@0
  1488
	if (iOperation->iPostInitialise)
sl@0
  1489
		r = iOperation->iPostInitialise(this);
sl@0
  1490
	if (r == EReqActionComplete)		// completed early ?
sl@0
  1491
		{
sl@0
  1492
sl@0
  1493
		// Start issuing the post-operation requests starting from the bottom of the chain
sl@0
  1494
		iCurrentPlugin = NULL;
sl@0
  1495
		if (PostInterceptEnabled())
sl@0
  1496
			{
sl@0
  1497
			FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1498
			if(iCurrentPlugin && !iCurrentPlugin->IsPluginThread(*this))
sl@0
  1499
				{
sl@0
  1500
				SetPostOperation(ETrue);
sl@0
  1501
				Dispatch();
sl@0
  1502
				return r;	// EReqActionComplete
sl@0
  1503
				}
sl@0
  1504
			}		
sl@0
  1505
sl@0
  1506
		Complete(KErrNone);
sl@0
  1507
		}
sl@0
  1508
	else if (r == EReqActionBusy)	// request postponed ?
sl@0
  1509
		{
sl@0
  1510
		}
sl@0
  1511
	else if (r != KErrNone)			// error 
sl@0
  1512
		{
sl@0
  1513
		Complete(r);
sl@0
  1514
		r = EReqActionComplete;
sl@0
  1515
		}
sl@0
  1516
sl@0
  1517
	return r;
sl@0
  1518
	}
sl@0
  1519
sl@0
  1520
sl@0
  1521
// CFsMessageRequest::Dispatch()
sl@0
  1522
//
sl@0
  1523
// If aInitialise is EFalse, just disptach request to appropriate thread - 
sl@0
  1524
// don't call DoInitialise() or PostInitialise()
sl@0
  1525
//
sl@0
  1526
void CFsMessageRequest::Dispatch(TBool aInitialise, TBool aLowPriority, TBool aDispatchToFront)
sl@0
  1527
	{
sl@0
  1528
	__THRD_PRINT1(_L("CFsMessageRequest::Dispatch() req %08x"), this);
sl@0
  1529
sl@0
  1530
	TInt r = KErrNone;
sl@0
  1531
sl@0
  1532
	if (iReqState == EReqStateInitialise && aInitialise)
sl@0
  1533
		{
sl@0
  1534
		r = DoInitialise();
sl@0
  1535
		if (r == EReqActionComplete)
sl@0
  1536
			{
sl@0
  1537
			return;
sl@0
  1538
			}
sl@0
  1539
		else if (r == EReqActionBusy)		// request postponed ?
sl@0
  1540
			{
sl@0
  1541
			SetState(EReqStateInitialise);	// reinitialize when request is next processed
sl@0
  1542
			}
sl@0
  1543
		else if (r == EReqActionPending)	// owned by file share ?
sl@0
  1544
			{
sl@0
  1545
			SetState(EReqStateInitialise);	// reinitialize when request is next processed
sl@0
  1546
			return;
sl@0
  1547
			}
sl@0
  1548
		if(!IsPluginSpecific() && (iOwnerPlugin == NULL))
sl@0
  1549
			{
sl@0
  1550
			iCurrentPlugin = NULL;
sl@0
  1551
			iClientThreadId = 0;
sl@0
  1552
			FsPluginManager::NextPlugin(iCurrentPlugin, this, (TBool)ETrue);
sl@0
  1553
sl@0
  1554
			// find out whether there is a plugin registered to post intercept this message
sl@0
  1555
			CFsPlugin* postInterceptPlugin = NULL;
sl@0
  1556
			if (iCurrentPlugin == NULL)
sl@0
  1557
				FsPluginManager::PrevPlugin(postInterceptPlugin, this, (TBool)ETrue);
sl@0
  1558
sl@0
  1559
			// Save the client's thread Id for subsequent testing by CFsPlugin::IsPluginThread() - doing so on the fly 
sl@0
  1560
			// is risky because some messages are completed early in which case Message().Client() will result in a panic
sl@0
  1561
			if ((iCurrentPlugin || postInterceptPlugin) && Message().Handle() != NULL && Message().Handle() != KLocalMessageHandle)
sl@0
  1562
				{
sl@0
  1563
				RThread thread;
sl@0
  1564
				Message().Client(thread, EOwnerThread);
sl@0
  1565
				iClientThreadId = thread.Id();
sl@0
  1566
				thread.Close();
sl@0
  1567
				}
sl@0
  1568
			} 
sl@0
  1569
		} // initialise
sl@0
  1570
		
sl@0
  1571
sl@0
  1572
		// dispatch to plugin thread if initialised (otherwise dispatch to drive thread)
sl@0
  1573
	if (iReqState > EReqStateInitialise && DispatchToPlugin())
sl@0
  1574
		{
sl@0
  1575
		__PLUGIN_PRINT1(_L("PLUGIN: CFsMessageRequest %x dispatched to plugin (async)"), this);
sl@0
  1576
		// The request has been delivered to the plugin thread
sl@0
  1577
		//  - leave the main thread now and await asynchronous completion
sl@0
  1578
		return;
sl@0
  1579
		}
sl@0
  1580
sl@0
  1581
sl@0
  1582
	// Is there a PostInitialise function ?
sl@0
  1583
	if (iReqState ==  EReqStatePostInitialise && aInitialise && r == KErrNone)
sl@0
  1584
		{
sl@0
  1585
		TInt r = PostInitialise();
sl@0
  1586
		if (r == EReqActionComplete)
sl@0
  1587
			return;
sl@0
  1588
		else if (r == EReqActionBusy)				// request postponed ?
sl@0
  1589
			SetState(EReqStatePostInitialise);		// reinitialize when request is next processed
sl@0
  1590
		}
sl@0
  1591
sl@0
  1592
sl@0
  1593
	if(!IsSeparateThread() || FsThreadManager::IsDriveSync(DriveNumber(),EFalse))
sl@0
  1594
		{
sl@0
  1595
		__PLUGIN_PRINT1(_L("PLUGIN: CFsMessageRequest %x dispatched to plugin (sync)"), this);
sl@0
  1596
		FsPluginManager::DispatchSync(this);
sl@0
  1597
		return;
sl@0
  1598
		}
sl@0
  1599
sl@0
  1600
	r = DispatchToDrive(aLowPriority, aDispatchToFront);
sl@0
  1601
	if (r != KErrNone)
sl@0
  1602
		Complete(r);
sl@0
  1603
	}
sl@0
  1604
sl@0
  1605
inline TInt CFsMessageRequest::DispatchToDrive(TBool aLowPriority, TBool aDispatchToFront)
sl@0
  1606
	{
sl@0
  1607
	TInt drivenumber = DriveNumber();
sl@0
  1608
	
sl@0
  1609
	if (drivenumber < EDriveA || drivenumber > EDriveZ)
sl@0
  1610
		return KErrNotSupported;
sl@0
  1611
	
sl@0
  1612
	FsThreadManager::LockDrive(drivenumber);
sl@0
  1613
sl@0
  1614
	CDriveThread* dT=NULL;
sl@0
  1615
	TInt r = FsThreadManager::GetDriveThread(drivenumber,&dT);
sl@0
  1616
sl@0
  1617
	if(r == KErrNone)
sl@0
  1618
		{
sl@0
  1619
		CRequestThread* pT = (CRequestThread*)dT;
sl@0
  1620
sl@0
  1621
		if (FsThreadManager::IsDriveHung(drivenumber))
sl@0
  1622
			r = KErrNotReady;
sl@0
  1623
		else if (aDispatchToFront)
sl@0
  1624
			pT->DeliverFront(this);
sl@0
  1625
		else
sl@0
  1626
			pT->DeliverBack(this, aLowPriority);
sl@0
  1627
		}
sl@0
  1628
	else if (r == KErrAccessDenied)
sl@0
  1629
		{
sl@0
  1630
		Process();
sl@0
  1631
		}
sl@0
  1632
sl@0
  1633
	FsThreadManager::UnlockDrive(drivenumber);
sl@0
  1634
sl@0
  1635
	return r;
sl@0
  1636
	}
sl@0
  1637
sl@0
  1638
void CFsMessageRequest::Dispatch()
sl@0
  1639
	{
sl@0
  1640
	Dispatch(ETrue);
sl@0
  1641
	}
sl@0
  1642
sl@0
  1643
TBool CFsMessageRequest::DispatchToPlugin()
sl@0
  1644
//
sl@0
  1645
// Common route: Receive -> Process -> Dispatch -> DispatchToPlugin
sl@0
  1646
//
sl@0
  1647
	{
sl@0
  1648
	TInt drivenumber = DriveNumber();
sl@0
  1649
	if(iCurrentPlugin)
sl@0
  1650
		{		
sl@0
  1651
		FOREVER
sl@0
  1652
			{
sl@0
  1653
			// if we've reached a plugin which is waiting for Complete(), stop going up the plugin chain
sl@0
  1654
			if(drivenumber >= 0 && IsPostOperation() && CurrentPluginWaiting())
sl@0
  1655
				{
sl@0
  1656
				// No more plug-ins need to process this request
sl@0
  1657
				iCurrentPlugin = NULL;
sl@0
  1658
				}
sl@0
  1659
sl@0
  1660
			while(iCurrentPlugin && iCurrentPlugin->IsPluginThread(*this))
sl@0
  1661
				{
sl@0
  1662
				// Skip the current plugin if the request originated from the plugin
sl@0
  1663
				if(IsPostOperation())
sl@0
  1664
					{
sl@0
  1665
					FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1666
					}
sl@0
  1667
				else
sl@0
  1668
					{
sl@0
  1669
					FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1670
					}
sl@0
  1671
				}
sl@0
  1672
				
sl@0
  1673
			if(iCurrentPlugin)
sl@0
  1674
				{
sl@0
  1675
				TFsPluginRequest request(this);
sl@0
  1676
				 __THRD_PRINT1(_L("CFsMessageRequest::DispatchToPlugin() req %08x"), this);
sl@0
  1677
sl@0
  1678
				TInt err = iCurrentPlugin->Deliver(request);
sl@0
  1679
				if(err == KErrNone)
sl@0
  1680
					{
sl@0
  1681
sl@0
  1682
					// The request has been delivered to the plugin thread
sl@0
  1683
					//  - leave the main thread now
sl@0
  1684
					return(ETrue);
sl@0
  1685
					}
sl@0
  1686
				else if(err < KErrNone)
sl@0
  1687
					{
sl@0
  1688
					// An error has occurred
sl@0
  1689
					//  - complete the message
sl@0
  1690
					Complete(err);
sl@0
  1691
					return(ETrue);
sl@0
  1692
					}
sl@0
  1693
				else if(err == KPluginMessageForward)
sl@0
  1694
					{
sl@0
  1695
					// The plugin has processed synchronously (case 1)
sl@0
  1696
					//  - Pass the message on to the next plugin
sl@0
  1697
					if(FsFunction() != EFsPluginOpen)
sl@0
  1698
					    {
sl@0
  1699
	                    FsPluginManager::NextPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1700
	                    continue;
sl@0
  1701
					    }
sl@0
  1702
					else // FsFunction == EFsPluginOpen
sl@0
  1703
					    {
sl@0
  1704
					    /* 
sl@0
  1705
					     * PluginOpen requests should not be passed down the plugin stack.
sl@0
  1706
					     * 
sl@0
  1707
sl@0
  1708
					     */
sl@0
  1709
					    iCurrentPlugin = NULL;
sl@0
  1710
					    continue;
sl@0
  1711
					    }
sl@0
  1712
					}
sl@0
  1713
				else if(err == KPluginMessageComplete)
sl@0
  1714
					{
sl@0
  1715
					// The plugin has processed synchronously (case 2)
sl@0
  1716
					//  - Pass the message back up the stack
sl@0
  1717
					SetPostOperation(ETrue);
sl@0
  1718
					FsPluginManager::PrevPlugin(iCurrentPlugin, this,(TBool)ETrue);
sl@0
  1719
					continue;
sl@0
  1720
					}
sl@0
  1721
				_LIT(KPanic,"Panic: F32-BAD-PLUGIN-ERROR");
sl@0
  1722
				Panic(KPanic, err);
sl@0
  1723
				}
sl@0
  1724
			else if (IsPostOperation())
sl@0
  1725
				{
sl@0
  1726
				// No more plugins are interested in this request
sl@0
  1727
				//	 - If in post operation, complete the request
sl@0
  1728
				Complete(GetError());
sl@0
  1729
				return(ETrue);
sl@0
  1730
				}
sl@0
  1731
			else
sl@0
  1732
				{
sl@0
  1733
				// No plugin is registered for pre-operation interception this message
sl@0
  1734
				//	- pass the request onto the drive thread.
sl@0
  1735
				return EFalse;
sl@0
  1736
				}
sl@0
  1737
			}			
sl@0
  1738
		}
sl@0
  1739
sl@0
  1740
	if(iOperation->Function() == EFsDismountPlugin)
sl@0
  1741
		{
sl@0
  1742
		// Don't pass plugin dismounts to the drive thread
sl@0
  1743
		Process();
sl@0
  1744
		return(ETrue);
sl@0
  1745
		}
sl@0
  1746
		
sl@0
  1747
	return EFalse;
sl@0
  1748
	}
sl@0
  1749
sl@0
  1750
TDrive* CFsMessageRequest::Drive()
sl@0
  1751
//
sl@0
  1752
//
sl@0
  1753
//
sl@0
  1754
	{
sl@0
  1755
	return(iDrive);
sl@0
  1756
	}
sl@0
  1757
sl@0
  1758
TDrive* CFsMessageRequest::SubstedDrive()
sl@0
  1759
//
sl@0
  1760
//
sl@0
  1761
//
sl@0
  1762
	{
sl@0
  1763
	return(iSubstedDrive);
sl@0
  1764
	}
sl@0
  1765
sl@0
  1766
void CFsMessageRequest::SetDrive(TDrive* aDrive)
sl@0
  1767
//
sl@0
  1768
//
sl@0
  1769
//
sl@0
  1770
	{
sl@0
  1771
	iDrive=aDrive;
sl@0
  1772
	if(aDrive)
sl@0
  1773
		{
sl@0
  1774
		iDriveNumber=aDrive->DriveNumber();
sl@0
  1775
		}
sl@0
  1776
	}
sl@0
  1777
sl@0
  1778
void CFsMessageRequest::SetSubstedDrive(TDrive* aDrive)
sl@0
  1779
//
sl@0
  1780
//
sl@0
  1781
//
sl@0
  1782
	{
sl@0
  1783
	iSubstedDrive=aDrive;
sl@0
  1784
	}
sl@0
  1785
sl@0
  1786
const RMessage2& CFsMessageRequest::Message()
sl@0
  1787
//
sl@0
  1788
//
sl@0
  1789
//
sl@0
  1790
	{
sl@0
  1791
	return(iMessage);
sl@0
  1792
	}
sl@0
  1793
sl@0
  1794
sl@0
  1795
sl@0
  1796
void CFsMessageRequest::ReStart()
sl@0
  1797
	{
sl@0
  1798
	__ASSERT_ALWAYS(CurrentOperationPtr() != NULL, Fault(EBadOperationIndex));
sl@0
  1799
sl@0
  1800
	// restore original settings :
sl@0
  1801
	TMsgOperation& currentOperation = CurrentOperation();
sl@0
  1802
	TInt offset = currentOperation.iReadWriteArgs.iOffset;
sl@0
  1803
	currentOperation.iReadWriteArgs.iPos-= offset;
sl@0
  1804
	currentOperation.iReadWriteArgs.iTotalLength+= offset;
sl@0
  1805
	currentOperation.iReadWriteArgs.iLength = currentOperation.iReadWriteArgs.iTotalLength;
sl@0
  1806
	currentOperation.iReadWriteArgs.iOffset = 0;
sl@0
  1807
	currentOperation.iState = 0;
sl@0
  1808
	TInt function = iOperation->Function();
sl@0
  1809
	__ASSERT_ALWAYS(function == EFsFileRead || function == EFsFileWrite,  Fault(EMsgRestartBadFunction));
sl@0
  1810
	}
sl@0
  1811
sl@0
  1812
sl@0
  1813
void CFsMessageRequest::SetOperationFunc(TInt aFunction)
sl@0
  1814
	{
sl@0
  1815
	const TOperation& oP = OperationArray[aFunction];
sl@0
  1816
	Set(oP);
sl@0
  1817
	// modified because some requests were set to PostInitialise. They are set to DoRequest in Dispatch anyway, so this is possibly ok?
sl@0
  1818
	//__ASSERT_ALWAYS(iReqState == EReqStateDoRequest, Fault(EInvalidMsgState));
sl@0
  1819
	}
sl@0
  1820
sl@0
  1821
TInt CFsMessageRequest::PushOperation(TFsRequestFunc aCallback, TInt aNextState, TInt aFunction)
sl@0
  1822
	{
sl@0
  1823
	TMsgOperation* nextOperation;
sl@0
  1824
	TInt r = RequestAllocator::GetOperation(nextOperation);
sl@0
  1825
	if (r != KErrNone)
sl@0
  1826
		return r;
sl@0
  1827
sl@0
  1828
	
sl@0
  1829
	// Store the caller's state etc in the CURRENT TMsgOperation (if there is one)
sl@0
  1830
	if (iCurrentOperation != NULL)
sl@0
  1831
		{
sl@0
  1832
		__ASSERT_ALWAYS(aCallback, Fault(EPushOpNoCallback));
sl@0
  1833
		iCurrentOperation->iState = aNextState;
sl@0
  1834
		iCurrentOperation->iCurrentPlugin = iCurrentPlugin;
sl@0
  1835
		iCurrentOperation->iFunction = iOperation->Function();
sl@0
  1836
		iCurrentOperation->iNext = nextOperation;
sl@0
  1837
		nextOperation->iPrev = iCurrentOperation;
sl@0
  1838
		}
sl@0
  1839
sl@0
  1840
	// store the call-back routine in the NEW TMsgOperation
sl@0
  1841
	nextOperation->iComplete = aCallback;
sl@0
  1842
	nextOperation->iState = 0;
sl@0
  1843
	if (aFunction != KOperationFunctionUnaltered && aFunction != iOperation->Function())
sl@0
  1844
		SetOperationFunc(aFunction);
sl@0
  1845
sl@0
  1846
sl@0
  1847
	iCurrentOperation = nextOperation;
sl@0
  1848
	
sl@0
  1849
	// reset post operation state: as a plugin may push more than one TMsgOperation
sl@0
  1850
	SetPostOperation(EFalse);
sl@0
  1851
sl@0
  1852
	return KErrNone;
sl@0
  1853
	}
sl@0
  1854
sl@0
  1855
/**
sl@0
  1856
PushOperation()
sl@0
  1857
sl@0
  1858
Pushes a new TMsgOperation onto this request's "stack". After this function completes the new 
sl@0
  1859
TMsgOperation object becomes the "current" one (pointed at by CFsMessageRequest::iCurrentOperation). 
sl@0
  1860
sl@0
  1861
After the request has been dispatched to the drive thread, TOperation::DoRequestL() will be called.
sl@0
  1862
When this has completed, CFsMessage::Complete() is called which then pops the new TMsgOperation 
sl@0
  1863
off the stack; and calls the callback routine (aCallback).
sl@0
  1864
sl@0
  1865
@param aPos			The position to read / write. Stored in the NEW TMsgOperation.
sl@0
  1866
sl@0
  1867
@param aLength		The length to read / write. Stored in the NEW TMsgOperation.
sl@0
  1868
sl@0
  1869
@param aData		A buffer to read the data from / write the data to. Stored in the NEW TMsgOperation.
sl@0
  1870
					The buffer must belong to the file server or to a plugin
sl@0
  1871
sl@0
  1872
@param aOffset		The offset onto the buffer to read from / write to. Stored in the NEW TMsgOperation.
sl@0
  1873
sl@0
  1874
@param aCallback	An optional callback routine. Stored in the OLD TMsgOperation.
sl@0
  1875
					MUST be supplied if there are one or more TMsgOperation's already on the stack
sl@0
  1876
sl@0
  1877
@param aNextState	State information private to the caller. Defaults to zero. Stored in the OLD TMsgOperation.
sl@0
  1878
sl@0
  1879
@param aFunction	An optional TFsMessage. Supplied if the caller wishes to change the TOperation
sl@0
  1880
					associated with this request. When the new TMsgOperation is popped off the stack, the
sl@0
  1881
					previous TOperation is restored. Used primarally for read-modify-write.
sl@0
  1882
					
sl@0
  1883
*/
sl@0
  1884
TInt CFsMessageRequest::PushOperation(TInt64 aPos, TInt aLength, TUint8* aData, TInt aOffset, TFsRequestFunc aCallback, TInt aNextState, TInt aFunction)
sl@0
  1885
	{
sl@0
  1886
	TInt r = PushOperation(aCallback, aNextState, aFunction);
sl@0
  1887
	if (r == KErrNone)
sl@0
  1888
		CurrentOperation().Set(aPos, aLength, aData, aOffset, 0);
sl@0
  1889
	return r;
sl@0
  1890
	}
sl@0
  1891
sl@0
  1892
sl@0
  1893
/**
sl@0
  1894
PushOperation()
sl@0
  1895
sl@0
  1896
Pushes a new TMsgOperation onto this request's "stack". After this function completes the new 
sl@0
  1897
TMsgOperation object becomes the "current" one (pointed at by CFsMessageRequest::iCurrentOperation). 
sl@0
  1898
sl@0
  1899
After the request has been dispatched to the drive thread, TOperation::DoRequestL() will be called.
sl@0
  1900
When this has completed, CFsMessage::Complete() is called which then pops the new TMsgOperation 
sl@0
  1901
off the stack; and calls the callback routine (aCallback).
sl@0
  1902
sl@0
  1903
@param aPos			The position to read / write. Stored in the NEW TMsgOperation.
sl@0
  1904
sl@0
  1905
@param aLength		The length to read / write. Stored in the NEW TMsgOperation.
sl@0
  1906
sl@0
  1907
@param aData		A buffer to read the data from / write the data to. Stored in the NEW TMsgOperation.
sl@0
  1908
					The buffer belongs to a client of the file server on the other side of an IPC boundary.
sl@0
  1909
sl@0
  1910
@param aOffset		The offset onto the buffer to read from / write to. Stored in the NEW TMsgOperation.
sl@0
  1911
sl@0
  1912
@param aCallback	An optional callback routine. Stored in the OLD TMsgOperation.
sl@0
  1913
					MUST be supplied if there are one or more TMsgOperation's already on the stack
sl@0
  1914
sl@0
  1915
@param aNextState	State information private to the caller. Defaults to zero. Stored in the OLD TMsgOperation.
sl@0
  1916
sl@0
  1917
@param aFunction	An optional TFsMessage. Supplied if the caller wishes to change the TOperation
sl@0
  1918
					associated with this request. When the new TMsgOperation is popped off the stack, the
sl@0
  1919
					previous TOperation is restored. Used primarally for read-modify-write.
sl@0
  1920
					
sl@0
  1921
*/
sl@0
  1922
TInt CFsMessageRequest::PushOperation(TInt64 aPos, TInt aLength, TDesC8* aData, TInt aOffset, TFsRequestFunc aCallback, TInt aNextState, TInt aFunction)
sl@0
  1923
	{
sl@0
  1924
	TInt r = PushOperation(aCallback, aNextState, aFunction);
sl@0
  1925
	if (r == KErrNone)
sl@0
  1926
		CurrentOperation().Set(aPos, aLength, aData, aOffset, 0);
sl@0
  1927
	return r;
sl@0
  1928
	}
sl@0
  1929
sl@0
  1930
void CFsMessageRequest::PopOperation()
sl@0
  1931
	{
sl@0
  1932
	__ASSERT_ALWAYS(iCurrentOperation != NULL, Fault(EInvalidOperationIndex));
sl@0
  1933
	
sl@0
  1934
	TMsgOperation* currentOperation = iCurrentOperation;
sl@0
  1935
	
sl@0
  1936
	if (iCurrentOperation->iPrev == NULL)
sl@0
  1937
		{
sl@0
  1938
		iCurrentOperation = NULL;
sl@0
  1939
		}
sl@0
  1940
	else
sl@0
  1941
		{
sl@0
  1942
		TMsgOperation* prevOperation = iCurrentOperation->iPrev;
sl@0
  1943
		prevOperation->iNext = NULL;
sl@0
  1944
		iCurrentOperation = prevOperation;
sl@0
  1945
sl@0
  1946
		iCurrentPlugin = iCurrentOperation->iCurrentPlugin;
sl@0
  1947
		
sl@0
  1948
		if (iCurrentOperation->iFunction != iOperation->Function())
sl@0
  1949
			SetOperationFunc(iCurrentOperation->iFunction);
sl@0
  1950
		}
sl@0
  1951
sl@0
  1952
	RequestAllocator::FreeOperation(currentOperation);
sl@0
  1953
	}
sl@0
  1954
sl@0
  1955
TMsgOperation& CFsMessageRequest::CurrentOperation()
sl@0
  1956
	{
sl@0
  1957
	__ASSERT_ALWAYS(iCurrentOperation != NULL, Fault(EInvalidOperationIndex));
sl@0
  1958
	return *iCurrentOperation;
sl@0
  1959
	}
sl@0
  1960
sl@0
  1961
sl@0
  1962
CFsClientMessageRequest::CFsClientMessageRequest()
sl@0
  1963
: iPoolSrc (0),
sl@0
  1964
  iPoolDest(0)
sl@0
  1965
	{
sl@0
  1966
	}
sl@0
  1967
sl@0
  1968
// Return ETrue if there are ANY TMsgOperation's in the stack which were pushed by iCurrentPlugin
sl@0
  1969
// If there are any, then it's NOT OK to dispatch this message to the plugin thread as it will be 
sl@0
  1970
// waiting on a semaphore which is only cleared by Complete()
sl@0
  1971
TBool CFsMessageRequest::CurrentPluginWaiting()
sl@0
  1972
	{
sl@0
  1973
	if (iOwnerPlugin == iCurrentPlugin)
sl@0
  1974
		return ETrue;
sl@0
  1975
sl@0
  1976
	// find out which plugin (if any) was the last to push a TMsgOperation
sl@0
  1977
	TMsgOperation* currentOperation;
sl@0
  1978
sl@0
  1979
	for (currentOperation = iCurrentOperation ? iCurrentOperation->iPrev : NULL;
sl@0
  1980
		 currentOperation != NULL;
sl@0
  1981
		 currentOperation = currentOperation->iPrev)
sl@0
  1982
			{
sl@0
  1983
			if (currentOperation->iCurrentPlugin == iCurrentPlugin)
sl@0
  1984
				return ETrue;
sl@0
  1985
			}
sl@0
  1986
sl@0
  1987
	return EFalse;
sl@0
  1988
	}
sl@0
  1989
sl@0
  1990
sl@0
  1991
TBool CFsMessageRequest::IsPluginRequest()
sl@0
  1992
	{
sl@0
  1993
	if(iOwnerPlugin) // Check the previous operation had a plugin)
sl@0
  1994
		{
sl@0
  1995
		return ETrue;
sl@0
  1996
		}
sl@0
  1997
	return EFalse;
sl@0
  1998
	}
sl@0
  1999
sl@0
  2000
sl@0
  2001
void CFsClientMessageRequest::Free()
sl@0
  2002
//
sl@0
  2003
//
sl@0
  2004
//
sl@0
  2005
	{
sl@0
  2006
	__THRD_PRINT(_L("CFsClientMessageRequest::Free()"));
sl@0
  2007
	__ASSERT_ALWAYS(CurrentOperationPtr() == NULL, Fault(EFreeingMsgWithMsgOp));
sl@0
  2008
	if (iPoolSrc)
sl@0
  2009
		{
sl@0
  2010
		TParsePool::Release(iPoolSrc);
sl@0
  2011
		iPoolSrc = 0;
sl@0
  2012
		}
sl@0
  2013
sl@0
  2014
	if (iPoolDest)
sl@0
  2015
		{
sl@0
  2016
		TParsePool::Release(iPoolDest);
sl@0
  2017
		iPoolDest = 0;
sl@0
  2018
		}
sl@0
  2019
sl@0
  2020
	SetScratchValue(0);	// this should close the CFsObject
sl@0
  2021
	iOperation = NULL;
sl@0
  2022
	RequestAllocator::FreeRequest(this);
sl@0
  2023
	}
sl@0
  2024
sl@0
  2025
sl@0
  2026
TInt CFsClientMessageRequest::AllocParseObjects(const TOperation& aOperation)
sl@0
  2027
	{
sl@0
  2028
	__ASSERT_ALWAYS(iPoolSrc == NULL && iPoolDest == NULL, Fault(ETParsePoolGet));
sl@0
  2029
sl@0
  2030
	if (aOperation.iFlags & EParseSrc)
sl@0
  2031
		{
sl@0
  2032
		iPoolSrc = TParsePool::Get();
sl@0
  2033
		if (iPoolSrc == NULL)
sl@0
  2034
			return KErrNoMemory;
sl@0
  2035
		}
sl@0
  2036
	if (aOperation.iFlags & EParseDst)
sl@0
  2037
		{
sl@0
  2038
		iPoolDest = TParsePool::Get();
sl@0
  2039
		if (iPoolDest == NULL)
sl@0
  2040
			return KErrNoMemory;
sl@0
  2041
		}
sl@0
  2042
	return KErrNone;
sl@0
  2043
	}
sl@0
  2044
sl@0
  2045
TParse& CFsClientMessageRequest::Src()
sl@0
  2046
//
sl@0
  2047
//
sl@0
  2048
	{
sl@0
  2049
	__ASSERT_ALWAYS(iPoolSrc, Fault(ETParsePoolGet));
sl@0
  2050
	return (iPoolSrc->GetObject());
sl@0
  2051
	}
sl@0
  2052
sl@0
  2053
TParse& CFsClientMessageRequest::Dest()
sl@0
  2054
//
sl@0
  2055
//
sl@0
  2056
//
sl@0
  2057
	{
sl@0
  2058
	__ASSERT_ALWAYS(iPoolDest, Fault(ETParsePoolGet));
sl@0
  2059
	return (iPoolDest->GetObject());
sl@0
  2060
	}
sl@0
  2061
sl@0
  2062
sl@0
  2063
sl@0
  2064
TParsePool* TParsePool::iFreeHead   = 0;
sl@0
  2065
TParsePool* TParsePool::iClosedHead = 0;
sl@0
  2066
TInt        TParsePool::iCountFree  = 0;
sl@0
  2067
RFastLock	TParsePool::iLock;
sl@0
  2068
sl@0
  2069
sl@0
  2070
TParsePool::TParsePool()
sl@0
  2071
:	iNext   (iFreeHead),
sl@0
  2072
	iPrev   (0),
sl@0
  2073
	iFree   (ETrue)
sl@0
  2074
	{
sl@0
  2075
	}
sl@0
  2076
sl@0
  2077
TInt TParsePool::Init()
sl@0
  2078
	{
sl@0
  2079
	return iLock.CreateLocal();
sl@0
  2080
	}
sl@0
  2081
sl@0
  2082
TParsePool* TParsePool::Get()
sl@0
  2083
// Gets a TParsePool object from the free list. If the free list does 
sl@0
  2084
// not contain any TParsePool objects, additional objects are manufactured.
sl@0
  2085
// Returns NULL if unable to allocate a new object
sl@0
  2086
	{
sl@0
  2087
	iLock.Wait();
sl@0
  2088
sl@0
  2089
	TParsePool* pObject = 0;
sl@0
  2090
sl@0
  2091
	// If we don't have anything in the free list, allocate some more...
sl@0
  2092
	if (iCountFree < 1)
sl@0
  2093
		{    
sl@0
  2094
		__ASSERT_DEBUG(iFreeHead == NULL, Fault(ETParsePoolGet));
sl@0
  2095
		for (TInt i = 0; i < KEBlockSize; i++)
sl@0
  2096
			{
sl@0
  2097
			// if allocation fails break out of the loop.
sl@0
  2098
			pObject = new TParsePool;
sl@0
  2099
			if (pObject == NULL)
sl@0
  2100
				break;
sl@0
  2101
			
sl@0
  2102
			iCountFree++;
sl@0
  2103
			
sl@0
  2104
			if (iFreeHead)
sl@0
  2105
				iFreeHead->iPrev = pObject;
sl@0
  2106
sl@0
  2107
			iFreeHead = pObject;
sl@0
  2108
			}
sl@0
  2109
		}
sl@0
  2110
sl@0
  2111
	// if we failed to allocate even a single object, return NULL
sl@0
  2112
	if (iCountFree < 1)
sl@0
  2113
		{
sl@0
  2114
		iLock.Signal();
sl@0
  2115
		return NULL;
sl@0
  2116
		}
sl@0
  2117
sl@0
  2118
sl@0
  2119
	__ASSERT_ALWAYS(iFreeHead != NULL, Fault(ETParsePoolGet));
sl@0
  2120
sl@0
  2121
	pObject = iFreeHead;
sl@0
  2122
	pObject->iFree = EFalse;
sl@0
  2123
sl@0
  2124
sl@0
  2125
	// Remove the head of the free list...
sl@0
  2126
	iFreeHead = pObject->iNext;
sl@0
  2127
	if (iFreeHead)
sl@0
  2128
		iFreeHead->iPrev = 0;
sl@0
  2129
	iCountFree--;
sl@0
  2130
sl@0
  2131
	// ... and add it to the closed list
sl@0
  2132
	pObject->iNext = iClosedHead;
sl@0
  2133
	pObject->iPrev = 0;
sl@0
  2134
	if (iClosedHead)
sl@0
  2135
		iClosedHead->iPrev = pObject;
sl@0
  2136
	iClosedHead = pObject;
sl@0
  2137
sl@0
  2138
	iLock.Signal();
sl@0
  2139
sl@0
  2140
	return pObject;
sl@0
  2141
	}
sl@0
  2142
sl@0
  2143
sl@0
  2144
void TParsePool::Release(TParsePool* aObject)
sl@0
  2145
//
sl@0
  2146
// Release a sub-sequence of TParsePool objects back to the free list.
sl@0
  2147
//
sl@0
  2148
	{
sl@0
  2149
	__ASSERT_ALWAYS(aObject != NULL && !aObject->iFree, Fault(ETParsePoolGet));
sl@0
  2150
sl@0
  2151
	iLock.Wait();
sl@0
  2152
sl@0
  2153
	aObject->iFree = ETrue;
sl@0
  2154
sl@0
  2155
	// Get the objects either side of the one we're interested in
sl@0
  2156
	TParsePool* pPrevious = aObject->iPrev;
sl@0
  2157
	TParsePool* pNext     = aObject->iNext;
sl@0
  2158
sl@0
  2159
	// Remove it from the closed list
sl@0
  2160
	if (pPrevious)
sl@0
  2161
		pPrevious->iNext = pNext;
sl@0
  2162
	else
sl@0
  2163
		iClosedHead = pNext;
sl@0
  2164
sl@0
  2165
	if (pNext)
sl@0
  2166
		pNext->iPrev = pPrevious;
sl@0
  2167
sl@0
  2168
sl@0
  2169
	// Now add it to the free list
sl@0
  2170
	aObject->iNext = iFreeHead;
sl@0
  2171
	aObject->iPrev = 0;
sl@0
  2172
	if (iFreeHead)
sl@0
  2173
		iFreeHead->iPrev = aObject;
sl@0
  2174
sl@0
  2175
	iFreeHead = aObject;
sl@0
  2176
	iCountFree++;
sl@0
  2177
sl@0
  2178
	iLock.Signal();
sl@0
  2179
	}
sl@0
  2180
sl@0
  2181
sl@0
  2182
CFsInternalRequest::CFsInternalRequest()
sl@0
  2183
//
sl@0
  2184
//
sl@0
  2185
//
sl@0
  2186
	{
sl@0
  2187
	// iStatus=NULL;
sl@0
  2188
	// iIsAllocated=EFalse;
sl@0
  2189
	}
sl@0
  2190
sl@0
  2191
void CFsInternalRequest::Set(const TOperation& aOperation,CSessionFs* aSession)
sl@0
  2192
//
sl@0
  2193
//
sl@0
  2194
// 
sl@0
  2195
	{
sl@0
  2196
	CFsRequest::Set(aOperation,aSession);
sl@0
  2197
	}
sl@0
  2198
sl@0
  2199
void CFsInternalRequest::Process()
sl@0
  2200
//
sl@0
  2201
//
sl@0
  2202
//
sl@0
  2203
	{
sl@0
  2204
	__THRD_PRINT(_L("CFsInternalRequest::Process()"));
sl@0
  2205
	TInt r=KErrNone;
sl@0
  2206
	TRAPD(leaveValue,r=iOperation->DoRequestL(this));
sl@0
  2207
	// internal requests should never fail
sl@0
  2208
	__ASSERT_ALWAYS(leaveValue==KErrNone && (r==KErrNone||r==EReqActionBusy),Fault(EInternalRequestProcess));
sl@0
  2209
sl@0
  2210
	// request postponed ? (e.g. if a page used by file cache is busy).
sl@0
  2211
	if (r == EReqActionBusy)
sl@0
  2212
		{
sl@0
  2213
		Dispatch();
sl@0
  2214
		return;
sl@0
  2215
		}
sl@0
  2216
sl@0
  2217
	Complete(r);
sl@0
  2218
	}
sl@0
  2219
sl@0
  2220
sl@0
  2221
void CFsInternalRequest::Complete(TInt aError)
sl@0
  2222
//
sl@0
  2223
//
sl@0
  2224
//
sl@0
  2225
	{
sl@0
  2226
	__PRINT1(_L("CFsInternalRequest::Complete() with %d"),aError);
sl@0
  2227
	TInt func = Operation()->Function();
sl@0
  2228
	if(func==KCancelSession || func==KCancelPlugin || func==KFlushDirtyData)
sl@0
  2229
		{
sl@0
  2230
		__ASSERT_DEBUG(ThreadHandle()!=0 && !FsThreadManager::IsDisconnectThread(),Fault(EInternalRequestComplete1));
sl@0
  2231
		RThread t;
sl@0
  2232
		t.SetHandle(ThreadHandle());
sl@0
  2233
		TRequestStatus* s=&Status();
sl@0
  2234
		t.RequestComplete(s,aError);
sl@0
  2235
		Free();
sl@0
  2236
		}
sl@0
  2237
	else if(func == KDispatchObjectClose)
sl@0
  2238
		{
sl@0
  2239
		TFsCloseObject::Complete(this);
sl@0
  2240
		Free();
sl@0
  2241
		}
sl@0
  2242
	else if(func==KFileShareClose)
sl@0
  2243
		{
sl@0
  2244
		if (aError == EReqActionBusy)
sl@0
  2245
			{
sl@0
  2246
			Dispatch();
sl@0
  2247
			}
sl@0
  2248
		else
sl@0
  2249
			{
sl@0
  2250
			TFsCloseFileShare::Complete(this);
sl@0
  2251
			Free();
sl@0
  2252
			}
sl@0
  2253
		}
sl@0
  2254
	else
sl@0
  2255
		Fault(EInternalRequestComplete3);
sl@0
  2256
	}
sl@0
  2257
sl@0
  2258
void CFsInternalRequest::Dispatch()
sl@0
  2259
//
sl@0
  2260
//
sl@0
  2261
//
sl@0
  2262
	{
sl@0
  2263
	__THRD_PRINT(_L("CFsInternalRequest::Dispatch()"));
sl@0
  2264
	__ASSERT_ALWAYS(Initialise()==KErrNone,Fault(EInternalRequestDispatch1));
sl@0
  2265
sl@0
  2266
	if(iCurrentPlugin && Operation()->Function() == KCancelPlugin)
sl@0
  2267
		{
sl@0
  2268
		TFsPluginRequest request(this);
sl@0
  2269
		TInt r = iCurrentPlugin->Deliver(request);
sl@0
  2270
		__ASSERT_ALWAYS(r == KErrNone, Fault(EInternalRequestDispatchCancelPlugin));
sl@0
  2271
		}
sl@0
  2272
	else
sl@0
  2273
		{
sl@0
  2274
		TInt drivenumber = DriveNumber();
sl@0
  2275
		FsThreadManager::LockDrive(drivenumber);
sl@0
  2276
		// shouldn't dispath if no drive available
sl@0
  2277
		__ASSERT_ALWAYS(FsThreadManager::IsDriveAvailable(drivenumber,EFalse) && !FsThreadManager::IsDriveSync(drivenumber,EFalse),Fault(EInternalRequestDispatch2));
sl@0
  2278
		CDriveThread* dT=NULL;
sl@0
  2279
		TInt r=FsThreadManager::GetDriveThread(drivenumber,&dT);
sl@0
  2280
		__THRD_PRINT2(_L("deliver to thread 0x%x, drive number %d"),dT,drivenumber);
sl@0
  2281
		__ASSERT_ALWAYS(r==KErrNone && dT,Fault(EInternalRequestDispatch3));
sl@0
  2282
		CRequestThread* pT = (CRequestThread*)dT;
sl@0
  2283
		TInt func = Operation()->Function();
sl@0
  2284
		if(func == KDispatchObjectClose || func == KFileShareClose || func == KFlushDirtyData)
sl@0
  2285
			pT->DeliverBack(this);
sl@0
  2286
		else
sl@0
  2287
			pT->DeliverFront(this);
sl@0
  2288
		FsThreadManager::UnlockDrive(drivenumber);
sl@0
  2289
		}
sl@0
  2290
	}
sl@0
  2291
sl@0
  2292
void CFsInternalRequest::Free()
sl@0
  2293
//
sl@0
  2294
//
sl@0
  2295
//
sl@0
  2296
	{
sl@0
  2297
	__THRD_PRINT1(_L("CFsInternalRequest::Free() isAllocated=%d"),IsAllocated());
sl@0
  2298
sl@0
  2299
	SetScratchValue(0);	// this should close the CFsObject
sl@0
  2300
sl@0
  2301
	if(!IsAllocated())
sl@0
  2302
		delete(this);
sl@0
  2303
	}
sl@0
  2304
sl@0
  2305
void CFsDisconnectRequest::Dispatch()
sl@0
  2306
//
sl@0
  2307
//
sl@0
  2308
//
sl@0
  2309
	{
sl@0
  2310
	__THRD_PRINT(_L("CFsDisconnectRequest::Dispatch()"));
sl@0
  2311
	// no need to lock
sl@0
  2312
	TInt r=Initialise();
sl@0
  2313
	__ASSERT_ALWAYS(r==KErrNone,Fault(EDisconnectRequestDispatch1));
sl@0
  2314
	CRequestThread* pT=FsThreadManager::GetDisconnectThread();
sl@0
  2315
	__ASSERT_ALWAYS(pT,Fault(EDisconnectRequestDispatch2));
sl@0
  2316
	pT->DeliverBack(this);
sl@0
  2317
	}
sl@0
  2318
sl@0
  2319
void CFsDisconnectRequest::Process()
sl@0
  2320
//
sl@0
  2321
//
sl@0
  2322
//
sl@0
  2323
	{
sl@0
  2324
	__THRD_PRINT(_L("CFsDisconnectRequest::Process()"));
sl@0
  2325
	TInt r=KErrNone;
sl@0
  2326
	TRAPD(leaveValue,r=iOperation->DoRequestL(this));
sl@0
  2327
	leaveValue=leaveValue; // just to make compiler happy
sl@0
  2328
	__ASSERT_DEBUG(leaveValue==KErrNone && r==KErrNone,Fault(EDisonncectRequestProcess));
sl@0
  2329
	Complete(r);
sl@0
  2330
	}
sl@0
  2331
sl@0
  2332
void CFsDisconnectRequest::Complete(TInt aError)
sl@0
  2333
//
sl@0
  2334
//
sl@0
  2335
//
sl@0
  2336
	{
sl@0
  2337
	__PRINT1(_L("CFsDisconnectRequest::Complete() with %d"),aError);
sl@0
  2338
	__ASSERT_ALWAYS(aError==KErrNone,Fault(EDisconnectRequestComplete));
sl@0
  2339
	// set session disconnect reqeust to NULL
sl@0
  2340
	// will be freed in CFsMessageRequest::Free()
sl@0
  2341
	Session()->iDisconnectRequest=NULL;
sl@0
  2342
	// now delete session
sl@0
  2343
	TheFileServer->SessionQueueLockWait();
sl@0
  2344
	delete(Session());
sl@0
  2345
	TheFileServer->SessionQueueLockSignal();
sl@0
  2346
	// NB Must complete the message AFTER the session has been deleted...
sl@0
  2347
	Message().Complete(aError);
sl@0
  2348
	delete(this);	
sl@0
  2349
	}
sl@0
  2350
sl@0
  2351
sl@0
  2352
/**
sl@0
  2353
Create a new synchronous message scheduler
sl@0
  2354
*/
sl@0
  2355
CFsSyncMessageScheduler* CFsSyncMessageScheduler::NewL()
sl@0
  2356
	{
sl@0
  2357
	__PRINT(_L("CFsSyncMessageScheduler::NewL()"));
sl@0
  2358
sl@0
  2359
	CFsSyncMessageScheduler* pSelf = new(ELeave)CFsSyncMessageScheduler();
sl@0
  2360
	
sl@0
  2361
	CleanupStack::PushL(pSelf);
sl@0
  2362
	pSelf->ConstructL();
sl@0
  2363
	CleanupStack::Pop();
sl@0
  2364
	
sl@0
  2365
	return(pSelf);
sl@0
  2366
	}
sl@0
  2367
sl@0
  2368
sl@0
  2369
/**
sl@0
  2370
Construct a synchronous message scheduler
sl@0
  2371
*/
sl@0
  2372
CFsSyncMessageScheduler::CFsSyncMessageScheduler()
sl@0
  2373
 : CActive(EPriorityHigh),
sl@0
  2374
   iList(_FOFF(CFsRequest,iLink))
sl@0
  2375
	{
sl@0
  2376
	__PRINT(_L("CFsSyncMessageScheduler::CFsSyncMessageScheduler()"));
sl@0
  2377
	}
sl@0
  2378
sl@0
  2379
sl@0
  2380
/**
sl@0
  2381
Second-phase constructor
sl@0
  2382
*/
sl@0
  2383
sl@0
  2384
void CFsSyncMessageScheduler::ConstructL()
sl@0
  2385
	{
sl@0
  2386
	__PRINT(_L("CFsSyncMessageScheduler::ConstructL()"));
sl@0
  2387
	
sl@0
  2388
	User::LeaveIfError(iLock.CreateLocal());
sl@0
  2389
	User::LeaveIfError(iThread.Open(RThread().Id()));
sl@0
  2390
	
sl@0
  2391
	CActiveScheduler::Add(this);
sl@0
  2392
	}
sl@0
  2393
	
sl@0
  2394
	
sl@0
  2395
/**
sl@0
  2396
Synchronous message scheduler 
sl@0
  2397
	- dispatch any synchronous requests that were queued via ::Dispatch
sl@0
  2398
*/
sl@0
  2399
void CFsSyncMessageScheduler::RunL()
sl@0
  2400
	{
sl@0
  2401
	__PRINT(_L(">> CFsSyncMessageScheduler::RunL()"));
sl@0
  2402
	
sl@0
  2403
	FOREVER
sl@0
  2404
		{
sl@0
  2405
		iLock.Wait();
sl@0
  2406
		if(iList.IsEmpty())
sl@0
  2407
			{
sl@0
  2408
			break;
sl@0
  2409
			}
sl@0
  2410
		else
sl@0
  2411
			{
sl@0
  2412
			CFsRequest* request = iList.First();
sl@0
  2413
			request->iLink.Deque();
sl@0
  2414
			iLock.Signal();
sl@0
  2415
			__PRINT1(_L("   CFsSyncMessageScheduler - Dispatching message %08x"), request);
sl@0
  2416
			request->Process();
sl@0
  2417
			}
sl@0
  2418
		}
sl@0
  2419
	
sl@0
  2420
	iSignalled = EFalse;
sl@0
  2421
	iStatus = KRequestPending;
sl@0
  2422
	SetActive();
sl@0
  2423
	iLock.Signal();
sl@0
  2424
	
sl@0
  2425
	__PRINT(_L("<< CFsSyncMessageScheduler::RunL()"));
sl@0
  2426
	}
sl@0
  2427
sl@0
  2428
sl@0
  2429
/**
sl@0
  2430
DoCancel - Not Implemented
sl@0
  2431
*/
sl@0
  2432
void CFsSyncMessageScheduler::DoCancel()
sl@0
  2433
	{
sl@0
  2434
	__PRINT(_L("CFsSyncMessageScheduler::DoCancel"));
sl@0
  2435
	}
sl@0
  2436
sl@0
  2437
sl@0
  2438
/**
sl@0
  2439
Queue synchronous requests to be processed in main thread context
sl@0
  2440
	- called when synchronous messages are passed from plugin threads
sl@0
  2441
*/
sl@0
  2442
void CFsSyncMessageScheduler::Dispatch(CFsRequest* aRequest)
sl@0
  2443
	{
sl@0
  2444
	__PRINT1(_L("CFsSyncMessageScheduler::Dispatch(%08x)"), aRequest);
sl@0
  2445
sl@0
  2446
	// Accquire lock and add request to queue.
sl@0
  2447
	iLock.Wait();
sl@0
  2448
	iList.AddFirst(*aRequest);
sl@0
  2449
sl@0
  2450
	if(!iSignalled)
sl@0
  2451
		{
sl@0
  2452
		// set iSignalled in case another thread (plug-in) is calling dispatch, then release lock.
sl@0
  2453
		iSignalled = ETrue;
sl@0
  2454
		iLock.Signal();
sl@0
  2455
sl@0
  2456
		// signal main thread.
sl@0
  2457
		TRequestStatus* s = &iStatus;
sl@0
  2458
		iThread.RequestComplete(s, KErrNone);
sl@0
  2459
		}
sl@0
  2460
	else
sl@0
  2461
		{
sl@0
  2462
		// main thread already signalled, just release lock.
sl@0
  2463
		iLock.Signal();
sl@0
  2464
		}
sl@0
  2465
	}
sl@0
  2466
sl@0
  2467
sl@0
  2468
/**
sl@0
  2469
Complete outstanding requests for the specified session
sl@0
  2470
*/
sl@0
  2471
void CFsSyncMessageScheduler::CompleteSessionRequests(CSessionFs* aSession, TInt aValue)
sl@0
  2472
	{
sl@0
  2473
	__PRINT2(_L("FsPluginManager::CompleteSessionRequests(%08x, %d)"), aSession, aValue);
sl@0
  2474
	
sl@0
  2475
	iLock.Wait();
sl@0
  2476
	TDblQueIter<CFsRequest> q(iList);
sl@0
  2477
	CFsRequest* pR;
sl@0
  2478
	while((pR=q++)!=NULL)
sl@0
  2479
		{
sl@0
  2480
		if(pR->Session()==aSession)
sl@0
  2481
			{
sl@0
  2482
			pR->iLink.Deque();
sl@0
  2483
			pR->Complete(aValue);
sl@0
  2484
			}
sl@0
  2485
		}
sl@0
  2486
	iLock.Signal();
sl@0
  2487
	}
sl@0
  2488