userlibandfileserver/fileserver/sfile/sf_file.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfile/sf_file.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,3644 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+ 
+#include "sf_std.h"
+#include "sf_file_cache.h"
+#include "cl_std.h"
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+
+TInt OutputTraceInfo(CFsRequest* aRequest,TCorruptNameRec* aNameRec)
+	{	
+	RThread tT;
+	RProcess tP;
+	TBool nameUnknown=EFalse;
+	TInt r=aRequest->Message().Client(tT,EOwnerThread);
+	if(r!=KErrNone)
+		{
+		nameUnknown=ETrue;
+		}
+	else
+		{
+		r=tT.Process(tP);
+		if(r!=KErrNone)	
+			{
+			tT.Close();	
+			nameUnknown=ETrue;
+			}
+		}
+	TName n;
+	if(!nameUnknown)
+		{
+		n=tP.Name();
+		TInt b=n.Locate('[');
+		if (b>=0)
+			n.SetLength(b);
+		tP.Close();
+		tT.Close();
+		}
+	else
+		{
+		n=_L("*Unknown*");
+		}
+	TPtrC t(aRequest->Src().FullName());
+	// output a message via the debug port
+	RDebug::Print(_L("@@@@ Corrupt file check %S tried to open %S"),&n,&t);
+	// make a new log record & chain it in
+	TCorruptLogRec* pLogRec= new TCorruptLogRec;
+	if(pLogRec==NULL)
+		return KErrNoMemory;
+	TPtrC nPtr(n);
+	if(pLogRec->Construct(aNameRec,&nPtr,gCorruptLogRecordList)!=KErrNone)
+		{
+		delete pLogRec;
+		return KErrNoMemory;
+		}
+	else
+		{
+		gCorruptLogRecordList=pLogRec;
+		// really a count of number of log records
+		gNumberOfCorruptHits++;
+		}
+	return KErrNone;
+	}
+
+TCorruptLogRec::TCorruptLogRec()
+	:iProcessName(NULL),iNameRec(NULL),iNext(NULL)
+	{}
+
+TCorruptLogRec::~TCorruptLogRec()
+	{ // free off name memory
+	delete iProcessName;
+	}
+
+
+void TCorruptLogRec::DestroyList()
+	{
+	TCorruptLogRec* pList=gCorruptLogRecordList;
+
+	while(pList!=NULL)
+		{
+		TCorruptLogRec* pThis=pList;
+		pList=pList->iNext;
+		delete pThis;
+		}
+	gCorruptLogRecordList=NULL;
+	gNumberOfCorruptHits=0;
+	}
+
+TInt TCorruptLogRec::Construct(TCorruptNameRec* aNameRec, TPtrC* aProcessName, TCorruptLogRec* aChain)
+	{
+	iProcessName=aProcessName->Alloc();
+	if(iProcessName==NULL)
+		return KErrNoMemory;
+
+	iNameRec=aNameRec;
+	iNext=aChain;
+	return KErrNone;
+	}
+
+TInt TCorruptLogRec::GetLogRecord(TFsDebugCorruptLogRecordBuf& aLogRecord,TInt aLogRecNum)
+	{
+	if(aLogRecNum<=0)
+		{
+		return KErrArgument;
+		}
+	else if(aLogRecNum>gNumberOfCorruptHits)
+		{
+		return KErrNotFound;
+		}
+
+	TCorruptLogRec* pList=gCorruptLogRecordList;
+
+	for(TInt i=1;i<aLogRecNum && pList!=NULL;i++)
+		{	
+		pList=pList->iNext;
+		}
+
+	TInt r=KErrNotFound;
+
+	if(pList)
+		{
+		aLogRecord().iProcessName=pList->iProcessName->Des();
+		aLogRecord().iFileName=pList->iNameRec->Name();
+		aLogRecord().iError=pList->iNameRec->ReturnCode();
+		r=KErrNone;
+		}
+
+	return r;
+	}
+
+TCorruptNameRec::TCorruptNameRec()
+:iName(NULL),iNext(NULL){} 
+
+TInt TCorruptNameRec::Construct(TPtr* aName,TInt aReturnCode, TBool aUseOnce, TCorruptNameRec* aChain)
+	{
+	iName=aName->Alloc();
+	if(iName==NULL)
+		return KErrNoMemory;
+	iReturnCode=aReturnCode;
+	iUseOnce=aUseOnce;
+	iConsumed=EFalse;
+	iNext=aChain;
+	return KErrNone;
+	}
+
+void TCorruptNameRec::ResetListConsumed()
+	{
+	TCorruptNameRec* pList=gCorruptFileNameList;
+	while(pList!=NULL)
+		{
+		pList->iConsumed=EFalse;
+		pList=pList->Next();
+		}
+	}
+
+LOCAL_C void checkCorruptNamesList(CFsRequest* aRequest, TInt &aError)
+	{
+	aError=KErrNone;
+	TPtrC path(aRequest->Src().FullName());
+	TCorruptNameRec* pList=gCorruptFileNameList;
+	while(pList)
+		{
+		if(pList->Name().MatchF(path)==0)
+			{
+			if(!pList->Consumed())
+				{
+				aError=pList->ReturnCode();
+				pList->SetConsumed();
+				OutputTraceInfo(aRequest,pList);
+				}
+			break;
+			}
+		pList=pList->Next();
+		}
+	}
+#endif
+
+
+LOCAL_C TInt DoInitNoParse(CFsRequest* aRequest)
+//
+// Common init for read and write access to files
+//
+	{
+	CFileShare* share = GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
+	if(!share)
+		return(KErrBadHandle);
+	aRequest->SetDrive(&share->File().Drive());
+	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
+	return KErrNone;
+	}
+
+_LIT(KDrivePath,"?:");
+LOCAL_C TInt DoInitialise(CFsRequest* aRequest)
+//
+//	Common initialisation code use file share to determine asychronicity
+//
+	{
+	CFileShare* share = GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
+	if(!share)
+		return(KErrBadHandle);
+	aRequest->SetDrive(&share->File().Drive());
+	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
+	TBuf<2> drive(KDrivePath);
+	drive[0]=TText(aRequest->DriveNumber()+'A');
+	aRequest->Src().Set(share->File().FileName(),NULL,&drive);
+	return KErrNone;
+	}
+
+LOCAL_C TInt InitialiseScratchToShare(CFsRequest* aRequest)
+//
+// Common code used to initialise the scratch value to the CFileShare* from the request
+//	
+	{
+	CFileShare* share=GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
+	if(!share)
+		return(KErrBadHandle);
+	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
+
+	return(KErrNone);
+	}
+
+LOCAL_C TInt FsFileOpenL(CFsRequest* aRequest, TFileOpen anOpen)
+//
+// Open a file.
+//
+	{
+	TInt r;
+    
+    TUint32 mode=aRequest->Message().Int1();
+	if (anOpen==EFileCreate || anOpen==EFileReplace)
+		{
+		r = CheckDiskSpace(0, aRequest);
+		if(r != KErrNone)
+            return r;
+        
+        mode|=EFileWrite;
+		}
+
+	TInt h;
+    r=aRequest->Drive()->FileOpen(aRequest,h,aRequest->Src().FullName().Mid(2),mode,anOpen);
+	if (r!=KErrNone)
+		return(r);
+	
+    TPtrC8 pH((TUint8*)&h,sizeof(TInt));
+	TRAP(r, aRequest->WriteL(KMsgPtr3,pH))
+	CheckForLeaveAfterOpenL(r, aRequest, h);
+	aRequest->Session()->IncResourceCount();
+	
+    return(KErrNone);
+	}
+
+TInt TFsFileOpen::DoRequestL(CFsRequest* aRequest)
+//
+//
+//
+	{
+	__PRINT(_L("TFsFileOpen::DoRequestL(CFsRequest* aRequest)"));
+	return FsFileOpenL(aRequest, EFileOpen);
+	}
+
+TInt TFsFileCreate::DoRequestL(CFsRequest* aRequest)
+//
+//
+//
+	{
+
+	__PRINT(_L("TFsFileCreate::DoRequestL(CFsRequest* aRequest)"));
+	return FsFileOpenL(aRequest, EFileCreate);
+	}
+
+TInt TFsFileCreate::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
+ 	if (r!=KErrNone)
+		return(r);
+	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileCreate,&KCapFsPriFileCreate,&KCapFsROFileCreate, __PLATSEC_DIAGNOSTIC_STRING("Create File")); 
+	if (r!=KErrNone)
+		return(r);
+	if (OpenOnDriveZOnly)
+		{
+		aRequest->SetDrive(&TheDrives[EDriveZ]);
+		aRequest->SetSubstedDrive(NULL);
+		}
+	return(r);
+	}
+
+
+
+TInt TFsFileReplace::DoRequestL(CFsRequest* aRequest)
+//
+//
+//
+	{
+	__PRINT(_L("TFsFileReplace::DoRequestL(CFsRequest* aRequest)"));
+	return FsFileOpenL(aRequest, EFileReplace);
+	}
+
+TInt TFsFileReplace::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
+ 	if (r!=KErrNone)
+		return(r);
+	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileReplace,&KCapFsPriFileReplace,&KCapFsROFileReplace, __PLATSEC_DIAGNOSTIC_STRING("Replace File")); 
+	if (r!=KErrNone)
+		return(r);
+
+	if (OpenOnDriveZOnly)	// Yuck! yet another global
+		{
+		aRequest->SetDrive(&TheDrives[EDriveZ]);
+		aRequest->SetSubstedDrive(NULL);
+		}
+	return(r);
+	}
+
+
+#ifdef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+
+#define __PLATSEC_DIAGNOSTIC_MESSAGE(s)	NULL
+static const TInt KMsgBuffSize = KMaxPath;
+
+#else
+
+	#if defined(_UNICODE) && !defined(__KERNEL_MODE__)
+
+static const TInt KCharMsgMaxLen = KMaxPath - 1;
+static const TInt KMsgBuffSize = KMaxPath;
+
+	#else
+
+static const TInt KCharMsgMaxLen = 50;
+static const TInt KMsgBuffSize = KMaxPath + KMsgMaxLen + 1;
+
+	#endif	// #if defined(_UNICODE) && !defined(__KERNEL_MODE__)
+
+// Local function to format a message
+static
+const char* FmtPlatSecMessage(TBufC<KMsgBuffSize>& buff, CFsRequest& req, const char* str)
+    {
+    char* p = (char*)buff.Ptr();
+	const char* const base = p;
+    // copy message string (if any)
+    if(str)
+        {
+        while(*str && p < &base[KCharMsgMaxLen - 2]) // 2 for trailing ": "
+            *p++ = *str++;
+        *p++ = ':';
+        *p++ = ' ';
+        }
+    // append filename
+    const TDesC& fname = req.Src().FullName();
+    const TInt end = Min(fname.Length(), 
+                         KMsgBuffSize * sizeof(*buff.Ptr()) - (p - base) - 1);
+    for(TInt i = 0; i < end; ++i)
+        *p++ = (char)fname[i];
+    *p = 0;
+    return base;
+    }
+    
+#define __PLATSEC_DIAGNOSTIC_MESSAGE(s) FmtPlatSecMessage(thisPath, *aRequest, s)
+
+#endif	// #ifdef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+
+
+TInt TFsFileOpen::Initialise(CFsRequest* aRequest)
+//
+// Parse and execute FileOpen service otherwise sets flag for  
+// asynchronous service
+//
+	{
+	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
+ 	if (r!=KErrNone)
+		return(r);
+
+	TBufC<KMsgBuffSize> thisPath(aRequest->Src().FullName().Mid(2));
+	TUint32 mode = (aRequest->Message().Int1() & ~(EFileStreamText | EFileReadAsyncAll | EFileBigFile));
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+// see if file is on our "Most Wanted" list
+	TInt errorCode;
+	checkCorruptNamesList(aRequest,errorCode);
+	if(errorCode!=KErrNone)
+		{
+		return errorCode;
+		}
+#endif
+
+	CFsMessageRequest* msgRequest = (CFsMessageRequest*)aRequest;
+	if (OpenOnDriveZOnly)
+		{
+		aRequest->SetDrive(&TheDrives[EDriveZ]);
+		aRequest->SetSubstedDrive(NULL);
+		}
+
+	if(msgRequest->IsPluginRequest())
+		{
+		// Always allow plugins to open files, regardless of the clients policy
+		return KErrNone;
+		}
+
+	if(ComparePrivate(thisPath))
+		{
+		if(! SIDCheck(aRequest,thisPath))
+			{
+			if(!KCapFsPriFileOpen.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in private path")))
+				return KErrPermissionDenied;
+			}
+		}
+	else if(CompareResource(thisPath))
+		{
+ 		if(mode != EFileShareReadersOrWriters && mode != EFileShareReadersOnly && mode != EFileRead) 
+ 		// File opening mode EFileShareReadersOrWriters|EFileRead will fail the above test and not 
+ 		// be checked for policy, whereas file opening mode EFileShareReadersOrWriters|EFileWrite 
+ 		// will pass the test and will be checked for policy. 
+ 		// EFileRead is 0 whereas EFileWrite is non 0.
+ 			{
+			if(!KCapFsROFileOpenWr.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in resource path")))
+				return KErrPermissionDenied;
+			}
+		}
+	else if(CompareSystem(thisPath))
+		{
+		if(!(mode & EFileShareReadersOnly) && (mode & EFileWrite))
+			{
+			if(!KCapFsSysFileOpenWr.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in system path")))
+				return KErrPermissionDenied;
+			}
+		else
+			{
+			if(!KCapFsSysFileOpenRd.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in system path")))
+				return KErrPermissionDenied;
+			}
+		}
+
+	return(r);
+	}
+
+#undef __PLATSEC_DIAGNOSTIC_MESSAGE	
+	
+TInt TFsIsFileOpen::DoRequestL(CFsRequest* aRequest)
+//
+// Return whether a file is open or not
+//
+	{
+
+	__PRINT(_L("TFsIsFileOpen::DoRequestL(CFsRequest* aRequest)"));
+	CFileCB* file;
+	TInt r=aRequest->Drive()->IsFileOpen(aRequest->Src().FullName().Mid(2),file);
+	if (r!=KErrNone)
+		return(r);
+	TBool isOpen = file?(TBool)ETrue:(TBool)EFalse;
+	TPtrC8 pA((TUint8*)&isOpen,sizeof(TBool));
+	aRequest->WriteL(KMsgPtr1,pA);
+	return(KErrNone);
+	}
+
+TInt TFsIsFileOpen::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
+	if (r!=KErrNone)
+		return(r);
+	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysIsFileOpen,&KCapFsPriIsFileOpen, __PLATSEC_DIAGNOSTIC_STRING("Is File Open")); 
+	return(r);
+	}
+
+
+TInt TFsListOpenFiles::DoRequestL(CFsRequest* aRequest)
+//
+// List open files
+//
+	{
+	
+	__PRINT(_L("TFsListOpenFiles::DoRequestL(CFsRequest* aRequest)"));
+
+	TOpenFileListPos listPos;
+	TPckg<TOpenFileListPos> listPkg(listPos);
+	aRequest->ReadL(KMsgPtr0,listPkg);
+	TBuf8<KEntryArraySize> entryArray(0);
+	
+	TThreadId idClient;
+	TPckgC<TThreadId> id(idClient);	
+
+	CSessionFs* session;
+	TBool fileFound=(listPos.iEntryListPos) ? (TBool)ETrue : EFalse;
+	TInt entryListPos;
+	TInt count;
+Start:
+	FOREVER
+		{
+		session=(*TheFileServer)[listPos.iSession];	//this global may not be the best way AJ
+		if (session==NULL)
+			goto End;
+		session->Handles().Lock();
+		count=session->Handles().Count();
+		if (count)
+			break;
+		session->Handles().Unlock();
+		listPos.iSession++;
+		}
+
+	entryListPos=listPos.iEntryListPos;
+	while (entryListPos<count)
+		{
+		CObjPromotion* obj=(CObjPromotion*)session->Handles()[entryListPos];
+		if (obj==NULL || obj->UniqueID()!=FileShares->UniqueID())
+			{
+			entryListPos++;
+			continue; // Is not a CFileShare
+			}
+		CFileCB& fileCb=((CFileShare*)obj)->File();
+
+		TEntry fileEntry;
+		// Set kEntryAttPacked to indicate it is in packed form
+		fileEntry.iAtt=fileCb.Att() | KEntryAttPacked;
+		TInt64 fileSize = fileCb.Size64();
+		fileEntry.iSize = I64LOW(fileSize);
+		fileEntry.iModified=fileCb.Modified();
+		fileEntry.iName=fileCb.FileName();
+		
+		// Pack - Copy iSizeHigh and reset iReserved in packed form
+		TUint32* pSizeHigh = PtrAdd((TUint32*)&fileEntry, EntrySize(fileEntry, EFalse));
+		
+		*pSizeHigh++ = I64HIGH(fileSize);	// Copy iSizeHigh
+		*pSizeHigh 	 = 0;					// Reset iReserved
+		
+		TInt entrySize=EntrySize(fileEntry, ETrue);
+		if (entryArray.Length()+entrySize>entryArray.MaxLength())
+			break;
+		TPtrC8 pfileEntry((TUint8*)&fileEntry,entrySize);
+		entryArray.Append(pfileEntry);
+		entryListPos++;
+		}
+	idClient = session->ThreadId();
+	session->Handles().Unlock();
+
+	if (entryArray.Length()==0)
+		listPos.iSession++;
+	if (fileFound==EFalse && entryArray.Length()==0)
+		goto Start;
+	listPos.iEntryListPos=entryListPos;
+
+End:
+	aRequest->WriteL(KMsgPtr1,id);
+	aRequest->WriteL(KMsgPtr0,listPkg);
+	aRequest->WriteL(KMsgPtr2,entryArray);
+	return(KErrNone);
+	}
+
+TInt TFsListOpenFiles::Initialise(CFsRequest* /*aRequest*/)
+//
+//
+//
+	{
+	return KErrNone;
+	}
+
+LOCAL_C void FsFileTempFinishL(CFsRequest* aRequest,TFileName& aN,TInt aH)
+	{
+
+	aRequest->WriteL(KMsgPtr2,aRequest->Src().Drive());
+	aRequest->WriteL(KMsgPtr2,aN,2);
+	TPtrC8 pH((TUint8*)&aH,sizeof(TInt));
+	aRequest->WriteL(KMsgPtr3,pH);
+	}
+
+TInt TFsFileTemp::DoRequestL(CFsRequest* aRequest)
+//
+// Create a temporary file.
+//
+	{
+	__PRINT(_L("TFsFileTemp::DoRequestL(CFsRequest* aRequest)"));
+    
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+	
+    TFileName n;
+	TInt h;
+	r=aRequest->Drive()->FileTemp(aRequest,h,aRequest->Src().FullName().Mid(2),n,aRequest->Message().Int1());
+	if (r!=KErrNone)
+		return(r);
+	
+    TRAP(r, FsFileTempFinishL(aRequest,n,h))
+	CheckForLeaveAfterOpenL(r,aRequest,h);
+	aRequest->Session()->IncResourceCount();
+	
+    return(KErrNone);
+	}
+
+TInt TFsFileTemp::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r=ParseNoWildSubstPtr0(aRequest,aRequest->Src());
+	if (r!=KErrNone)
+		return(r);
+	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileTemp,&KCapFsPriFileTemp,&KCapFsROFileTemp, __PLATSEC_DIAGNOSTIC_STRING("Temp File")); 
+	if (r!=KErrNone)
+		return(r);
+	if (aRequest->Src().NameOrExtPresent())
+		return(KErrBadName);
+	return(r);
+	}
+
+
+TInt TFsFileRead::DoRequestL(CFsRequest* aRequest)
+//
+// Read from a file.
+//
+	{
+	
+	__PRINT(_L("TFsFileRead::DoRequestL(CFsRequest* aRequest)"));
+	__PRINT1(_L("aRequest->Session() = 0x%x"),aRequest->Session());
+
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+	__ASSERT_DEBUG(msgRequest.CurrentOperationPtr() != NULL, Fault(EBadOperationIndex));
+	TMsgOperation& currentOperation = msgRequest.CurrentOperation();
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	TInt r = file->CheckMount();
+	__PRINT1(_L("share->CheckMount() returned = %d"),r);
+	if (r!=KErrNone)
+		return(r);
+
+	TInt& len = currentOperation.iReadWriteArgs.iLength;
+	TInt& totalLen = currentOperation.iReadWriteArgs.iTotalLength;
+	TInt64 pos = currentOperation.iReadWriteArgs.iPos;
+	TInt& offset = currentOperation.iReadWriteArgs.iOffset;
+
+	// Fair scheduling - 
+	// Needs extended file API to work (so that we can sepcify an offset)
+	// Also needs a separate drive thread to prevent excessive stack usage
+	len = Min(len, totalLen);
+	if (file->ExtendedFileInterfaceSupported() && !FsThreadManager::IsDriveSync(aRequest->DriveNumber(), EFalse))
+		{
+		len = Min(len, file->FairSchedulingLen());
+		}
+	if (pos == KCurrentPosition64)
+		pos = share->iPos;
+
+	currentOperation.iReadWriteArgs.iPos = pos;
+
+	__ASSERT_DEBUG(len > 0, Fault(EInvalidReadLength));
+	__ASSERT_DEBUG(len <= totalLen, Fault(EInvalidReadLength));
+
+	// The mount and any extensions must all support local buffers in order to support
+	// internally generated requests (ie - requests originating from plugins)
+	if ((aRequest->Message().Handle() == KLocalMessageHandle || !currentOperation.iClientRequest) && !file->LocalBufferSupport())
+		{
+		r = KErrNotSupported;
+		}
+
+	TInt reqLen = len;
+	if(r == KErrNone)
+		{
+		if (currentOperation.iClientRequest)	
+			{
+			// Current operation points to a descriptor
+			// The request originated from a client (with a normal message handle) or a plugin (KLocalMessageHandle)
+			TRAP(r,file->ReadL(pos, len, (TPtr8*) aRequest->Message().Ptr0(), aRequest->Message(), offset))
+			}
+		else
+			{
+			// Current operation points to a local buffer
+			// The request originated from the file server (e.g. file cache) with a local message handle (KLocalMessageHandle)
+			TPtr8 dataDesc((TUint8*) currentOperation.iReadWriteArgs.iData + currentOperation.iReadWriteArgs.iOffset, len, len);
+			const RLocalMessage msg;
+			TRAP(r,file->ReadL(pos, len, &dataDesc, msg, 0));
+			}
+		}
+
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+	CCacheManager* manager = CCacheManagerFactory::CacheManager();
+	if (manager)
+		{
+		manager->Stats().iUncachedPacketsRead++;
+		manager->Stats().iUncachedBytesRead+= len;
+		}
+#endif
+
+//RDebug::Print(_L("ReadR: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
+
+
+#if defined (_DEBUG_READ_AHEAD)
+	RDebug::Print(_L("ReadR: req %08X pos %ld\t len %d nextPos %ld file %08X\n"), aRequest, pos, len, pos + len, file);
+#endif
+
+	offset+= len;
+	currentOperation.iReadWriteArgs.iPos+= len;
+	totalLen-= reqLen;
+
+
+	// update the file share's position IF this request came from the client
+	if (share && r==KErrNone && currentOperation.iClientRequest)
+		{
+		__e32_atomic_store_ord64(&share->iPos, pos + len);
+		}
+
+	// re-issue request if not complete (to support fair scheduling)
+	if (r == KErrNone && totalLen > 0)
+		return CFsRequest::EReqActionBusy;	// dispatch request again to back of queue
+
+	return(r);
+	}
+
+
+TInt TFsFileRead::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+
+	TInt r = DoInitNoParse(aRequest);
+	if (r != KErrNone)
+		return r;
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	TMsgOperation* msgOp = msgRequest.CurrentOperationPtr();
+	if (!msgOp)	// initialised already ?
+		{
+		r = msgRequest.PushOperation(TFsFileRead::Complete);
+		if (r != KErrNone)
+			return r;
+		msgOp = msgRequest.CurrentOperationPtr();
+		}
+	// try to serialize requests to prevent asynchronous requests being processed out of sequence -
+	// this isn't possible if a plugin is loaded as this may issue it's own requests 
+	if (!share->RequestStart(&msgRequest))
+		return CFsRequest::EReqActionPending;
+
+	TDrive& drive = share->File().Drive();
+
+	TInt64 pos, reqPos;
+	TInt len, reqLen;
+
+	reqLen = len = aRequest->Message().Int1();
+
+	if(aRequest->IsDescData(KMsgPtr2))
+		{//-- 64-bit file addressing, absolute read position is TInt64
+			TPckg<TInt64> pkPos(reqPos);
+			aRequest->ReadL(KMsgPtr2, pkPos);
+		}
+	else
+		{
+		if(aRequest->Message().Int2() == (TInt)I64LOW(KCurrentPosition64))
+			reqPos = KCurrentPosition64; // Position is KCurrentPosition64 (-1)
+		else //-- legacy, RFile addressing
+			reqPos = MAKE_TINT64(0,aRequest->Message().Int2());	// Position is absolute value < 4GB, it's TUint
+		}
+	
+    msgOp->iClientPosition = pos = reqPos;
+	
+	if (len < 0)
+		return KErrArgument;
+
+	if (len == 0)
+		return CFsRequest::EReqActionComplete;
+	
+	if (pos == KCurrentPosition64)
+		pos = share->iPos;
+
+	const TInt64 fileSize = file->CachedSize64();
+	if (pos > fileSize)
+		pos = fileSize;
+
+	if ((r = file->CheckLock64(share,pos,len)) != KErrNone)
+		return r;
+
+	
+	TDes8* pD = (TDes8*) aRequest->Message().Ptr0();
+
+	if((share->iMode & EFileReadAsyncAll) && (aRequest->Message().ClientStatus() != NULL))
+		{
+		drive.Lock();
+		if (pos + len > fileSize)
+			{
+			r = share->File().AddAsyncReadRequest(share, reqPos, reqLen, aRequest);
+			drive.UnLock();
+			return (r == KErrNone)?CFsRequest::EReqActionComplete:r;
+			}
+		drive.UnLock();
+		}
+	
+    if (pos == fileSize)
+		{
+		__e32_atomic_store_ord64(&share->iPos, pos);
+		r = aRequest->Write(KMsgPtr0, KNullDesC8);
+		return(r == KErrNone?CFsRequest::EReqActionComplete:r);
+		}
+	
+    if (pos + len > fileSize)
+		{
+		// filesize - pos shall of TInt size
+		// Hence to suppress warning
+		len = (TInt)(fileSize - pos);
+		}
+
+	msgOp->Set(pos, len, (TDesC8*) pD);
+
+//RDebug::Print(_L("ReadI: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
+
+#if defined (_DEBUG_READ_AHEAD)
+	RDebug::Print(_L("ReadI: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
+#endif
+
+	return KErrNone;
+	}
+
+TInt TFsFileRead::PostInitialise(CFsRequest* aRequest)
+	{
+	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
+	CFileCB* file = &share->File();
+	TInt r = KErrNone;
+
+	CFileCache* fileCache = file->FileCache();
+	if (fileCache)
+		{
+		r = fileCache->ReadBuffered(*(CFsMessageRequest*)aRequest, share->iMode);
+
+		// if we're not reading from cache, force read ahead position & length to be recalculated
+		if (r == KErrNone)
+			fileCache->ResetReadAhead();
+		}
+	
+	return r;
+	}
+
+TInt TFsFileRead::Complete(CFsRequest* aRequest)
+	{
+//		RDebug::Print(_L("TFsFileRead::Complete() aRequest %08X"), aRequest); 
+
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+	
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	// Flag the request as having ended to allow another async read to occur
+	share->RequestEnd(&msgRequest);
+
+
+	// issue read-ahead
+	CFileCache* fileCache = file->FileCache();
+	if (fileCache && msgRequest.LastError() == KErrNone)
+		fileCache->ReadAhead(msgRequest, share->iMode);
+
+	return CFsRequest::EReqActionComplete;
+	}
+
+
+void GetFileFromScratch(CFsRequest* aRequest, CFileShare*& aShare, CFileCB*& aFile)
+	{
+
+	TInt64 scratchValue = aRequest->ScratchValue64();
+	TBool scratchValueIsShare  I64HIGH(scratchValue);
+	TUint32 scratchValueLow = I64LOW(scratchValue);
+	
+	aShare = NULL;
+	aFile = NULL;
+
+	if (scratchValueIsShare)
+		{
+		aShare = (CFileShare*) scratchValueLow;
+		if (aShare)
+			aFile = &aShare->File();
+		}
+	else
+		{
+		aFile = (CFileCB*) scratchValueLow;
+		}
+	}
+
+/**
+    Common init preamble for TFsFileWrite::Initialise() and TFsFileWrite::DoRequestL()
+    
+    @param   aShare     pointer to the file share
+    @param   aFile      pointer to the file object this function is called for
+    @param   aPos       file position to write data. Note that it can be KCurrentPosition64 i.e. KMaxTUint64
+    @param   aLen       length of the data to write
+    @param   aFileSize  current file size
+    @param   aFsOp      File Server message code. See TFsMessage. It must be ether EFsFileWrite for normal write, or EFsFileWriteDirty when file cache flushes dirty data
+*/
+
+TInt TFsFileWrite::CommonInit(CFileShare* aShare, CFileCB* aFile, TInt64& aPos, TInt& aLen, TInt64 aFileSize, TFsMessage aFsOp)
+	{
+	
+    if (aShare && aPos==KCurrentPosition64)
+		{//-- write to the current position in the file
+		aPos = aShare->iPos;
+		}
+
+	if(aPos > aFileSize)
+		aPos = aFileSize;
+
+        //-- check that the new position won't exceed maximum file size
+        {
+        const TUint64 endPos = aPos+aLen;
+
+	    //-- Large file mode check. Legacy RFile size can't exceed 2G-1
+        if(aShare && !(aShare->IsFileModeBig()) && (endPos > KMaxLegacyFileSize))
+		    return KErrTooBig;
+
+        //-- check CMountCB limitation on maximum file size
+        if(endPos > aFile->MaxSupportedSize())
+            return KErrNotSupported; //-- this is for the sake of error codes consistency; current FSYs return 
+                                     //-- this code in the case of accessing a file beyond its limit
+       }
+
+	if (aShare)
+		{
+		TInt r;
+		if ((r=aFile->CheckLock64(aShare,aPos,aLen))!=KErrNone)
+			return(r);
+		}
+
+    ASSERT(aFsOp == EFsFileWrite || aFsOp == EFsFileWriteDirty);
+    if(aFsOp == EFsFileWrite)
+        {//-- this call is originated from explicit file write operation. Set 'Archive' attribute and new file time.
+        aFile->SetArchiveAttribute(); //-- it will also set KEntryAttModified
+        }
+    else
+        {//-- don't touch data and attributes if it is cache flushing dirty data
+        aFile->iAtt |= KEntryAttModified;
+        }
+
+
+	return KErrNone;
+	}
+
+void TFsFileWrite::CommonEnd(CFsMessageRequest* aMsgRequest, TInt aRetVal, TUint64 aInitSize, TUint64 aNewSize, TInt64 aNewPos, TBool aFileWrite)
+//
+// Common end for TFsFileWrite::DoRequestL() and CFileCache::WriteBuffered()
+//
+	{
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aMsgRequest, share, file);
+	CFileCache* fileCache = file->FileCache();
+	ASSERT(aFileWrite || fileCache);
+
+	TMsgOperation& currentOperation = aMsgRequest->CurrentOperation();
+
+	if (aRetVal == KErrNone || aRetVal == CFsRequest::EReqActionComplete)
+		{
+		if (share)
+			{
+			__e32_atomic_store_ord64(&share->iPos, aNewPos);
+			}
+		
+		if ((TUint64)aNewPos > aNewSize)
+			{
+			if(aFileWrite)
+				file->SetSize64(aNewPos, EFalse);
+			else
+				fileCache->SetSize64(aNewPos);
+			aNewSize = aNewPos;
+			}
+		
+		// ensure cached file is at least as big as uncached file
+		if (fileCache && fileCache->Size64() < aNewPos)
+			{
+			file->SetCachedSize64(aNewPos);
+			}
+		
+		// Service async reads if the file has grown & this is the last fair-scheduled request
+		
+		// If the file has grown, flag this and call CFileCB::NotifyAsyncReaders()
+		// later in TFsFileWrite::Complete() - we need to delay the call because
+		// CFileCB::NotifyAsyncReaders() may requeue a request which will cause 
+		// the drive thread to spin because this file share is still marked as in use
+		// (by CFileShare::RequestStart())
+		if((aNewSize > aInitSize) && (currentOperation.iReadWriteArgs.iTotalLength == 0))
+			{
+			file->SetNotifyAsyncReadersPending(ETrue);
+			}
+		
+        file->iAtt |= KEntryAttModified;
+
+		}
+	else if (aRetVal == KErrCorrupt)
+		file->SetFileCorrupt(ETrue);
+	else if (aRetVal == KErrBadPower || (aRetVal == KErrAbort && !PowerOk()))
+		file->SetBadPower(ETrue);
+
+	file->ResetReadAhead();
+	aMsgRequest->SetFreeChanged(aNewSize != aInitSize);
+	}
+
+TInt TFsFileWrite::DoRequestL(CFsRequest* aRequest)
+//
+// Write to a file.
+//
+	{
+	__PRINT(_L("TFsFileWrite::DoRequestL(CFsRequest* aRequest)"));
+
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+	__ASSERT_DEBUG(msgRequest.CurrentOperationPtr() != NULL, Fault(EBadOperationIndex));
+	TMsgOperation& currentOperation = msgRequest.CurrentOperation();
+
+	TInt r;
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	TInt64 initSize = file->Size64();
+
+	r = file->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+
+
+	TInt& len = currentOperation.iReadWriteArgs.iLength;
+
+	// Fair scheduling - 
+	// Needs extended file API to work (so that we can specify an offset)
+	// Also needs a separate drive thread to prevent excessive stack usage
+	len = Min(len, currentOperation.iReadWriteArgs.iTotalLength);
+	if (file->ExtendedFileInterfaceSupported() && !FsThreadManager::IsDriveSync(aRequest->DriveNumber(), EFalse))
+		{
+		len = Min(len, file->FairSchedulingLen());
+		}
+
+	__ASSERT_DEBUG(len <= currentOperation.iReadWriteArgs.iTotalLength, Fault(EInvalidWriteLength));
+	
+	
+    const TFsMessage fsOp = (TFsMessage)aRequest->Operation()->Function(); 
+    r = CommonInit(share, file, currentOperation.iReadWriteArgs.iPos, len, initSize, fsOp);
+
+	if (r != KErrNone)
+		return r;
+	
+    TInt64 pos = currentOperation.iReadWriteArgs.iPos;
+
+	TInt64 upos = pos+len;
+	if (upos > initSize)
+		{
+		r = CheckDiskSpace(upos - initSize, aRequest);
+        if(r != KErrNone)
+            return r;
+		}
+
+	// The mount and any extensions must all support local buffers in order to support
+	// internally generated requests (ie - requests originating from plugins)
+	if ((aRequest->Message().Handle() == KLocalMessageHandle || !currentOperation.iClientRequest) && !file->LocalBufferSupport())
+		{
+		r = KErrNotSupported;
+		}
+
+	if(r == KErrNone)
+		{
+		if (currentOperation.iClientRequest)
+			{
+			TRAP(r,file->WriteL(pos, len, (const TPtrC8*) aRequest->Message().Ptr0(), aRequest->Message(), currentOperation.iReadWriteArgs.iOffset))
+			}
+		else
+			{
+			TPtr8 dataDesc((TUint8*) currentOperation.iReadWriteArgs.iData + currentOperation.iReadWriteArgs.iOffset, len, len);
+			const RLocalMessage msg;
+			TRAP(r,file->WriteL(pos, len, &dataDesc, msg, 0));
+			}
+		}
+
+//RDebug::Print(_L("WriteR: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+	CCacheManager* manager = CCacheManagerFactory::CacheManager();
+	if (manager)
+		{
+		manager->Stats().iUncachedPacketsWritten++;
+		manager->Stats().iUncachedBytesWritten+= len;
+		}
+#endif
+
+	if (r == KErrNone)
+		{
+		// update position, offset  & length remaining
+		currentOperation.iReadWriteArgs.iOffset+= len;
+		currentOperation.iReadWriteArgs.iPos+= len;
+		currentOperation.iReadWriteArgs.iTotalLength-= len;
+		}
+	TUint64 currentSize = MAKE_TUINT64(file->iBody->iSizeHigh,file->iSize);
+	CommonEnd(&msgRequest, r, initSize, currentSize, pos+len, ETrue);
+	
+	// re-issue request if not complete (to support fair scheduling)
+	if (r == KErrNone && currentOperation.iReadWriteArgs.iTotalLength > 0)
+		return CFsRequest::EReqActionBusy;	// dispatch request again to back of queue
+
+	return(r);
+	}
+
+TInt TFsFileWrite::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+
+	TInt r = DoInitNoParse(aRequest);
+	if (r != KErrNone)
+		return r;
+
+	// If the drive has been dismounted, don't even attempt to write to the file as that
+	// will create dirty data which can then not be flushed without hitting ASSERTs etc.
+	if (!FsThreadManager::IsDriveAvailable(aRequest->DriveNumber(), EFalse))
+		return KErrNotReady;
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	// Bail out if there's a new mount which isn't ours - this would fail
+	// later on anyway when TFsFileWrite::DoRequestL() called CFileCB::CheckMount()
+	if ( !file->Drive().IsCurrentMount(file->Mount())  )
+		return KErrDisMounted;
+
+
+	TMsgOperation* msgOp = msgRequest.CurrentOperationPtr();
+	if (!msgOp)	// initialised already ?
+		{
+		r = msgRequest.PushOperation(TFsFileWrite::Complete);
+		if (r != KErrNone)
+			return r;
+		msgOp = msgRequest.CurrentOperationPtr();
+		}
+	// try to serialize requests to prevent asynchronous requests being processed out of sequence -
+	// this isn't possible if a plugin is loaded as this may issue it's own requests 
+	if (share && !share->RequestStart(&msgRequest))
+		return CFsRequest::EReqActionPending;
+	
+	TInt64 pos;
+	
+	if(aRequest->IsDescData(KMsgPtr2))
+		{//-- 64-bit file addressing, absolute read position is TInt64
+			TPckg<TInt64> pkPos(pos);
+			aRequest->ReadL(KMsgPtr2, pkPos);
+		}
+	else
+		{
+		if(aRequest->Message().Int2() == (TInt)I64LOW(KCurrentPosition64))
+			pos = KCurrentPosition64;// Position is KCurrentPosition64 (-1)
+		else
+			pos = MAKE_TINT64(0,aRequest->Message().Int2());// Position is absolute value < 4GB, it's a TUint type
+		}
+
+	msgOp->iClientPosition = pos;
+	TInt len = aRequest->Message().Int1();
+
+	TDesC8* pD = (TDes8*) aRequest->Message().Ptr0();
+	
+	if (len == 0)
+		return CFsRequest::EReqActionComplete;
+	
+	if (len < 0)
+		return KErrArgument;
+	
+	//if this request was sent down from a plugin, then we want to
+	//ignore the mode that the files was opened in.
+	if (share && !msgRequest.IsPluginRequest())
+		{
+		if ((share->iMode & EFileWrite)==0 || 
+			(share->iMode & KFileShareMask) == EFileShareReadersOnly)
+			{
+			return(KErrAccessDenied);
+			}
+		}
+	
+	
+    const TFsMessage fsOp = (TFsMessage)aRequest->Operation()->Function(); 
+    r = CommonInit(share, file, pos, len, file->CachedSize64(), fsOp);
+	if (r != KErrNone)
+		return r;
+
+	msgOp->Set(pos, len, pD);
+
+	return KErrNone;
+	}
+
+
+TInt TFsFileWrite::PostInitialise(CFsRequest* aRequest)
+	{
+	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
+	CFileCB* file = &share->File();
+	TInt r = KErrNone;
+
+	CFileCache* fileCache = file->FileCache();
+	if (fileCache)
+		{
+		// If there's no data left proceed straight to completion stage
+		// This can happen when re-posting a completed write request to 
+		// start the dirty data timer
+		if (((CFsMessageRequest*) aRequest)->CurrentOperation().iReadWriteArgs.iTotalLength == 0)
+			return CFsRequest::EReqActionComplete;
+
+		r = fileCache->WriteBuffered(*(CFsMessageRequest*)aRequest, share->iMode);
+		}
+	
+	return r;
+	}
+
+TInt TFsFileWrite::Complete(CFsRequest* aRequest)
+	{
+	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
+	
+
+	CFileShare* share;
+	CFileCB* file;
+	GetFileFromScratch(aRequest, share, file);
+
+	if (share)
+		share->RequestEnd(&msgRequest);
+
+	if (file->NotifyAsyncReadersPending())
+		file->NotifyAsyncReaders();
+	
+	return CFsRequest::EReqActionComplete;
+	}
+
+TInt TFsFileLock::DoRequestL(CFsRequest* aRequest)
+//
+// Lock a region of the file.
+//
+	{
+
+	__PRINT(_L("TFsFileLock::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+
+	// We must wait for ALL shares to have no active requests (see RequestStart())
+	// and post this request to the back of the queue if there are any. This is to 
+	// avoid a fair-scheduled write from writing to a locked region of a file
+	CSessionFs* session = aRequest->Session();
+	if (session)
+		{
+		TBool fileInUse = EFalse;
+		session->Handles().Lock();
+		TInt count = session->Handles().Count();
+		CFileCB* file = &share->File();
+
+		for (TInt n=0; n<count; n++)
+			{
+			CObjPromotion* obj = (CObjPromotion*)session->Handles()[n];
+			if (obj != NULL && 
+				obj->UniqueID() == FileShares->UniqueID() &&
+				(file == &((CFileShare*) obj)->File()) &&
+				((CFileShare*) obj)->RequestInProgress())
+				{
+				CFsMessageRequest& msgRequest = *(CFsMessageRequest*)aRequest;
+				if(msgRequest.IsPluginRequest())
+					break;
+
+				fileInUse = ETrue;
+				break;
+				}
+			}
+		session->Handles().Unlock();
+		if (fileInUse)
+			return CFsRequest::EReqActionBusy;
+		}
+	
+	TInt64 pos, length;
+	if(aRequest->IsDescData(KMsgPtr0))
+		{
+		TPckg<TInt64> pkPos(pos);
+		aRequest->ReadL(KMsgPtr0, pkPos);
+		}
+	else
+		{
+		pos = MAKE_TINT64(0, aRequest->Message().Int0());
+		}
+	
+    if(aRequest->IsDescData(KMsgPtr1))
+		{
+		TPckg<TInt64> pkLength(length);
+		aRequest->ReadL(KMsgPtr1, pkLength);
+		if(length <= 0)
+			User::Leave(ELockLengthZero);
+		}
+	else
+		{
+		length = aRequest->Message().Int1();
+		if(length <= 0) 
+			User::Leave(ELockLengthZero);
+		}
+	return(share->File().AddLock64(share, pos, length));
+	}
+
+TInt TFsFileLock::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileUnlock::DoRequestL(CFsRequest* aRequest)
+//
+// Unlock a region of the file.
+//
+	{
+	__PRINT(_L("TFsFileUnlock::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	
+	TInt64 pos, length;
+	
+    if(aRequest->IsDescData(KMsgPtr0))
+		{
+		TPckg<TInt64> pkPos(pos);
+		aRequest->ReadL(KMsgPtr0, pkPos);
+		}
+	else
+		{
+		pos = MAKE_TINT64(0, aRequest->Message().Int0());
+		}
+	
+    if(aRequest->IsDescData(KMsgPtr1))
+		{
+		TPckg<TInt64> pkLength(length);
+		aRequest->ReadL(KMsgPtr1, pkLength);
+		if(length <= 0)
+			User::Leave(EUnlockLengthZero);
+		}
+	else
+		{
+		length = aRequest->Message().Int1();
+		if(length <= 0) 
+			User::Leave(EUnlockLengthZero);
+		}
+	return(share->File().RemoveLock64(share, pos, length));
+	}
+
+TInt TFsFileUnlock::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileSeek::DoRequestL(CFsRequest* aRequest)
+//
+// Set the file position.
+//
+	{
+
+	__PRINT(_L("TFsFileSeek::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TInt64 size = share->File().CachedSize64();
+	TInt64 pos;
+	if(aRequest->IsDescData(KMsgPtr0))
+		{
+		TPckg<TInt64> pkPos(pos);
+		aRequest->ReadL(KMsgPtr0, pkPos);
+		}
+	else
+		{
+		pos = aRequest->Message().Int0();
+		}
+	
+	TInt r,t;
+	
+	if (share->iPos != pos)
+		share->File().ResetReadAhead();
+	
+	switch (aRequest->Message().Int1())
+		{
+	case ESeekCurrent:
+		pos+=share->iPos;
+		if (pos<0)
+			pos=0;
+		
+        if (pos>size)
+			pos=size;
+
+		// Large file mode check
+		if((!(share->IsFileModeBig())) && ((TUint64)pos > KMaxLegacyFileSize))
+			return (KErrTooBig);
+
+		break;
+	case ESeekEnd:
+		pos+=size;
+		if (pos<0)
+			pos=0;
+		if (pos>size)
+			pos=size;
+		// Large file mode check
+		if((!(share->IsFileModeBig())) && ((TUint64)pos > KMaxLegacyFileSize))
+			return (KErrTooBig);
+		
+        break;
+	case ESeekAddress:
+		t = (TUint)pos;
+		r = share->File().Address(t);
+		pos = (TUint)t;
+		if(KErrNone != r)
+			return(r);
+		goto writeBackPos;
+	case ESeekStart:
+		if (pos>=0)
+            {
+            share->iPos = pos;
+            return KErrNone;
+            }
+		return(KErrArgument);
+	default:
+		return(KErrArgument);
+		}
+	__e32_atomic_store_ord64(&share->iPos, pos);
+writeBackPos:
+	TPckgC<TInt64> pkNewPos(pos);
+	aRequest->WriteL(KMsgPtr2, pkNewPos);
+	return(KErrNone);
+	}
+
+TInt TFsFileSeek::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileFlush::DoRequestL(CFsRequest* aRequest)
+//
+// Commit any data in memory to the media.
+//
+	{
+
+	__PRINT(_L("TFsFileFlush::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+
+	// if any write requests are being fair scheduled, wait for them to complete
+	if (share->RequestInProgress())
+		return CFsRequest::EReqActionBusy;
+
+	// flush the write cache
+	TInt r;
+	CFileCache* fileCache = share->File().FileCache();
+	if (fileCache && (r = fileCache->FlushDirty(aRequest)) != CFsRequest::EReqActionComplete)
+	    {
+		//To be used in notification framework
+	    //CFsMessageRequest& msgRequest = (CFsMessageRequest&)*aRequest;
+	    //msgRequest.iUID = msgRequest.Message().Identity();
+		return r;
+	    }
+
+	if ((share->File().Att()&KEntryAttModified)==0)
+		return(KErrNone);
+	if ((share->iMode&EFileWrite)==0)
+		return(KErrAccessDenied);
+	r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+
+	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataL, EF32TraceUidFileSys, &share->File());
+	TRAP(r,share->File().FlushDataL());
+	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataLRet, EF32TraceUidFileSys, r);
+
+	return(r);
+	}
+
+TInt TFsFileFlush::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileSize::DoRequestL(CFsRequest* aRequest)
+//
+// Get the file size.
+//
+	{
+
+	__PRINT(_L("TFsFileSize::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TInt64 size = share->File().CachedSize64();
+	// Large file mode check and error handling is done at client library side.
+	// Return file size even if it is greater than 2GB - 1.
+	TPckgC<TInt64> pkSize(size);
+	aRequest->WriteL(KMsgPtr0, pkSize);
+	return(KErrNone);
+	}
+
+TInt TFsFileSize::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileSetSize::DoRequestL(CFsRequest* aRequest)
+//
+// Set the file size.
+//
+	{
+	__PRINT(_L("TFsFileSetSize::DoRequestL(CFsRequest* aRequest)"));
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	if ((share->iMode&EFileWrite)==0)
+		return(KErrAccessDenied);
+	TInt r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+
+	TInt64 size;
+	if(aRequest->IsDescData(KMsgPtr0))
+		{
+		TPckg<TInt64> pkSize(size);
+		aRequest->ReadL(KMsgPtr0, pkSize);
+		}
+	else
+		{
+		size = aRequest->Message().Int0();
+		}
+
+	if(size < 0)
+		User::Leave(ESizeNegative);
+	
+	// Large file mode check
+	if((!(share->IsFileModeBig())) && ((TUint64)size > KMaxLegacyFileSize))
+		return (KErrTooBig);
+	
+	CFileCB& file=share->File();
+
+	// flush the write cache
+	CFileCache* fileCache = share->File().FileCache();
+	if (fileCache && (r = fileCache->FlushDirty(aRequest)) != CFsRequest::EReqActionComplete)
+		return r;
+	
+	if (size==file.Size64())
+		return(KErrNone);
+	
+	TBool fileHasGrown = size > file.Size64();
+	if (fileHasGrown)
+		{
+		r = CheckDiskSpace(size - file.Size64(), aRequest);
+        if(r != KErrNone)
+            return r;
+
+		r=file.CheckLock64(share,file.Size64(),size-file.Size64());
+		}	
+	else
+		r=file.CheckLock64(share,size,file.Size64()-size);
+	if (r!=KErrNone)
+		return(r);
+	__PRINT1(_L("Owner mount size before SetSize() = %d"),I64LOW(file.Mount().Size()));
+	TRAP(r,file.SetSizeL(size))
+	if (r!=KErrNone)
+		{
+		//	Set size failed
+		__PRINT1(_L("SetSize() failed = %d"),r);
+		__PRINT1(_L("Owner mount size now = %d"),I64LOW(file.Mount().Size()));
+		return(r);
+		}
+	file.SetArchiveAttribute();
+	file.SetSize64(size, EFalse);
+	file.SetCachedSize64(size);
+
+	if(fileHasGrown)
+		file.NotifyAsyncReaders();	// Service outstanding async reads if the file has grown
+
+	return(r);
+	}
+
+TInt TFsFileSetSize::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileAtt::DoRequestL(CFsRequest* aRequest)
+//
+// Get the file attributes.
+//
+	{
+
+	__PRINT(_L("TFsFileAtt::DoRequestL(CFsRequest* aRequest)"));
+	
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+//	TInt att=(TInt)aRequest->FileShare()->File().Att()&KEntryAttMaskSupported;
+	TInt att=(TInt)share->File().Att();	// DRM: let ROM XIP attribute through
+	TPtrC8 pA((TUint8*)&att,sizeof(TInt));
+	aRequest->WriteL(KMsgPtr0,pA);
+	
+    return(KErrNone);
+	}
+
+TInt TFsFileAtt::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileSetAtt::DoRequestL(CFsRequest* aRequest)
+//
+// Set the file attributes.
+//
+	{
+	__PRINT(_L("TFsFileSetAtt::DoRequestL(CSessionFs* aSession)"));
+    
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+	
+    if ((share->iMode&EFileWrite)==EFalse)
+		return(KErrAccessDenied);
+	
+    TUint setAttMask=(TUint)(aRequest->Message().Int0());
+	TUint clearAttMask=(TUint)aRequest->Message().Int1();
+	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);
+
+	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
+	TRAP(r,share->File().SetEntryL(TTime(0),setAttMask,clearAttMask))
+	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
+
+	return(r);
+	}
+
+
+TInt TFsFileSetAtt::Initialise(CFsRequest* aRequest)
+//
+//	Call GetShareFromHandle to determine asynchronicity ***
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileModified::DoRequestL(CFsRequest* aRequest)
+//
+// Get the modified date and time.
+//
+	{
+	__PRINT(_L("TFsFileModified::DoRequestL(CFsRequest* aRequest)"));
+
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+        	
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TTime mod=share->File().Modified();
+	TPtrC8 pM((TUint8*)&mod,sizeof(TTime));
+	aRequest->WriteL(KMsgPtr0,pM);
+	
+    return(KErrNone);
+	}
+
+
+TInt TFsFileModified::Initialise(CFsRequest* aRequest)
+//
+//	Call GetShareFromHandle to determine asynchronicity ***
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileSetModified::DoRequestL(CFsRequest* aRequest)
+//
+// Set the modified date and time.
+//
+	{
+	__PRINT(_L("TFsFileSetModified::DoRequestL(CFsRequest* aRequest)"));
+    
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+
+	if ((share->iMode&EFileWrite)==EFalse)
+		return(KErrAccessDenied);
+	
+	TTime time;
+	TPtr8 t((TUint8*)&time,sizeof(TTime));
+	aRequest->ReadL(KMsgPtr0,t);
+
+	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, KEntryAttModified,0);
+	TRAP(r,share->File().SetEntryL(time,KEntryAttModified,0))
+	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
+
+	return(r);
+	}
+
+
+TInt TFsFileSetModified::Initialise(CFsRequest* aRequest)
+//
+//	Call GetShareFromHandle to determine asynchronicity ***
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+TInt TFsFileSet::DoRequestL(CFsRequest* aRequest)
+//
+// Set the attributes and the modified date and time.
+//
+	{
+	__PRINT(_L("TFsFileSet::DoRequestL(CFsRequest* aRequest)"));
+
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+	
+    if (share->File().Att()&KEntryAttReadOnly)
+		return(KErrAccessDenied);
+	
+    if ((share->iMode&EFileWrite)==0)
+		{
+		if(share->File().Drive().IsWriteProtected())
+			return(KErrAccessDenied);
+		}
+	
+    TTime time;
+	TPtr8 t((TUint8*)&time,sizeof(TTime));
+	aRequest->ReadL(KMsgPtr0,t);
+	TUint setAttMask=(TUint)(aRequest->Message().Int1()|KEntryAttModified);
+	TUint clearAttMask=(TUint)aRequest->Message().Int2();
+	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);//	Validate attributes
+
+	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
+	TRAP(r,share->File().SetEntryL(time,setAttMask,clearAttMask))
+	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
+
+	return(r);
+	}
+
+TInt TFsFileSet::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)
+//
+// The access to a file may be changed from share exclusive to share readers only or vice versa.
+// KErrAccessDenied is returned if the file has multiple readers.
+//
+	{
+	__PRINT(_L("TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TInt r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+	
+	const TFileMode currentMode = (TFileMode)share->iMode;
+	const TFileMode newMode = (TFileMode)aRequest->Message().Int0();
+	
+		// check argument 
+		// (only EFileShareExclusive and EFileShareReadersOnly are allowed)
+	if((newMode & ~EFileShareReadersOnly) != 0)
+		return KErrArgument;
+	
+		// check if the file is in EFileShareAny mode
+	if( (currentMode & EFileShareAny) ||
+	    // or the file has been opened for writing in EFileShareExclusive mode, 
+		// and an attempt is made to change the access mode to EFileShareReadersOnly
+		((currentMode & EFileWrite) && 
+		 (currentMode & KFileShareMask) == EFileShareExclusive && 
+		 newMode == EFileShareReadersOnly) )
+		return KErrAccessDenied;
+
+		// check if an attempt is made to change the share mode to EFileShareExclusive
+		// while the file has multiple readers
+	if (newMode == EFileShareExclusive && (currentMode & KFileShareMask) != EFileShareExclusive)
+		{ 
+		// Check no other CFileCB is reading the file.
+		FileShares->Lock();
+		TInt count=FileShares->Count();
+		TBool found=EFalse;
+		while(count--)
+			{
+			CFileShare* fileShare=(CFileShare*)(*FileShares)[count];
+			if (&fileShare->File()==&share->File())
+				{
+				if (found)
+					{
+					FileShares->Unlock();
+					return(KErrAccessDenied);
+					}
+				found=ETrue;
+				}
+			}
+		FileShares->Unlock();
+		}
+	share->iMode&=~KFileShareMask;
+	share->iMode|=newMode;
+	share->File().SetShare(newMode);
+	return(KErrNone);
+	}
+
+
+TInt TFsFileChangeMode::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r = DoInitNoParse(aRequest);
+	if(r != KErrNone)
+		return r;
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	if(CompareResource(share->File().FileName().Mid(2)) )
+		{
+		if(!KCapFsFileChangeMode.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("File Change Mode")))
+			return KErrPermissionDenied;
+		}
+	return KErrNone;
+	}
+
+
+TInt TFsFileRename::DoRequestL(CFsRequest* aRequest)
+//
+// Rename the file if it was openned EFileShareExclusive
+//
+	{
+	__PRINT(_L("TFsFileRename::DoRequestL(CFsRequest* aRequest)"));
+
+    TInt r = CheckDiskSpace(0, aRequest);
+    if(r != KErrNone)
+        return r;
+
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	r=share->CheckMount();
+	if (r!=KErrNone)
+		return(r);
+
+	TInt currentMode=(share->iMode&KFileShareMask);
+	if ((currentMode&EFileShareAny) || (currentMode&EFileShareReadersOnly))
+		return(KErrAccessDenied); // File must be EFileShareExclusive
+
+	if ((share->iMode&EFileWrite)==0)
+		return(KErrAccessDenied); // File must have write permission
+
+	TPtrC filePath = aRequest->Dest().FullName().Mid(2);
+	CFileCB& file = share->File();
+
+	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameL, EF32TraceUidFileSys, 
+		(TUint) &file, filePath);
+	TRAP(r,file.RenameL(filePath));
+	TRACERETMULT1(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameLRet, EF32TraceUidFileSys, r);
+
+	// Re-write the file's folded name & re-calculate the hash
+	if (r == KErrNone)
+		{
+		TFileName filePathF;
+		filePathF.CopyF(filePath);
+	    TRAP(r, AllocBufferL(file.iFileNameF, filePathF));
+		file.iNameHash=CalcNameHash(*file.iFileNameF);
+		}
+
+	return(r);
+	}
+
+TInt TFsFileRename::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	TInt r=DoInitialise(aRequest);
+	if(r!=KErrNone)
+		return(r);
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TFileName newName;
+	TRAP(r,aRequest->ReadL(KMsgPtr0,newName));
+	if(r!=KErrNone)
+		return(r);
+	TDriveUnit currentDrive(share->File().Mount().Drive().DriveNumber());
+	TDriveName driveName=currentDrive.Name();
+	r=aRequest->Dest().Set(newName,&share->File().FileName(),&driveName);
+	if (r!=KErrNone)
+		return(r);
+	if (aRequest->Dest().IsWild())
+		return(KErrBadName);
+	TInt driveNo;
+	if ((r=RFs::CharToDrive(aRequest->Dest().Drive()[0],driveNo))!=KErrNone)
+		return(r);
+	TDrive& drive=TheDrives[driveNo];
+ 	if(drive.IsSubsted())
+		{
+		if ((drive.Subst().Length()+aRequest->Dest().FullName().Length())>(KMaxFileName+3))
+			return(KErrBadName);
+		TFileName n=drive.Subst();
+		n+=aRequest->Dest().FullName().Mid(3);
+		r=aRequest->Dest().Set(n,NULL,NULL);
+		if(r!=KErrNone)
+			return(r);
+		}
+
+	TDriveUnit newDrive(aRequest->Dest().Drive());
+	if (newDrive!=currentDrive)
+		return(KErrBadName);
+	if (IsIllegalFullName(aRequest->Dest().FullName().Mid(2)))
+		return(KErrBadName);
+	r=PathCheck(aRequest,aRequest->Dest().FullName().Mid(2),&KCapFsSysFileRename,&KCapFsPriFileRename,&KCapFsROFileRename, __PLATSEC_DIAGNOSTIC_STRING("File Rename"));
+	return(r);
+	}
+
+
+TInt TFsFileDrive::DoRequestL(CFsRequest* aRequest)
+//
+// Get the drive info for the file.
+//
+	{
+	__PRINT(_L("TFsFileDrive::DoRequestL(CFsRequest* aRequest)"));
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TDrive *dr = &share->File().Drive();
+
+	TPckgBuf<TInt> pkiF(dr->DriveNumber());		// copy drive number to user
+	aRequest->WriteL(KMsgPtr0, pkiF);
+
+	TDriveInfo di;								// copy drive info to user
+	dr->DriveInfo(di);
+	TPckgC<TDriveInfo> pkdiF(di);
+	aRequest->WriteL(KMsgPtr1, pkdiF);
+
+	return(KErrNone);
+	}
+
+
+TInt TFsFileDrive::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return(DoInitNoParse(aRequest));
+	}
+
+
+TInt TFsFileDuplicate::DoRequestL(CFsRequest* aRequest)
+//
+// Duplicate the received file handle ready for transfer to another process.
+// The new file handle is written back to the client in a a mangled form to prevent
+// it from being used. Calling TFsFileAdopt will de-mangle the handle.
+//
+	{
+	CFileShare* pS = (CFileShare*)aRequest->ScratchValue();
+
+	// get the file control block from the client's file share
+	CFileCB& fileCB = pS->File();
+
+	// Create a new file share and initialize it with the 
+	// client file share's file control block, position & mode
+	
+	CFileShare* pNewFileShare = new CFileShare(&fileCB);
+	if (pNewFileShare == NULL)
+		return KErrNoMemory;
+
+	// We need to call CFileCB::PromoteShare immediately after the CFileShare 
+	// instance is created since the destructor calls CFileCB::DemoteShare()
+	// which checks the share count is non-zero
+	pNewFileShare->iMode = pS->iMode;
+	fileCB.PromoteShare(pNewFileShare);
+	
+	
+	TInt r = fileCB.Open();	// increment the ref count
+
+	if (r == KErrNone)
+		TRAP(r, pNewFileShare->InitL());
+	__e32_atomic_store_ord64(&pNewFileShare->iPos, pS->iPos);
+	
+	// Add new file share to the global file share container
+	if (r == KErrNone)
+		TRAP(r, FileShares->AddL(pNewFileShare,ETrue));
+	
+	// Add new file share to list owned by this session
+	TInt newHandle;
+	if (r == KErrNone)
+		TRAP(r,newHandle = aRequest->Session()->Handles().AddL(pNewFileShare,ETrue));
+
+	if (r!=KErrNone)
+		{
+		pNewFileShare->Close();
+		return r;
+		}
+
+	newHandle^= KSubSessionMangleBit;
+
+	TPtrC8 pH((TUint8*)&newHandle, sizeof(TInt));
+	aRequest->WriteL(KMsgPtr3, pH);
+	aRequest->Session()->IncResourceCount();
+	return(KErrNone);
+	}
+
+TInt TFsFileDuplicate::Initialise(CFsRequest* aRequest)
+	{
+	TInt handle = aRequest->Message().Int0();
+	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
+	
+	// If the handle is invalid, either panic (CFsMessageRequest::Dispatch() will 
+	// panic if we return KErrBadHandle) or complete the request with KErrArgument.
+	// The latter case is the behaviour for the (deprecated) RFile::Adopt() to
+	// prevent a server from panicing if the passed file handle is invalid.
+	if(!share)
+		return aRequest->Message().Int1()?KErrBadHandle:KErrArgument;
+
+	aRequest->SetDrive(&share->File().Drive());
+	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
+	return(KErrNone);
+	}
+
+
+
+TInt TFsFileAdopt::DoRequestL(CFsRequest* aRequest)
+//
+// Adopt the passed file handle. This assumes that the handle has already been 
+// duplicated by calling TFsFileDuplicate and is therefore mangled.
+//
+	{
+	if (((CFileShare*)aRequest->ScratchValue()) == NULL)
+		return KErrBadHandle;
+	
+	TInt adoptType = aRequest->Message().Int1();
+	// EFileBigFile mode check
+	switch(adoptType)
+		{
+		case KFileAdopt32:
+			// Request is from RFile::Adopt or RFile::AdoptFromXXX: Force NO EFileBigFile
+			((CFileShare*)aRequest->ScratchValue())->iMode &= ~EFileBigFile;
+			break;
+		case KFileAdopt64:
+			// Request is from RFile64::AdoptFromXXX: Force EFileBigFile
+			((CFileShare*)aRequest->ScratchValue())->iMode |= EFileBigFile;
+			break;
+		case KFileDuplicate:
+			// Request is from RFile::Duplucate
+			// adopt original file mode - do nothing
+			break;
+		//default:
+			// Do nothing
+		}
+	
+	// De-mangle the existing sub-session handle and return it to the client
+	TInt newHandle = aRequest->Message().Int0() ^ KSubSessionMangleBit;
+
+	TPtrC8 pH((TUint8*)&newHandle,sizeof(TInt));
+	aRequest->WriteL(KMsgPtr3,pH);
+	return(KErrNone);
+	}
+
+TInt TFsFileAdopt::Initialise(CFsRequest* aRequest)
+	{
+	TInt handle = aRequest->Message().Int0() ^KSubSessionMangleBit;
+
+	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
+	// Normally returning KErrBadHandle will result in a panic, but when a server calls 
+	// RFile::AdoptXXX() and it's client has given it a bad handle then it's not a good 
+	// idea to panic the server. So we return KErrNone here and allow 
+	// TFsFileAdopt::DoRequestL() to return KErrBadHandle
+	if (share)
+		aRequest->SetDrive(&share->File().Drive());
+
+	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
+	return(KErrNone);
+	}
+
+
+TInt TFsFileName::DoRequestL(CFsRequest* aRequest)
+//
+// Get the name of a file. 
+// i.e. including the name & extension but excluding the drive and path
+//
+	{
+	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
+
+	// Search backwards until a backslash is found
+	// This should always succeed as this is a full pathname
+	TPtrC name(share->File().FileName());
+	TInt offset = name.LocateReverse('\\');
+	aRequest->WriteL(KMsgPtr0, name.Mid(offset+1));
+
+	return(KErrNone);
+	}
+
+TInt TFsFileName::Initialise(CFsRequest* aRequest)
+//
+// Get the full name of a file, including path and drive 
+//
+//
+	{
+	return InitialiseScratchToShare(aRequest);
+	}
+	
+	
+TInt TFsFileFullName::DoRequestL(CFsRequest* aRequest)
+//
+// Get the full name of a file, including path and drive 
+//
+	{
+	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
+
+	// Write the drive letter and ':'
+	TBuf<2> driveBuf(KDrivePath);
+	driveBuf[0]=TText('A' + share->File().Drive().DriveNumber());
+	aRequest->WriteL(KMsgPtr0, driveBuf);
+
+	// Write the file and path including leading '\'
+	TPtrC name(share->File().FileName());
+	aRequest->WriteL(KMsgPtr0, name, 2);
+	
+	return(KErrNone);
+	}
+
+
+TInt TFsFileFullName::Initialise(CFsRequest* aRequest)
+//
+//
+//
+	{
+	return InitialiseScratchToShare(aRequest);
+	}
+
+TInt TFsGetMediaSerialNumber::DoRequestL(CFsRequest* aRequest)
+//
+// Acquire capability from media and return serial number if supported.
+//
+    {
+    // Get request parameters
+    const TInt drvNum = aRequest->Message().Int1();
+
+	// Get media capability
+    TLocalDriveCapsV5Buf capsBuf;
+
+	TInt r = KErrNone;
+
+	// is the drive local?
+	if (!IsProxyDrive(drvNum))
+		{
+		// if not valid local drive, use default values in localDriveCaps
+		// if valid local drive and not locked, use TBusLocalDrive::Caps() values
+		// if valid drive and locked, hard-code attributes
+		r = GetLocalDrive(drvNum).Caps(capsBuf);
+		}
+	else  // this need to be made a bit nicer
+		{   
+		CExtProxyDrive* pD = GetProxyDrive(drvNum);
+		if(pD)
+			r = pD->Caps(capsBuf);
+		else
+			r = KErrNotReady;
+		}
+	
+	if (r != KErrNone)
+        return r;
+
+    TLocalDriveCapsV5& capsV5 = capsBuf();
+
+    // Return serial number if supported
+    if (capsV5.iSerialNumLength == 0)
+        return KErrNotSupported;
+
+    TPtrC8 snPtr(capsV5.iSerialNum, capsV5.iSerialNumLength);
+    aRequest->WriteL(KMsgPtr0, snPtr);
+
+	return KErrNone;
+    }
+
+TInt TFsGetMediaSerialNumber::Initialise(CFsRequest* aRequest)
+//
+// Validate drive number and its attributes passed in a request object.
+//
+    {
+    const TInt drvNum = aRequest->Message().Int1();
+
+    TInt nRes = ValidateDrive(drvNum, aRequest);
+    if(nRes != KErrNone)
+        return KErrBadName; //-- incorrect drive number
+
+    if(aRequest->Drive()->IsSubsted())
+        return KErrNotSupported; //-- the drive is substed, this operation doesn't make a sense
+    
+    if(!IsValidLocalDriveMapping(drvNum))
+	    return KErrNotReady;
+
+    return KErrNone;
+    }
+
+TInt TFsBlockMap::Initialise(CFsRequest* aRequest)
+	{
+	TInt r = DoInitNoParse(aRequest);
+	if(r!=KErrNone)
+		return r;
+
+	TInt blockMapUsage = aRequest->Message().Int2();
+	if ( blockMapUsage == EBlockMapUsagePaging )
+		{
+		CFileShare* share = (CFileShare*) aRequest->ScratchValue();
+		CFileCB& file = share->File();
+
+		// To determine whether the drive where this file resides is pageable, we need to locate 
+		// the specific TBusLocalDrive object first; querying the drive attributes directly from the 
+		// (composite) file system is no good as this API treats all slave file systems as "ROM & not pageable.
+		TBusLocalDrive* localDrive;
+		TInt r = file.LocalDrive(localDrive);
+		if (r != KErrNone)
+			return r;
+		TLocalDriveCapsV4Buf caps;
+		r = localDrive->Caps(caps);
+		if (r != KErrNone)
+			return r;
+		__PRINT4(_L("TFsBlockMap::Initialise, drive %d file %S iMediaAtt %08X iDriveAtt %08X\n"), file.DriveNumber(), &file.FileName(), caps().iMediaAtt, caps().iDriveAtt);
+		if ( !(caps().iDriveAtt & KDriveAttPageable))
+			return KErrNotSupported;
+		}
+
+	return KErrNone;
+	}
+
+TInt TFsBlockMap::DoRequestL(CFsRequest* aRequest)
+	{
+	__PRINT(_L("TFsBlockMap::DoRequestL(CFsRequest* aRequest)"));
+	__PRINT1(_L("aRequest->Session() = 0x%x"), aRequest->Session());
+
+	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
+
+	TInt r = share->CheckMount();
+
+	__PRINT1(_L("share->CheckMount() returned - %d"), r);
+	if ( r != KErrNone )
+		return(r);
+
+	SBlockMapInfo reqInfo;
+	SBlockMapArgs args;
+	TPckg<SBlockMapArgs> pkArgs(args);
+	aRequest->ReadL(KMsgPtr1, pkArgs);
+
+	CFileCB& file = share->File();
+	TInt64& reqStartPos = args.iStartPos;
+	TInt64 reqEndPos = args.iEndPos;
+
+	if ( ( reqStartPos > file.Size64() ) || ( reqStartPos < 0 ) )
+		return KErrArgument;
+
+	const TInt64 KReadToEOF = -1;
+	if ( reqEndPos != KReadToEOF )
+ 		{
+		if ( !( reqEndPos >= reqStartPos ) )
+			return KErrArgument;
+		}
+	else
+		reqEndPos = file.Size64();
+
+	// If the requested start position is equal to the size of the file
+	// then we read no data and return an empty BlockMap.
+	if ( reqStartPos == file.Size64() || reqEndPos == 0 || reqEndPos == reqStartPos )
+		{
+		TPckg<SBlockMapInfo> pkInfo(reqInfo);
+		TRAP(r,aRequest->WriteL(KMsgPtr0,pkInfo) );
+ 		if ( r == KErrNone )
+ 			return(KErrArgument);
+		else
+			return(r);
+		}
+	r = share->File().BlockMap(reqInfo, reqStartPos, reqEndPos);
+	TPckg<SBlockMapInfo> pkInfo(reqInfo);
+	aRequest->WriteL(KMsgPtr0, pkInfo);
+	aRequest->WriteL(KMsgPtr1, pkArgs);
+
+	return(r);
+	}
+
+#pragma warning( disable : 4705 )	// statement has no effect
+/**
+Default constructor
+*/
+EXPORT_C CFileCB::CFileCB()
+	{
+	}
+#pragma warning( default : 4705 )
+
+
+
+
+/**
+Destructor.
+
+Frees resources before destruction of the object.
+*/
+EXPORT_C CFileCB::~CFileCB()
+	{
+	// NB Must be careful to close the file cache BEFORE deleting iFileNameF
+	// as CFileCache may steal it (!)
+	if (FileCache())
+		FileCache()->Close();
+	if (iBody && iBody->iDeleteOnClose)
+		{
+		TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteL, EF32TraceUidFileSys, DriveNumber(), FileName());
+		TInt r;
+		TRAP(r, iMount->DeleteL(FileName()));
+		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteLRet, EF32TraceUidFileSys, r);
+		}
+
+	if(iMount)
+		iMount->Close();
+	if (iMountLink.iNext!=NULL)
+		{
+		iMountLink.Deque();
+		}
+	delete iFileName;
+	delete iFileNameF;
+	if (iFileLocks)
+		{
+		iFileLocks->Close();
+		delete iFileLocks;
+		}
+
+	delete iBody;
+	}
+
+/**
+    Initialise CFileCB object.
+    @internalTechnology
+
+    @param  aDrive
+    @param  aCreatedDrive
+    @param  aName           file name descriptor
+*/
+EXPORT_C void CFileCB::InitL(TDrive* aDrive, TDrive* aCreatedDrive, HBufC* aName)
+	{
+	// Take ownership of heap-allocated objects aName and aLock before attempting any memory allocation 
+	// to avoid leaking memory
+	iFileName = aName;
+
+    DoInitL(aDrive->DriveNumber());
+	iDrive=aDrive;
+	iCreatedDrive=aCreatedDrive;
+	TFileName tempName;
+	tempName.CopyF(*aName);
+	iFileNameF=tempName.AllocL();
+	iNameHash=CalcNameHash(*iFileNameF);
+	
+
+	
+	// see whether the file system supports the CFileCB extended API
+	MExtendedFileInterface* extendedFileInterface = NULL;
+	GetInterfaceTraced(CFileCB::EExtendedFileInterface, (void*&) extendedFileInterface, NULL);
+	iBody = new(ELeave)CFileBody(this, extendedFileInterface);
+
+	iMount=&iDrive->CurrentMount();
+	iBody->InitL();
+	User::LeaveIfError(iMount->Open());
+	
+	//-- create file locks array
+    ASSERT(!iFileLocks);
+    iFileLocks = new(ELeave) TFileLocksArray(KFileShareLockGranularity, _FOFF(TFileShareLock, iPosLow));
+
+    }
+	
+
+TInt CFileCB::FindLock(TInt aPosLow,TInt aPosHigh)
+	{
+	return FindLock64(aPosLow, aPosHigh);
+	}
+
+TInt CFileCB::AddLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
+	{
+	return AddLock64(aFileShare, aPos, aLength);
+	}
+
+TInt CFileCB::RemoveLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
+	{
+	return RemoveLock64(aFileShare, aPos, aLength);
+	}
+
+TInt CFileCB::CheckLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
+	{
+	return CheckLock64(aFileShare, aPos, aLength);
+	}
+
+/**
+    Remove any locks held by aFileShare.
+*/
+void CFileCB::RemoveLocks(CFileShare* aFileShare)
+	{
+
+	TInt i=0;
+	while (i<FileLocks().Count())
+		{
+		if (FileLocks()[i].MatchOwner(aFileShare))
+			FileLocks().Remove(i);
+		else
+			i++;
+		}
+	}
+
+
+void CFileCB::PromoteShare(CFileShare* aShare)
+//
+// Manages share promotion after the share has been added to the FilsShares container.
+//
+//  - Assumes the share has already been validated using ValidateShare()
+//
+//  - The count of promoted shares (ie - non-EFileShareReadersOrWriters) is incremented
+//	  to allow the share mode to be demoted when the last promoted share is closed.
+//
+	{
+	TShare reqShare = (TShare)(aShare->iMode & KFileShareMask);
+	if(reqShare != EFileShareReadersOrWriters)
+		{
+		iBody->iPromotedShares++;
+		iShare = reqShare;
+		}
+	}
+
+
+void CFileCB::DemoteShare(CFileShare* aShare)
+//
+// Manages share demotion after the share has been removed from the FileShares container.
+//
+//  - If the share being removed is not EFileShareReadersOrWriters, then the current
+//	  share mode may require demotion back to EFileShareReadersOrWriters.
+//
+//	- This is determined by the iPromotedShares count, incremented in PromoteShare()
+//
+	{
+	if((aShare->iMode & KFileShareMask) != EFileShareReadersOrWriters)
+		{
+		if(--iBody->iPromotedShares == 0)
+			{
+			// Don't worry if the file has never been opened as EFileShareReadersOrWriters
+			//  - in this case the CFileCB object is about to be closed anyway.
+			iShare = EFileShareReadersOrWriters;
+			}
+		}
+	__ASSERT_DEBUG(iBody->iPromotedShares>=0,Fault(EFileShareBadPromoteCount));
+	}
+
+
+RArray<TAsyncReadRequest>& CFileCB::AsyncReadRequests()
+//
+// Gets a reference to the pending asynchronous read requests for this file.
+//
+//  - The request is completed when all data is available or the request is cancelled.
+//
+	{
+	return(*iBody->iAsyncReadRequests);
+	}
+
+
+TInt CFileCB::AddAsyncReadRequest(CFileShare* aShareP, TInt64 aPos, TInt aLen, CFsRequest* aRequestP)
+//
+// Adds a pending asynchronous read request to the list.
+//
+//  - The request is completed when all data is available or the request is cancelled.
+//
+	{
+
+	__ASSERT_ALWAYS(aRequestP->Operation()->Function() == EFsFileRead, Fault(EBaseRequestMessage));
+	
+	TAsyncReadRequest req(aPos + aLen, aShareP, aRequestP);
+	TInt err = AsyncReadRequests().InsertInSignedKeyOrderAllowRepeats(req);
+	if(err != KErrNone)
+		return err;
+
+	aRequestP->SetCompleted(EFalse);
+	return KErrNone;
+	}
+
+
+TInt CFileCB::CancelAsyncReadRequest(CFileShare* aShareP, TRequestStatus* aStatusP)
+//
+// Cancels (and completes) an outstanding read request for the specified share.
+//
+//	- aStatusP == NULL cancels all outstanding read requests.
+//
+	{
+
+	TInt i=0;
+	Drive().Lock();
+	while (i < AsyncReadRequests().Count())
+		{
+		TAsyncReadRequest& req = AsyncReadRequests()[i];
+		if(req.CompleteIfMatching(aShareP, aStatusP, KErrCancel))
+			{
+			iBody->iAsyncReadRequests->Remove(i);
+			if(aStatusP != NULL)
+				{
+				Drive().UnLock();
+				return KErrNone;
+				}
+			}
+		else
+			{
+			i++;
+			}
+		}
+
+	Drive().UnLock();
+	return KErrNone;
+	}
+
+
+void CFileCB::NotifyAsyncReaders()
+//
+// Determine if any outstanding read requests require completion.
+//
+//  - Called whenever the file size changes (due to a write operation or SetSize)
+//
+//  - Any outstanding read requests are re-issued (rather then completed in the 
+//    context of the current operation so not to affect performance of the writer).
+//
+//  - Should the file size shrink before the request is serviced, the request will
+//    be added back onto the queue.
+//
+//	- A future optimisation may issue the request as data becomes available (which
+//	  would minimise the final latency between writer and reader) but the current
+//	  implementation reads all requested data in one operation.
+//
+	{
+	Drive().Lock();
+	
+	SetNotifyAsyncReadersPending(EFalse);
+
+	while(AsyncReadRequests().Count())
+		{
+		TAsyncReadRequest& req = AsyncReadRequests()[0];
+		if(req.iEndPos > CachedSize64())
+			break;
+
+		// Make a copy and then remove it from the queue before releasing the lock - 
+		// because the file server thread could append to the RArray and this might 
+		// cause a re-allocation which would move the whole array (!)
+		TAsyncReadRequest reqCopy = req;
+		AsyncReadRequests().Remove(0);
+		Drive().UnLock();
+
+		// allocate a new request, push a TMsgOperation onto the request's stack (duplicating
+		// the functionality of TFsFileRead::Initialise()) & dispatch the request
+		CFsClientMessageRequest* pRequest = NULL;
+		const TOperation& oP = OperationArray[EFsFileRead];
+		TInt r = RequestAllocator::GetMessageRequest(oP, reqCopy.iMessage, pRequest);
+		if (r != KErrNone)
+			{
+			reqCopy.iMessage.Complete(r);	// complete the client's message with an error
+			continue;
+			}
+		pRequest->Set(reqCopy.iMessage, oP, reqCopy.iSessionP);
+
+		r = DoInitNoParse(pRequest);
+		if (r != KErrNone)
+			{
+			pRequest->Complete(r);		// complete the client's message with an error
+			continue;
+			}
+		
+		r = pRequest->PushOperation(TFsFileRead::Complete);
+		if (r != KErrNone)
+			{
+			pRequest->Complete(r);		// complete the client's message with an error
+			continue;
+			}
+
+		pRequest->CurrentOperation().Set(
+			reqCopy.iEndPos - pRequest->Message().Int1(), 
+			pRequest->Message().Int1(), 
+			(TDes8*) pRequest->Message().Ptr0());
+
+		// don't call Initialise()
+		pRequest->SetState(CFsRequest::EReqStatePostInitialise);
+
+		pRequest->Dispatch();
+		Drive().Lock();
+		}
+	Drive().UnLock();
+	}
+
+
+/**
+Gets the address of the file that the file control block represents. 
+
+The default implementation returns KErrNotSupported and should only
+be overridden for ROM file systems.
+
+@param aPos On return, should contain the address of the file that
+            the file control block represents.
+
+@return KErrNone, if successful,otherwise one of the other system wide error
+        codes,
+*/
+EXPORT_C TInt CFileCB::Address(TInt& /*aPos*/) const
+	{
+
+	return(KErrNotSupported);
+	}
+
+
+/**
+Sets the archive attribute, KEntryAttArchive, in iAtt.
+*/
+EXPORT_C void CFileCB::SetArchiveAttribute()
+	{
+
+	iAtt|=KEntryAttArchive;
+	iAtt|=KEntryAttModified;
+	iModified.UniversalTime();
+	}
+
+
+EXPORT_C TInt CFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* /*aInput*/)
+	{
+	switch(aInterfaceId)
+		{
+		case EGetLocalDrive:
+			return Mount().LocalDrive((TBusLocalDrive*&) aInterface);
+		default:
+			return(KErrNotSupported);
+		}
+	}
+
+
+CFileCache* CFileCB::FileCache() const
+	{return iBody?iBody->iFileCache:NULL;}
+
+TBool CFileCB::LocalBufferSupport() const
+	{return iBody?iBody->iLocalBufferSupport:EFalse;}
+
+void CFileCB::SetLocalBufferSupport(TBool aEnabled)
+	{iBody->iLocalBufferSupport = aEnabled;}
+
+TInt CFileCB::CheckMount()
+//
+// Check that the media is still mounted.
+//
+	{
+
+	TDrive& d = Drive();
+	TInt r=d.CheckMount();
+	if (r!=KErrNone)
+		return(r);
+	if (&Mount() != &d.CurrentMount())
+		return(KErrDisMounted);
+	if (FileCorrupt())
+		return(KErrCorrupt);
+	if (BadPower())
+		{
+		if (PowerOk())
+			SetBadPower(EFalse);
+		else
+			return(KErrBadPower);
+		}
+	return(KErrNone);
+	}
+
+TInt64 CFileCB::CachedSize64() const
+	{
+	CFileCache* fileCache = iBody?iBody->iFileCache:NULL;
+	return fileCache? fileCache->Size64(): Size64();
+	}
+
+void CFileCB::SetCachedSize64(TInt64 aSize)
+	{
+	if (FileCache())
+		FileCache()->SetSize64(aSize);
+	else
+		SetSize64(aSize, EFalse);	// assume not locked
+	}
+
+/**
+Constructor.
+Locks the mount resource to which the shared file resides.
+
+@param aFileCB File to be shared.
+*/
+CFileShare::CFileShare(CFileCB* aFileCB)
+	: iFile(aFileCB)
+	{
+	AddResource(iFile->Mount());
+	}
+
+/**
+Destructor.
+
+Frees mount resource to which the shared file resides,
+removes share status from the shared file and finally closes
+the file.
+*/
+CFileShare::~CFileShare()
+	{
+	// We shouldn't be deleting the file share with a valid request queue or there will be request (& memory) leakage
+	__ASSERT_DEBUG(iCurrentRequest == NULL, Fault(ERequestQueueNotEmpty));
+
+	RemoveResource(iFile->Mount());
+	iFile->RemoveLocks(this);
+	iFile->DemoteShare(this);
+	iFile->CancelAsyncReadRequest(this, NULL);
+	iFile->Close();
+	}
+
+/**
+Check that the media is still mounted.
+
+@return KErrNone if successful.
+        KErrDisMounted if media has dismounted.
+        KErrCorrupted if shared file is corrupted.
+        KErrBadPower if insufficent power supply.
+        or other system wide error code.
+*/
+TInt CFileShare::CheckMount()
+	{
+	return File().CheckMount();
+	}
+
+/**
+Initialise the object
+*/
+void CFileShare::InitL()
+	{
+	DoInitL(iFile->Drive().DriveNumber());
+
+	// override the close operation so that we can flush the write cache if necessary
+	iRequest->Set(FileShareCloseOp,NULL);
+	iRequest->SetDriveNumber(DriveNumber());
+	iRequest->SetScratchValue((TUint)this);
+	}
+
+// Mark the start of a request - 
+// the is to prevent fair-scheduled async read/writes from being processed out of sequence. This is especially 
+// important when considering a client which appends to a file by issuing more than one asynchronous request as each
+// write request must be entirely satisfied before a subsequent request can append to the file
+TBool CFileShare::RequestStart(CFsMessageRequest* aRequest)
+	{
+	TBool ret;
+	
+	TDrive& drive = File().Drive();
+	drive.Lock();
+
+	if (iCurrentRequest == NULL || iCurrentRequest == aRequest)
+		{
+		iCurrentRequest = aRequest;
+		ret = ETrue;
+		}
+	else
+		{
+		// add to end of linked list of requests if there is already an active request for this share
+		CFsClientMessageRequest* request;
+		for (request = (CFsClientMessageRequest*) iCurrentRequest; request->iNext != NULL; request = request->iNext)
+			{
+			}
+		request->iNext = (CFsClientMessageRequest*) aRequest;
+		ret =  EFalse;
+		}
+
+	drive.UnLock();
+	return ret;
+	}
+
+
+// Mark the end of a request
+void CFileShare::RequestEnd(CFsMessageRequest* aRequest)
+	{
+	TDrive& drive = File().Drive();
+	drive.Lock();
+
+	if (aRequest == iCurrentRequest)
+		{
+		// Any requests in the queue ?
+		if (((CFsClientMessageRequest*) iCurrentRequest)->iNext)
+			{
+			iCurrentRequest = ((CFsClientMessageRequest*) aRequest)->iNext;
+			((CFsClientMessageRequest*) aRequest)->iNext = NULL;
+
+			// if the current request has been cancelled, cancel all requests in the queue
+			TInt lastError = aRequest->LastError();
+			if (lastError == KErrCancel || lastError == KErrNotReady)
+				{
+				// take ownership of this queue and make it invisible to anyone else by setting iCurrentRequest to NULL
+				CFsClientMessageRequest* currentRequest = (CFsClientMessageRequest*) iCurrentRequest;
+				iCurrentRequest = NULL;
+				drive.UnLock();
+				while(currentRequest)
+					{
+					CFsClientMessageRequest* nextRequest = ((CFsClientMessageRequest*) currentRequest)->iNext;
+					((CFsClientMessageRequest*) currentRequest)->iNext = NULL;
+					currentRequest->Complete(lastError);
+					currentRequest = nextRequest;
+					}
+				}
+			else
+				{
+				drive.UnLock();
+				iCurrentRequest->Dispatch(EFalse);
+				}
+			}
+		else	// queue empty
+			{
+			iCurrentRequest = NULL;
+			drive.UnLock();
+			}
+		}
+	else	// if (aRequest == iCurrentRequest)
+		{
+		drive.UnLock();
+		}
+	}
+
+TBool CFileShare::RequestInProgress() const
+	{
+	return (iCurrentRequest != NULL)?(TBool)ETrue:(TBool)EFalse;
+	}
+
+
+
+/**
+Initialise the object
+*/
+TInt TFsCloseFileShare::DoRequestL(CFsRequest* aRequest)
+//
+	{
+	__PRINT(_L("TFsCloseFileCache::DoRequestL()"));
+	
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+
+	// flush the write cache before closing the file share
+	TInt r;
+	CFileCache* fileCache = share->File().FileCache();
+	if (fileCache && (r = fileCache->FlushDirty(aRequest)) == CFsRequest::EReqActionBusy)
+		return r;
+	
+	return KErrNone;
+	}
+
+TInt TFsCloseFileShare::Complete(CFsRequest* aRequest)
+	{
+	__PRINT(_L("TFsCloseFileShare::Complete()"));
+	return TFsCloseObject::Complete(aRequest);
+	}
+
+
+TAsyncReadRequest::TAsyncReadRequest(TInt64 aEndPos, CFileShare* aOwningShareP, CFsRequest* aRequestP)
+//
+// Constructor for TAsyncReadRequest
+//	- Maintains information about oustanding async read requests
+//
+  : iEndPos(aEndPos), 
+	iOwningShareP(aOwningShareP)
+	{
+	iMessage  = aRequestP->Message();
+	iSessionP = aRequestP->Session();
+	iStatusP  = iMessage.ClientStatus();
+	}
+
+
+TBool TAsyncReadRequest::CompleteIfMatching(CFileShare* aShareP, TRequestStatus* aStatusP, TInt aError)
+//
+// Completes an asynchronous read request.
+//
+	{
+	if (iOwningShareP == aShareP && (aStatusP == NULL || aStatusP == iStatusP))
+		{
+		iMessage.Complete(aError);
+		return ETrue;
+		}
+
+	return EFalse;
+	}
+
+
+TInt TFsFileReadCancel::Initialise(CFsRequest* aRequest)
+//
+// Initialise function for RFile::ReadCancel [EFsReadCancel]
+//
+	{
+	return InitialiseScratchToShare(aRequest);
+	}
+
+
+TInt TFsFileReadCancel::DoRequestL(CFsRequest* aRequest)
+//
+// Request function for RFile::ReadCancel [EFsReadCancel]
+//
+	{
+	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
+	TRequestStatus* status = (TRequestStatus*)aRequest->Message().Ptr0();
+	share->File().CancelAsyncReadRequest(share, status);
+	return(KErrNone);
+	}
+
+void CFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+	{
+	TRACETHREADID(aMessage);
+	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadL, EF32TraceUidFileSys, 
+		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
+
+	iBody->iExtendedFileInterface->ReadL(aPos,aLength,aDes,aMessage,aOffset);
+
+	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadLRet, EF32TraceUidFileSys, KErrNone);
+	}
+
+void CFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+	{
+	TRACETHREADID(aMessage);
+	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteL, EF32TraceUidFileSys, 
+		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
+
+	iBody->iExtendedFileInterface->WriteL(aPos,aLength,aDes,aMessage,aOffset);
+
+	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteLRet, EF32TraceUidFileSys, KErrNone);
+	}
+
+void CFileCB::SetSizeL(TInt64 aSize)
+	{
+	TRACE3(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeL, EF32TraceUidFileSys, this, I64LOW(aSize), I64HIGH(aSize));
+
+	iBody->iExtendedFileInterface->SetSizeL(aSize);
+
+	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeLRet, EF32TraceUidFileSys, KErrNone);
+	}
+
+TBool CFileCB::ExtendedFileInterfaceSupported()
+	{
+	return iBody->ExtendedFileInterfaceSupported();
+	}
+
+TInt CFileCB::FairSchedulingLen() const
+	{
+	return iBody->iFairSchedulingLen;
+	}
+
+void CFileCB::SetNotifyAsyncReadersPending(TBool aNotifyAsyncReadersPending)
+//
+// Notify the asynchronous reader that a file has grown so that it may service outstanding async reads
+//
+	{
+	iBody->iNotifyAsyncReadersPending = aNotifyAsyncReadersPending;
+	}
+
+TBool CFileCB::NotifyAsyncReadersPending() const
+	{
+	return iBody->iNotifyAsyncReadersPending;
+	}
+
+
+void CFileCB::ResetReadAhead()
+	{
+	CFileCache* fileCache = FileCache();
+	if (fileCache)
+		fileCache->ResetReadAhead();
+	}
+
+void CFileCB::SetDeleteOnClose()
+	{
+	iBody->iDeleteOnClose = ETrue;
+	}
+
+TBool CFileCB::DeleteOnClose() const
+	{
+	return iBody->iDeleteOnClose;
+	}
+
+TInt CFileCB::GetInterfaceTraced(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
+	{
+	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterface, EF32TraceUidFileSys, aInterfaceId, aInput);
+
+	TInt r = GetInterface(aInterfaceId, aInterface, aInput);
+
+	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterfaceRet, EF32TraceUidFileSys, r, aInterface);
+
+	return r;
+	}
+
+CFileBody::CFileBody(CFileCB* aFileCB, CFileCB::MExtendedFileInterface* aExtendedFileInterface)
+  : iFileCB(aFileCB),
+	iExtendedFileInterface(aExtendedFileInterface ? aExtendedFileInterface : this),
+	iSizeHigh(0)
+	{
+	iFairSchedulingLen = TFileCacheSettings::FairSchedulingLen(iFileCB->DriveNumber());
+    iMaxSupportedFileSize = KMaxSupportedFileSize;
+	}
+
+
+CFileBody::~CFileBody()
+	{
+	if (iAsyncReadRequests)
+		{
+		iAsyncReadRequests->Close();
+		delete iAsyncReadRequests;
+		}
+	}
+
+
+void CFileBody::InitL()
+	{
+	iAsyncReadRequests = new(ELeave) RArray<TAsyncReadRequest>(KAsyncRequestArrayGranularity, _FOFF(TAsyncReadRequest, iEndPos));
+	}
+
+
+
+TInt TFsFileClamp::Initialise(CFsRequest* aRequest)
+//
+// Initialise function for RFile::Clamp [EFsFileClamp]
+//
+	{
+	TSecureId aUID = aRequest->Message().SecureId();	
+    if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
+		{
+		SSecurityInfo info;
+		info.iVendorId=0;
+		info.iCaps.iCaps[0]=0;
+		info.iCaps.iCaps[1]=0;
+		info.iSecureId=KEstartUidValue;
+		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
+		info.iSecureId=KFileServerUidValue;
+		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
+		return KErrPermissionDenied;
+		}
+
+	TInt r=DoInitialise(aRequest);
+	if(r!=KErrNone)
+		return r;
+
+	// The clamp API is only supported on non-removable media
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+	TDriveInfo di;
+	share->File().Drive().DriveInfo(di);
+	if (!(di.iDriveAtt & KDriveAttInternal))
+		r = KErrNotSupported;
+
+	return(r);
+	}
+
+
+TInt TFsFileClamp::DoRequestL(CFsRequest* aRequest)
+//
+// Request function for RFile::Clamp [EFsFileClamp]
+//
+	{
+	TInt r;
+
+	// Flush data for this file, if it is open for writing, before clamping
+	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
+
+	if (((share->iMode&EFileWrite)) || ((share->File().Att()&KEntryAttModified)))
+		{
+		r=share->CheckMount();
+		if (r!=KErrNone)
+			return(r);
+
+		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataL, EF32TraceUidFileSys, &share->File());
+		TRAP(r,share->File().FlushDataL());
+		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataLRet, EF32TraceUidFileSys, r);
+
+		if(r!=KErrNone)
+			return(r);
+		}
+
+	RFileClamp clamp;
+	r=aRequest->Drive()->ClampFile(aRequest->Src().FullName().Mid(2),
+									(TAny*)(&clamp));
+	// Write clamp information to user
+	TPckgC<RFileClamp> pkClamp(clamp);
+	aRequest->WriteL(KMsgPtr0, pkClamp);
+	return r;
+	}
+
+
+TInt TFsUnclamp::Initialise(CFsRequest* aRequest)
+//
+// Initialise function for RFs::Unclamp [EFsUnclamp]
+//
+	{
+	TSecureId aUID = aRequest->Message().SecureId();	
+    if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
+		{
+		SSecurityInfo info;
+		info.iVendorId=0;
+		info.iCaps.iCaps[0]=0;
+		info.iCaps.iCaps[1]=0;
+		info.iSecureId=KEstartUidValue;
+		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
+		info.iSecureId=KFileServerUidValue;
+		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
+		return KErrPermissionDenied;
+		}
+	RFileClamp clamp;
+	TPckg<RFileClamp> pkClamp(clamp);
+	aRequest->ReadL(KMsgPtr0, pkClamp);
+	TInt driveNo=(I64HIGH(clamp.iCookie[1]));
+	TDrive& drive=TheDrives[driveNo];
+	aRequest->SetDrive(&drive);
+	return KErrNone;
+	}
+
+
+TInt TFsUnclamp::DoRequestL(CFsRequest* aRequest)
+//
+// Request function for RFs::Unclamp [EFsUnclamp]
+//
+	{
+	RFileClamp clamp;
+	TPckg<RFileClamp> pkClamp(clamp);
+	aRequest->ReadL(KMsgPtr0, pkClamp);
+	TDrive* drive=aRequest->Drive();
+	CMountCB* mount=(CMountCB*)&(drive->CurrentMount());
+	return(drive->UnclampFile(mount,&clamp));
+	}
+
+CMountBody::CMountBody(CMountCB* aMountCB, CMountCB::MFileAccessor* aFileAccessor, CMountCB::MFileExtendedInterface* aFileInterface)
+//
+// Constructor for private body class
+//
+  : iMountCB(aMountCB),
+	iFileAccessor(aFileAccessor?aFileAccessor:this),
+	iFileExtendedInterface(aFileInterface?aFileInterface:this)
+	{
+	}
+
+CMountBody::~CMountBody()
+//
+// Destructor for private body class
+//
+	{
+	__ASSERT_DEBUG(iClampIdentifiers.Count() == 0, User::Invariant());
+	iClampIdentifiers.Close();
+	}
+
+TInt CMountBody::ClampFile(const TInt aDriveNo,const TDesC& aName,TAny* aHandle)
+	{
+	// Need CMountCB::MFileAccessor interface support
+	if(iFileAccessor==this)
+		return KErrNotSupported;
+
+	// Get unique identifier for the file
+	TInt64 uniqueId = 0;
+	TInt r = iFileAccessor->GetFileUniqueId(aName,uniqueId);
+	if(r!=KErrNone)
+			return r;
+
+	// Populate the RFileClamp clamp instance and store it in iClampIdentifiers
+	RFileClamp* newClamp = (RFileClamp*)aHandle;
+	newClamp->iCookie[0]=uniqueId;
+	newClamp->iCookie[1]=MAKE_TINT64(aDriveNo,++iClampCount);
+	r = iClampIdentifiers.InsertInOrder((const RFileClamp&)*newClamp,&CompareClampsByIdAndCount);
+	if(r != KErrNone)
+		return r;
+
+	// Indicate that (at least) one file is clamped on this drive
+	iMountCB->Drive().SetClampFlag(ETrue);
+	AddResource(*iMountCB);
+	return KErrNone;
+	}
+
+
+TInt CMountBody::UnclampFile(RFileClamp* aHandle)
+	{
+	// Need CMountCB::MFileAccessor interface support
+	if(iFileAccessor==this)
+		return KErrNotSupported;
+
+	TInt idx;
+	if((idx = iClampIdentifiers.Find((const RFileClamp&)*aHandle,&FindClampByIdAndCount)) < KErrNone)
+		{
+		// This file is not 'clamped'
+		return idx;
+		}
+
+	// If we're removing the last clamp and a dismount has been deferred (due to files being clamped),
+	// then DeferredDismount() will trigger a dismount: before this happens we need to flush all
+	// dirty data on this drive; 
+	TDrive& drive = iMountCB->Drive();
+	TInt noOfClamps = NoOfClamps();
+	if (noOfClamps == 1 && drive.DismountDeferred())
+		{
+		TInt r = drive.FlushCachedFileInfo(ETrue);
+		if (r == CFsRequest::EReqActionBusy)
+			return r;
+		}
+
+	RemoveResource(*iMountCB);
+	iClampIdentifiers.Remove(idx);
+
+	TInt r = KErrNone;
+	// If this was the last clamp, check for outstanding dismount requests
+	if (noOfClamps == 1)
+		{
+		ASSERT(NoOfClamps() == 0);
+		drive.SetClampFlag(EFalse);
+		if (drive.DismountDeferred())
+			r = drive.DeferredDismount();
+		}
+
+	return r;
+	}
+
+
+TInt CMountBody::IsFileClamped(const TInt64 aUniqueId)
+	{
+	// Need CMountCB::MFileAccessor interface support
+	if(iFileAccessor==this)
+		return KErrNotSupported;
+
+	// Encapsulate the unique identifier in an appropriate class
+	RFileClamp newClamp;
+	newClamp.iCookie[0]=aUniqueId;
+	// Search for (any) entry in iClampIdentifiers holding this value
+	TInt index=iClampIdentifiers.Find((const RFileClamp&)newClamp,&FindClampById);
+	return (index==KErrNotFound?0:1);
+	}
+
+TInt CMountBody::NoOfClamps()
+	{
+	// Need CMountCB::MFileAccessor interface support
+	if(iFileAccessor==this)
+		return KErrNotSupported;
+
+	// This will return zero if ClampFile has not previously been invoked
+	return iClampIdentifiers.Count();
+	}
+
+TInt CMountBody::CompareClampsById(const RFileClamp& aClampA, const RFileClamp& aClampB)
+	{
+	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return 1;
+	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return -1;
+	return 0;
+	}
+
+TInt CMountBody::CompareClampsByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
+	{
+	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return 1;
+	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return -1;
+	// Now compare the count values
+	if(I64LOW(aClampA.iCookie[1]) > I64LOW(aClampB.iCookie[1])) return 1;
+	if(I64LOW(aClampA.iCookie[1]) < I64LOW(aClampB.iCookie[1])) return -1;
+	return 0;
+	}
+
+TInt CMountBody::FindClampById(const RFileClamp& aClampA, const RFileClamp& aClampB)
+	{
+	return (TInt)(!CompareClampsById(aClampA, aClampB));
+	}
+
+
+TInt CMountBody::FindClampByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
+	{
+	return (TInt)(!CompareClampsByIdAndCount(aClampA, aClampB));
+	}
+
+void CMountBody::SetProxyDriveDismounted()
+	{
+	iProxyDriveDismounted = ETrue;
+	}
+
+TBool CMountBody::ProxyDriveDismounted()
+	{
+	return iProxyDriveDismounted;
+	}
+
+
+TInt CMountBody::GetFileUniqueId(const TDesC& /*aName*/, TInt64& /*aUniqueId*/)
+	{
+	return KErrNotSupported;
+	}
+TInt CMountBody::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
+	{
+	return KErrNotSupported;
+	}
+TInt CMountBody::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
+	{
+	return KErrNotSupported;
+	}
+TInt CMountBody::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
+	{
+	return KErrNotSupported;
+	}
+void CMountBody::ReadSection64L(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
+	{
+	if((TUint64)aPos > KMaxLegacyFileSize)
+		User::Leave(KErrNotSupported);
+
+	iMountCB->ReadSectionL(aName, I64LOW(aPos), aTrg, aLength, aMessage);
+	}
+
+TBool CFileBody::ExtendedFileInterfaceSupported()
+	{
+	return (iExtendedFileInterface==this) ? (TBool)EFalse : (TBool)ETrue;
+	}
+
+// default implementations of MExtendedFileInterface
+void CFileBody::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+	{
+	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
+		User::Leave(KErrNotSupported);
+
+	iFileCB->ReadL((TInt) aPos, aLength, aDes, aMessage);
+	}
+
+void CFileBody::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+	{
+	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
+		User::Leave(KErrNotSupported);
+
+	iFileCB->WriteL((TInt) aPos, aLength, aDes, aMessage);
+	}
+
+void CFileBody::SetSizeL(TInt64 aSize)
+	{
+	if ((TUint64)aSize > KMaxLegacyFileSize)
+		User::Leave(KErrNotSupported);
+
+	iFileCB->SetSizeL((TInt) aSize);
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+    This method allows file system to set maximum file size it supports.
+    This can be called on instantiation of the CFileCB derived class object by the file system implementation.
+    If this method is not called, the iMaxSupportedFileSize will have default value KMaxTUint64
+
+    @param aMaxFileSize maximum file size supported by file system
+*/
+EXPORT_C void CFileCB::SetMaxSupportedSize(TUint64 aMaxFileSize)
+    {
+    iBody->iMaxSupportedFileSize = aMaxFileSize;    
+    }
+
+/**
+    @return maximum supported file size (depends on the file system created it)
+*/
+TUint64 CFileCB::MaxSupportedSize(void) const
+    {
+    return iBody->iMaxSupportedFileSize;
+    }
+
+//---------------------------------------------------------------------------------------------------------------------
+
+/**
+Gets the size of the file.
+
+This is 64-bit variant for CFileCB::Size().
+This shall be used by File Systems supporting file size > 4GB - 1 to query the file size 
+inplace of CFileCB::Size() or CFileCB::iSize.
+
+@see CFileCB::iSize
+@see CFileCB::Size() 
+
+@prototype
+
+@return The size of the file.
+*/
+EXPORT_C TInt64 CFileCB::Size64() const
+	{
+	__ASSERT_DEBUG(iBody != NULL, Fault(EFileBodyIsNull));
+	const TInt64 size = MAKE_TINT64(iBody->iSizeHigh,iSize);
+	return size;
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+Sets the size of the file.
+
+This is 64-bit variant for CFileCB::SetSize().
+This should be used by File Systems supporting file size > 4GB - 1 to set the file size 
+inplace of CFileCB::SetSize() or CFileCB::iSize.
+
+@see CFileCB::iSize
+@see CFileCB::SetSize() 
+
+@prototype
+
+@param aSize The size of the file.
+@param aDriveLocked The status of the Drive Lock. If it is EFalse,
+the file size shall be modified after acquiring the iLock mutex and if it is ETrue, 
+the file size shall be modified without aquiring the iLock mutex.  
+*/
+EXPORT_C void CFileCB::SetSize64(TInt64 aSize, TBool aDriveLocked)
+	{
+	if(aDriveLocked)
+		{
+		iSize = (TInt)I64LOW(aSize);
+		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
+		}
+	else
+		{
+		Drive().Lock();
+		iSize = (TInt)I64LOW(aSize);
+		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
+		Drive().UnLock();
+		}
+	}
+
+
+/** used to organize key comparison for the TFileShareLock*/
+TInt LockOrder(const TFileShareLock& aMatch, const TFileShareLock& anEntry)
+	{
+
+	if(aMatch.PosLow() > anEntry.PosLow())
+		return 1;
+	else if(aMatch.PosLow() < anEntry.PosLow())
+		return -1;
+	else
+		return 0;
+   
+    }
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+    Find a lock inclusive of aPosLow to aPosHigh.
+*/
+TInt CFileCB::FindLock64(TInt64 aPosLow, TInt64 aPosHigh)
+    {
+
+	const TInt count=FileLocks().Count();
+	for (TInt i=0; i<count; i++)
+		{
+            
+            const TFileShareLock& lock=FileLocks()[i];
+
+            if(lock.PosLow() > (TUint64)aPosHigh)
+                return KErrNotFound;
+
+            if(lock.MatchByPos(aPosLow, aPosHigh))
+                return i;
+		}
+
+	return KErrNotFound;
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+    Add a lock on a range.
+*/
+TInt CFileCB::AddLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
+	{
+	const TUint64 posHigh=aPos+aLength-1;
+	
+        
+        {//-- Lock overflow check
+        const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
+	    if(posHigh > KMaxFileSize)
+                return KErrArgument;
+        }
+    
+    
+    TInt r=CheckLock64(NULL, aPos, aLength);
+	if (r!=KErrNone)
+		return r;
+	
+    TFileShareLock lock(aFileShare, aPos, posHigh);
+
+    TLinearOrder<TFileShareLock> lockOrder(LockOrder);
+	r=FileLocks().InsertInOrder(lock, lockOrder);
+	__ASSERT_ALWAYS(r!=KErrAlreadyExists,Fault(EFileDuplicateLock));
+	
+    return r;
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+    Remove a lock on a range.
+*/
+TInt CFileCB::RemoveLock64(CFileShare* aFileShare, TInt64 aPos, TInt64 aLength)
+	{
+	const TUint64 posHigh = aPos+aLength-1;
+
+        {//-- Lock overflow check
+        const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
+	    if(posHigh > KMaxFileSize)
+                return KErrArgument;
+        }
+    
+	const TInt pos=FindLock64(aPos, posHigh);
+	if (pos==KErrNotFound)
+		return KErrNotFound;
+	
+    const TFileShareLock& lock=FileLocks()[pos];
+    if (!lock.MatchOwner(aFileShare) || lock.PosLow() != (TUint64)aPos || lock.PosHigh() != posHigh)
+		return KErrNotFound;
+	
+   
+    FileLocks().Remove(pos);
+
+	return KErrNone;
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/** 
+    Check if a range is available.
+    @param  aFileShare pointer to FileShare object. NULL only when is called from CFileCB::AddLock64()
+
+*/
+TInt CFileCB::CheckLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
+	{
+	const TUint64 posHigh=aPos+aLength-1;
+	
+    //-- Lock overflow check. It is OK to have a lock that is beyond the real file size.
+    //-- if aFileShare == NULL, this is the call from AddLock64 and the position is already checked.
+    if(aFileShare)
+        {
+        const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
+	    if(posHigh > KMaxFileSize)
+            return KErrNone; //-- OK, there can't be any locks beyond the max. supported file length
+        }
+
+
+	TInt lockIdx=FindLock64(aPos, posHigh);
+	if (lockIdx == KErrNotFound)
+		return KErrNone;
+
+    const TInt count=FileLocks().Count();
+	const TFileShareLock* lock=(&FileLocks()[lockIdx]);
+
+	for(;;)
+		{
+		if (!lock->MatchOwner(aFileShare))
+			return KErrLocked;
+
+		if (lock->PosHigh() >= posHigh)
+			break;
+		
+        lockIdx++;
+		if (lockIdx >= count)
+			break;
+
+		lock=&FileLocks()[lockIdx];
+		
+        if (posHigh < lock->PosLow())
+			break;
+		}
+
+    return KErrNone;
+	}
+
+
+//#####################################################################################################################
+//#  TFileShareLock class implementation
+//#####################################################################################################################
+
+TFileShareLock::TFileShareLock(const CFileShare* aOwner, TUint64 aPosLow, TUint64 aPosHigh) 
+               : iOwner(aOwner), iPosLow(aPosLow), iPosHigh(aPosHigh) 
+    {
+    }
+
+
+   
+TUint64 TFileShareLock::PosLow()  const 
+    {
+    return iPosLow;
+    }
+
+
+TUint64 TFileShareLock::PosHigh() const 
+    {
+    return iPosHigh;
+    }
+
+TBool TFileShareLock::MatchOwner(const CFileShare* aShare) const 
+    {
+    return (aShare == iOwner);
+    }
+
+/**
+    @return ETrue if aPosLow and PosHigh match the lock boundaries
+*/
+TBool TFileShareLock::MatchByPos(TUint64 aPosLow, TUint64 aPosHigh) const
+    {
+        if(PosLow() > aPosHigh)
+            return EFalse;
+
+		if ((aPosLow  >= PosLow() && aPosLow   <= PosHigh()) ||
+			(aPosHigh >= PosLow() && aPosHigh  <= PosHigh()) ||
+			(aPosLow  <= PosLow() && aPosHigh  >= PosHigh() ))
+			{
+			return ETrue;
+			}
+
+         return EFalse;
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+