/**
Delivers the request to the end of plugin thread's queue. 
In certain circumstances, where the request requires priority handling
it adds it to the front of the queue.

@param	aRequest: The request to be delivered
@return KErrNone
*/
EXPORT_C TInt CFsPlugin::Deliver(TFsPluginRequest& aRequest)
	{
	__ASSERT_ALWAYS(iThreadP != NULL, User::Panic(_L("CFsPlugin::Dispatch"),999));

	TInt function = aRequest.Function();

	if(function == EFsPluginOpen)
		{
		// Don't dispatch open requests to the plugin thread
		return KPluginMessageForward;
		}

	if(function == EFsPluginDoRequest ||
	   function == EFsPluginDoControl ||
	   function == EFsPluginDoCancel)
		{
		iThreadP->DeliverFront(aRequest.Request());
		}
	else
		{
		iThreadP->DeliverBack(aRequest.Request());
		}

	return KErrNone;
	}
/** 
@prototype
@deprecated
@see RFilePlugin::Read
 */
EXPORT_C TInt CFsPlugin::FileRead(TFsPluginRequest& aRequest, TDes8& aDes, TInt64 aPos)
	{
	CFileShare* share;
	CFileCB* file;
	GetFileFromScratch((CFsMessageRequest*) aRequest.Request(), share, file);
	TInt64 fileSize = file->CachedSize64();
	if (aPos > fileSize)
		aPos = fileSize;
	TInt len = aDes.Length();
	if (aPos >= fileSize)
		len = 0;
	if (aPos + len > fileSize)
		// filesize - pos shall of TInt size
		// Hence to suppress warning
		len = (TInt)(fileSize - aPos);
	aDes.SetLength(len);

	return DispatchOperation(aRequest, aDes, aPos, EFsFileRead);
	}
/** @prototype */
EXPORT_C TInt CFsPlugin::ClientRead(TFsPluginRequest& aRequest, TDes8& aDes, TInt aOffset)
	{
	CFsMessageRequest& msgRequest = * (CFsMessageRequest*) aRequest.Request();
	TMsgOperation& currentOperation = msgRequest.CurrentOperation();
	
	TInt r = KErrNone;
	if (currentOperation.iClientRequest)
		{
		r = msgRequest.Read(0, aDes, aOffset);
		}
	else
		{
		TInt len = aDes.Length();
		if (len > (currentOperation.iReadWriteArgs.iTotalLength - aOffset))
			return KErrArgument;
		aDes.Copy ( (TUint8*) currentOperation.iReadWriteArgs.iData + aOffset, len );
		currentOperation.iReadWriteArgs.iOffset = aOffset + len;
		}
	return r;
	}
/**
@internalTechnology
@prototype
@deprecated

Pushes a msgop, dispatches it and waits for it to complete
*/
TInt CFsPlugin::DispatchOperation(TFsPluginRequest& aRequest, TDes8& aDes, TInt64 aPos, TInt aFunction)
	{
	if (aRequest.Function() != EFsFileRead && aRequest.Function() != EFsFileWrite)
		return KErrNotSupported;
	if (aFunction != EFsFileRead && aFunction != EFsFileWrite)
		return KErrNotSupported;

	CFsMessageRequest& msgRequest = * (CFsMessageRequest*) aRequest.Request();


	TInt len = aDes.Length();
	if (len <= 0)
		return CFsRequest::EReqActionComplete;

	TUint8* ptr = (TUint8*) aDes.Ptr();

	TInt r = msgRequest.PushOperation(
		aPos, len, ptr,
		0,			// aOffset
		Complete,	// callback
		0,			// next state
		aFunction);
	if (r != KErrNone)
		return r;


	CFsPlugin* plugin = this;
	FsPluginManager::ReadLockChain();
	FsPluginManager::NextPlugin(plugin, &msgRequest);
	msgRequest.iCurrentPlugin = plugin;
	msgRequest.Dispatch();
	FsPluginManager::UnlockChain();
	iThreadP->OperationLockWait();

	aDes.SetLength(len);
	
	return msgRequest.LastError();	// KErrNone;
	}