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