userlibandfileserver/fileserver/sfile/sf_plugin_shim.cpp
changeset 0 a41df078684a
child 36 538db54a451d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfile/sf_plugin_shim.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,772 @@
+// Copyright (c) 2008-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:
+// f32\sfile\sf_plugin_shim.cpp
+// 
+//
+
+#include "cl_std.h"
+#include "sf_std.h"
+
+/*******************************************************
+*						RFsPlugin					   *
+*******************************************************/
+
+EXPORT_C RFsPlugin::RFsPlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
+  : iSessionHelper(&aRequest, aDirectToDrive)
+	{
+	SetReturnedHandle(KNullHandle);
+	}
+
+EXPORT_C RFsPlugin::~RFsPlugin()
+	{
+	Close();
+	}
+
+EXPORT_C TInt RFsPlugin::Connect()
+/**
+Connects a file server plugin to the file server.
+
+To end the file server session, use Close().
+
+@return KErrNone, if successful, otherwise one of the other system-wide error codes.
+*/
+	{
+	return KErrNone;
+	}
+
+EXPORT_C void RFsPlugin::Close()
+/**
+Closes a file server plugin session.
+*/
+	{
+	SetReturnedHandle(KNullHandle);
+	}
+
+EXPORT_C TInt RFsPlugin::Delete(const TDesC& aName)
+/**
+Deletes a single file.
+
+@see RFs::Delete
+*/
+	{
+	return(RFs::Delete(aName));
+	}
+
+EXPORT_C TInt RFsPlugin::Rename(const TDesC& aOldName,const TDesC& aNewName)
+/**
+Renames a single file or directory.
+
+@see RFs::Rename
+*/
+	{
+	return(RFs::Rename(aOldName, aNewName));
+	}
+
+EXPORT_C TInt RFsPlugin::Replace(const TDesC& aOldName,const TDesC& aNewName)
+/**
+Replaces a single file with another.
+
+@see RFs::Replace
+*/
+	{
+	return(RFs::Replace(aOldName, aNewName));
+	}
+
+EXPORT_C TInt RFsPlugin::Entry(const TDesC& aName,TEntry& aEntry) const
+/**
+Gets the entry details for a file or directory.
+
+@see RFs::Entry
+*/
+	{
+	return(RFs::Entry(aName, aEntry));
+	}
+
+EXPORT_C TInt RFsPlugin::SetEntry(const TDesC& aName,const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
+/**
+Sets both the attributes and the last modified date and time for a file or directory.
+
+@see RFs::SetEntry
+*/
+	{
+	return(RFs::SetEntry(aName,aTime,aSetAttMask,aClearAttMask));
+	}
+
+EXPORT_C TInt RFsPlugin::ReadFileSection(const TDesC& aName,TInt64 aPos,TDes8& aDes,TInt aLength) const
+/**
+Reads data from a file without opening it.
+
+The contents of the	file can be accessed regardless of the file's lock state.
+
+@see RFs::ReadFileSection
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return(RFs::ReadFileSection(aName,I64LOW(aPos),aDes,aLength));
+#else
+	return(RFs::ReadFileSection(aName,aPos,aDes,aLength));
+#endif
+	}
+
+TInt RFsPlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	return iSessionHelper.SendReceive(aFunction, aArgs);
+	}
+
+TInt RFs::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	if(Handle())
+		return RSessionBase::SendReceive(aFunction, aArgs);
+		
+	return ((RFsPlugin*) this)->SendReceive(aFunction, aArgs);
+	}
+
+
+/*******************************************************
+*						RFilePlugin					   *
+*******************************************************/
+
+EXPORT_C RFilePlugin::RFilePlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
+  : iSessionHelper(&aRequest, aDirectToDrive)
+	{
+	SetHandle(KErrBadHandle);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+EXPORT_C RFilePlugin::~RFilePlugin()
+	{
+	Close();
+	}
+
+EXPORT_C TInt RFilePlugin::Open(const TDesC& aName,TUint aMode)
+/**
+Opens an existing file for reading or writing.
+
+If the file does not already exist, an error is returned.
+
+@see RFile::Open
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+	return(CreateSubSession(fs,EFsFileOpen,TIpcArgs(&aName,aMode)));
+	}
+
+EXPORT_C void RFilePlugin::Close()
+/**
+Closes the file.
+
+@see RFile::Close
+*/
+	{
+	CloseSubSession(EFsFileSubClose);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+EXPORT_C TInt RFilePlugin::Create(const TDesC& aName,TUint aFileMode)
+/**
+Closes the file.
+
+@see RFile::Create
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+	return(CreateSubSession(fs,EFsFileCreate,TIpcArgs(&aName,aFileMode)));
+	}
+
+EXPORT_C TInt RFilePlugin::Replace(const TDesC& aName,TUint aFileMode)
+/**
+Closes the file.
+
+@see RFile::Replace
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+	return(CreateSubSession(fs,EFsFileReplace,TIpcArgs(&aName,aFileMode)));
+	}
+
+EXPORT_C TInt RFilePlugin::Temp(const TDesC& aPath,TFileName& aName,TUint aFileMode)
+/**
+Closes the file.
+
+@see RFile::Temp
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+	return(CreateSubSession(fs,EFsFileTemp,TIpcArgs(&aPath,aFileMode,&aName)));
+	}
+
+EXPORT_C TInt RFilePlugin::AdoptFromClient()
+/**
+Closes the file.
+
+@see RFile::AdoptFromClient
+*/
+	{
+	TFsPluginRequest* request = iSessionHelper.Request();
+	if(request == NULL)
+		return KErrBadHandle;
+
+	TInt clientSubSessionHandle;
+	TInt err = request->ClientSubSessionHandle(clientSubSessionHandle);
+	if (err != KErrNone)
+		return err;
+
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+	err = CreateSubSession(fs,EFsFileDuplicate, TIpcArgs(clientSubSessionHandle, ETrue));
+	if (err != KErrNone)
+		return err;
+
+	SetSubSessionHandle(SubSessionHandle() ^ KSubSessionMangleBit);
+
+	return err;
+	}
+    
+EXPORT_C TInt RFilePlugin::TransferToClient()
+/**
+Closes the file.
+
+@see RFile::TransferToClient
+*/
+	{
+	TFsPluginRequest* request = iSessionHelper.Request();
+	if(request == NULL)
+		return KErrBadHandle;
+
+	// This doesn't behave like a standard duplicate as we're running in the context of the
+	// client's session.  Instead, we can simply return our subsession handle to the client.
+	TRAPD(err, request->Request()->WriteL(KMsgPtr3, TPckgC<TInt>(SubSessionHandle())));
+
+	// Next we have to free up the close request reserved for our internal subsession
+	// otherwise two messages will be reserved for the client...
+	RequestAllocator::OpenSubFailed(request->Request()->Session());
+
+	// And now we're done - we don't bother closing, as the client now completely owns the handle
+	SetSubSessionHandle(KErrBadHandle);
+
+	return err;
+	}
+
+EXPORT_C TInt RFilePlugin::Write(TInt64 aPos, const TDesC8& aDes)
+/**
+Writes to the file at the specified offset within the file
+
+@see RFile::Write
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::Write(I64LOW(aPos), aDes);
+#else
+	return RFile64::Write(aPos, aDes);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Write(TInt64 aPos,const TDesC8& aDes,TInt aLen)
+/**
+Writes the specified number of bytes to the file at the specified offset within the file.
+
+@see RFile::Write
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::Write(I64LOW(aPos), aDes, aLen);
+#else
+	return RFile64::Write(aPos, aDes, aLen);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Read(TInt64 aPos,TDes8& aDes) const
+/**
+Reads from the file at the specified offset within the file
+
+@see RFile::Read
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::Read(I64LOW(aPos), aDes);
+#else
+	return RFile64::Read(aPos, aDes);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Read(TInt64 aPos,TDes8& aDes,TInt aLen) const
+/**
+Reads the specified number of bytes of binary data from the file at a specified 
+offset within the file.
+
+@see RFile::Read
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::Read(I64LOW(aPos), aDes, aLen);
+#else
+	return RFile64::Read(aPos, aDes, aLen);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Size(TInt64& aSize) const
+/**
+Gets the current file size.
+
+@see RFile::Size
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	TInt size = I64LOW(aSize);
+	TInt err = RFile::Size(size);
+	aSize = size;
+	return err;
+#else
+	return RFile64::Size(aSize);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::SetSize(TInt64 aSize)
+/**
+Sets the file size.
+
+@see RFile::SetSize
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::SetSize(I64LOW(aSize));
+#else
+	return RFile64::SetSize(aSize);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Lock(TInt64 aPos, TInt64 aLength) const
+/**
+Locks a region within the file as defined by a range of bytes.
+
+@see RFile::Lock
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::Lock(I64LOW(aPos), I64LOW(aLength));
+#else
+	return RFile64::Lock(aPos, aLength);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::UnLock(TInt64 aPos, TInt64 aLength) const
+/**
+Unlocks a region within the file as defined by a range of bytes.
+
+@see RFile::UnLock
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	return RFile::UnLock(I64LOW(aPos), I64LOW(aLength));
+#else
+	return RFile64::UnLock(aPos, aLength);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Seek(TSeek aMode,TInt64& aPos) const
+/**
+Sets the the current file position.
+
+@see RFile::Seek
+*/
+	{
+#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+	TInt position = I64LOW(aPos);
+	TInt err = RFile::Seek(aMode, position);
+	if(err != KErrNone)
+		return err;
+	aPos = position;
+	return KErrNone;
+#else
+	return RFile64::Seek(aMode, aPos);
+#endif
+	}
+
+EXPORT_C TInt RFilePlugin::Flush()
+/**
+Commits data to the storage device and flushes internal buffers without closing 
+the file.
+
+@see RFile::Flush
+*/
+	{
+	return RFile::Flush();
+	}
+
+EXPORT_C TInt RFilePlugin::Att(TUint& aVal) const
+/**
+Gets the file's attributes.
+
+@see RFile::Att
+*/
+	{
+	return RFile::Att(aVal);
+	}
+
+EXPORT_C TInt RFilePlugin::SetAtt(TUint aSetAttMask,TUint aClearAttMask)
+/**
+Sets or clears file attributes using two bitmasks.
+
+@see RFile::SetAtt
+*/
+	{
+	return RFile::SetAtt(aSetAttMask, aClearAttMask);
+	}
+
+EXPORT_C TInt RFilePlugin::Modified(TTime& aTime) const
+/**
+Gets local date and time the file was last modified, in universal time.
+
+@see RFile::Modified
+*/
+	{
+	return RFile::Modified(aTime);
+	}
+
+EXPORT_C TInt RFilePlugin::SetModified(const TTime& aTime)
+/**
+Sets the date and time the file was last modified. UTC date and time should be used.
+
+@see RFile::SetModified
+*/
+	{
+	return RFile::SetModified(aTime);
+	}
+
+EXPORT_C TInt RFilePlugin::Set(const TTime& aTime,TUint aMask,TUint aVal)
+/**
+Sets the file’s attributes, and the date and time it was last modified.
+
+@see RFile::Set
+*/
+	{
+	return RFile::Set(aTime, aMask, aVal);
+	}
+
+EXPORT_C TInt RFilePlugin::ChangeMode(TFileMode aNewMode)
+/**
+Switches an open file's access mode between EFileShareExclusive and EFileShareReadersOnly.
+
+@see RFile::ChangeMode
+*/
+	{
+	return RFile::ChangeMode(aNewMode);
+	}
+
+EXPORT_C TInt RFilePlugin::Rename(const TDesC& aNewName)
+/**
+Renames a file.
+
+@see RFile::Rename
+*/
+	{
+	return RFile::Rename(aNewName);
+	}
+
+void RFilePlugin::SetHandle(TInt aHandle)
+	{
+	*(((TInt*) this) + 0) = aHandle;
+	}
+
+void RFilePlugin::SetSubSessionHandle(TInt aHandle)
+	{
+	*(((TInt*) this) + 1) = aHandle;
+	}
+
+TInt RFilePlugin::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs)
+	{
+	TInt reply;
+	TInt err = iSessionHelper.CreateSubSession(aSession, aFunction, aArgs, &reply);
+	if(err == KErrNone)
+		SetSubSessionHandle(reply);
+	return(err);
+	}
+
+void RFilePlugin::CloseSubSession(TInt aFunction)
+	{
+	if (SubSessionHandle())
+		{
+		SendReceive(aFunction,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,SubSessionHandle()));
+		}
+
+	SetHandle(KErrBadHandle);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+TInt RFilePlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	return iSessionHelper.SendReceive(aFunction, aArgs, ((RFilePlugin*) this)->SubSessionHandle());
+	}
+
+TInt RFile::CreateSubSession(const RSessionBase& aSession,TInt aFunction,const TIpcArgs& aArgs)
+	{
+	if(SubSessionHandle() == KErrBadHandle)
+		return ((RFilePlugin*) this)->CreateSubSession(aSession, aFunction, aArgs);
+
+	return RSubSessionBase::CreateSubSession(aSession, aFunction, aArgs);
+	}
+
+void RFile::CloseSubSession(TInt aFunction)
+	{
+	if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle) 
+		RSubSessionBase::CloseSubSession(aFunction);
+	else
+		((RFilePlugin*) this)->CloseSubSession(aFunction);
+	}
+
+TInt RFile::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle) 
+		return RSubSessionBase::SendReceive(aFunction, aArgs);
+		
+	return ((RFilePlugin*) this)->SendReceive(aFunction, aArgs);
+	}
+
+
+/*******************************************************
+*						RDirPlugin					   *
+*******************************************************/
+
+EXPORT_C RDirPlugin::RDirPlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
+  : iSessionHelper(&aRequest, aDirectToDrive)
+	{
+	SetHandle(KErrBadHandle);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+EXPORT_C RDirPlugin::~RDirPlugin()
+	{
+	Close();
+	}
+
+EXPORT_C TInt RDirPlugin::Open(const TDesC& aMatchName,const TUidType& aUidType)
+/**
+Opens a directory using the specified UID type to filter the
+directory entry types that will subsequently be read.
+
+@see RDir::Open
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+
+	TPckgC<TUidType> pckgUid(aUidType);
+	return(CreateSubSession(fs,EFsDirOpen,TIpcArgs(&aMatchName,KEntryAttAllowUid,&pckgUid)));
+	}
+
+EXPORT_C TInt RDirPlugin::Open(const TDesC& aMatchName,TUint anAttMask)
+/**
+Opens a directory using an attribute bitmask to filter the directory entry
+types that will subsequently be read.
+
+@see RDir::Open
+*/
+	{
+	RFs fs;
+	fs.SetHandle(Session().Handle());
+
+	TUidType uidType(TUid::Null(),TUid::Null(),TUid::Null());
+	TPckgC<TUidType> pckgUid(uidType);
+	return(CreateSubSession(fs,EFsDirOpen,TIpcArgs(&aMatchName,anAttMask,&pckgUid)));
+	}
+    
+EXPORT_C void RDirPlugin::Close()
+/**
+Closes the the directory.
+
+@see RDir::Close
+*/
+	{
+	CloseSubSession(EFsDirSubClose);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+EXPORT_C TInt RDirPlugin::Read(TEntryArray& aArray)
+/**
+Reads all filtered directory entries into the specified array.
+
+@see RDir::Read
+*/
+	{
+	return RDir::Read(aArray);
+	}
+
+EXPORT_C TInt RDirPlugin::Read(TEntry& aEntry)
+/**
+Reads all filtered directory entries into the specified array.
+
+@see RDir::Read
+*/
+	{
+	return RDir::Read(aEntry);
+	}
+
+void RDirPlugin::SetHandle(TInt aHandle)
+	{
+	*(((TInt*) this) + 0) = aHandle;
+	}
+
+void RDirPlugin::SetSubSessionHandle(TInt aHandle)
+	{
+	*(((TInt*) this) + 1) = aHandle;
+	}
+
+TInt RDirPlugin::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs)
+	{
+	TInt reply;
+	TInt err = iSessionHelper.CreateSubSession(aSession, aFunction, aArgs, &reply);
+	if(err == KErrNone)
+		SetSubSessionHandle(reply);
+	return(err);
+	}
+
+void RDirPlugin::CloseSubSession(TInt aFunction)
+	{
+	if (SubSessionHandle())
+		{
+		SendReceive(aFunction,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,SubSessionHandle()));
+		}
+
+	SetHandle(KErrBadHandle);
+	SetSubSessionHandle(KErrBadHandle);
+	}
+
+TInt RDirPlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	return iSessionHelper.SendReceive(aFunction, aArgs, ((RDirPlugin*) this)->SubSessionHandle());
+	}
+
+TInt RDir::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
+	{
+	if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle) 
+		return RSubSessionBase::SendReceive(aFunction, aArgs);
+
+	return ((RDirPlugin*) this)->SendReceive(aFunction, aArgs);
+	}
+
+
+/*******************************************************
+*				TFsPluginSessionHelper				   *
+*******************************************************/
+
+TPluginSessionHelper::TPluginSessionHelper()
+	{ memclr(this, sizeof(TPluginSessionHelper)); }
+
+TPluginSessionHelper::TPluginSessionHelper(TFsPluginRequest* aRequest, TBool aDirectToDrive)
+  : iPlugin(aRequest->Request()->iCurrentPlugin),
+	iSession(aRequest->Request()->Session()),
+	iDirectToDrive(aDirectToDrive),
+    iRequest(aRequest)
+	{
+	// need to initialise RLocalMessage with client session
+	*((RMessage2*) &iMessage) = aRequest->Message();
+	iMessage.InitHandle();	// set handle to KLocalMessageHandle
+	memclr(iSpare, sizeof(iSpare));
+	}
+
+TInt TPluginSessionHelper::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs, TInt* aReply)
+	{
+	(void)aSession;
+
+	// Init message
+	TIpcArgs args;
+	args.iArgs[0] = aArgs.iArgs[0];
+	args.iArgs[1] = aArgs.iArgs[1];
+	args.iArgs[2] = aArgs.iArgs[2];
+	args.iFlags = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
+
+	TPckgBuf<TInt> reply;
+	args.Set(3,&reply);
+
+	// copy session pointer
+	RLocalMessage message = iMessage;
+	message.SetFunction(aFunction);
+	message.SetArgs(args);
+
+	TInt err = Dispatch(aFunction, args);
+	if (err == KErrNone)
+		*aReply = reply();
+
+	return err;
+	}
+
+TInt TPluginSessionHelper::Dispatch(TInt aFunction, TIpcArgs& aArgs) const
+	{
+	// copy session pointer
+	RLocalMessage message = iMessage;
+	message.SetFunction(aFunction);
+	message.SetArgs(aArgs);
+
+	// allocate request
+	CFsClientMessageRequest* newRequest;
+	const TOperation& oP = OperationArray[aFunction & KIpcFunctionMask];
+	TInt err = RequestAllocator::GetMessageRequest(oP, message, newRequest);
+	if (err != KErrNone)
+		return err;
+
+	newRequest->Set(message, oP, iSession);
+	
+	//This is wrong. drive number is set in TFsXxx::initialise
+	//newRequest->SetDrive(&TheDrives[iPlugin->Drive()]);
+
+	newRequest->iCurrentPlugin = iPlugin;
+	newRequest->iOwnerPlugin   = iPlugin;
+	newRequest->iDirectToDrive = iDirectToDrive;
+
+	newRequest->Dispatch();
+
+	// NOTE : newRequest will be free'd by the File Server before completing the 
+	//        request so it's not safe to touch the request from now on...
+	
+	return(iPlugin->WaitForRequest());
+	}
+
+TInt TPluginSessionHelper::SendReceive(TInt aFunction, const TIpcArgs& aArgs, TInt aSubSessionHandle) const
+	{
+	// Init message
+	TIpcArgs args;
+	args.iArgs[0] = aArgs.iArgs[0];
+	args.iArgs[1] = aArgs.iArgs[1];
+	args.iArgs[2] = aArgs.iArgs[2];
+	args.iFlags   = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
+	args.iArgs[3] = aSubSessionHandle;
+
+	return Dispatch(aFunction, args);
+	}
+
+TInt TPluginSessionHelper::SendReceive(TInt aFunction, const TIpcArgs& aArgs) const
+	{
+	// Init message
+	TIpcArgs args;
+	args.iArgs[0] = aArgs.iArgs[0];
+	args.iArgs[1] = aArgs.iArgs[1];
+	args.iArgs[2] = aArgs.iArgs[2];
+	args.iArgs[3] = aArgs.iArgs[3];
+	args.iFlags = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
+
+	return Dispatch(aFunction, args);
+	}
+
+GLDEF_C void Panic(TClientPanic aPanic)
+//
+// Panic the current client with a file server client side panic.
+//
+	{
+	User::Panic(_L("FS_PLUGIN_CLIENT panic"),aPanic);
+	}
+