sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32\sfile\sf_plugin.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include "sf_std.h" sl@0: #include "sf_plugin_priv.h" sl@0: sl@0: CFsObjectCon* FsPluginManager::iPluginFactories = NULL; sl@0: CFsObjectCon* FsPluginManager::iPluginConns = NULL; sl@0: RFastLock FsPluginManager::iChainLock; sl@0: RPointerArray FsPluginManager::iPluginChain; sl@0: CFsSyncMessageScheduler* FsPluginManager::iScheduler = NULL; sl@0: sl@0: TBool IsPagableDrive(TInt aDrive) sl@0: { sl@0: if(LocalDrives::IsValidDriveMapping(aDrive)) sl@0: { sl@0: TLocalDriveCapsBuf capsBuf; sl@0: if(!LocalDrives::IsProxyDrive(aDrive) && LocalDrives::GetLocalDrive(aDrive).Caps(capsBuf) && capsBuf().iDriveAtt & KDriveAttPageable) sl@0: { sl@0: return (TBool)ETrue; sl@0: } sl@0: } sl@0: return (TBool) EFalse; sl@0: } sl@0: sl@0: /* sl@0: @param aNonPagableDriveMask - a drive mask of the drives a plugin wishes to mount on sl@0: @return A drive mask of the drives a plugin wishes to mount on not containing any pagable drives. sl@0: */ sl@0: TInt NonPagableDrivesMask(TInt aNonPagableDriveMask) sl@0: { sl@0: TInt driveMask = aNonPagableDriveMask; sl@0: for(TInt i = 0; i < KMaxDrives; i++) sl@0: { sl@0: //If we're interested in this drive sl@0: if((aNonPagableDriveMask & 1<SupportedDrives()&KPluginVersionTwo)) sl@0: { //Version 1 Plugin - Mount on all (except Z and pagble drives) sl@0: TInt drivesAToY = (KPluginSupportAllDrives>>1); sl@0: aPlugin->iMountedOn = NonPagableDrivesMask(drivesAToY); sl@0: } sl@0: else sl@0: { //Version 2 Plugin - Mount on what the plugin supports (except pagable drives) sl@0: aPlugin->iMountedOn = NonPagableDrivesMask((aFactory->SupportedDrives()&(~KPluginVersionTwo))); sl@0: } sl@0: sl@0: if(!(aPlugin->iMountedOn &(~KPluginVersionTwo))) sl@0: { //Are we mounted on anything? sl@0: return KErrNotSupported; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: // DriveZ special handling sl@0: if(aDrive==KPluginMountDriveZ) sl@0: aDrive = EDriveZ; sl@0: sl@0: //Mounting on a single drive sl@0: if(!IsPagableDrive(aDrive)) sl@0: { sl@0: aPlugin->iMountedOn |= 1<CreateL(); sl@0: iPluginConns = TheContainer->CreateL(); sl@0: iPluginChain.Reset(); sl@0: User::LeaveIfError(iChainLock.CreateLocal()); sl@0: sl@0: // Create and install the synchronous message scheduler sl@0: // - Messages are dispatched here from plugin threads if they are sl@0: // to be executed in the context of the main file server thread. sl@0: iScheduler = CFsSyncMessageScheduler::NewL(); sl@0: iScheduler->RunL(); sl@0: } sl@0: sl@0: /** sl@0: FsPluginManager::MountPlugin sl@0: */ sl@0: TInt FsPluginManager::MountPlugin(CFsPluginFactory& aPluginFactory, TInt aDrive, TInt aPos) sl@0: { sl@0: TInt uniquePosition = aPluginFactory.UniquePosition(); sl@0: CFsPlugin* pP = NULL; sl@0: CFsPluginFactory* pF = &aPluginFactory; sl@0: sl@0: //Version1 plugins could either been mounted on 1 or all drives. sl@0: //This isn't particularily desirable. sl@0: // Thus - sl@0: //For version2 plugins: sl@0: //Check whether this plugin has already been mounted sl@0: pP = FindByUniquePosition(uniquePosition); sl@0: if(pP && (aPluginFactory.iSupportedDrives&KPluginVersionTwo)) sl@0: { sl@0: //if this plugin has already been mounted then sl@0: //Instead of trying to mount and failing with KErrInUse, sl@0: //lets update the iMountedOn instead. sl@0: return UpdateMountedDrive(pP,pF,aDrive); sl@0: } sl@0: sl@0: sl@0: TRAPD(err, pP = aPluginFactory.NewPluginL()); sl@0: if(err != KErrNone) sl@0: { sl@0: if(pP) sl@0: pP->Close(); sl@0: return err; sl@0: } sl@0: sl@0: TFullName name = aPluginFactory.Name(); sl@0: pP->SetName(&name); sl@0: pP->iUniquePos=aPluginFactory.UniquePosition(); sl@0: pP->SetDrive(aDrive); sl@0: sl@0: //Set which drive(s?) this plugin is mounted on. sl@0: err = UpdateMountedDrive(pP,pF,aDrive); sl@0: if(err != KErrNone) sl@0: { sl@0: pP->Close(); sl@0: return err; sl@0: } sl@0: sl@0: LockChain(); sl@0: err = InsertInPluginStack(pP,aPos); sl@0: UnlockChain(); sl@0: if(err != KErrNone) sl@0: { sl@0: pP->Close(); sl@0: return err; sl@0: } sl@0: sl@0: err = InitPlugin(*pP); sl@0: if(err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: aPluginFactory.IncrementMounted(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Dismounts a plugin sl@0: sl@0: Must be called with the plugin chain locked. sl@0: */ sl@0: void FsPluginManager::DismountPlugin(CFsPluginFactory& aPluginFactory,TInt aPos) sl@0: { sl@0: CFsPlugin* plugin=iPluginChain[aPos]; sl@0: sl@0: if (plugin != NULL) sl@0: { sl@0: // Check if there is any requests for this plugin sl@0: // if so, deliver them to the next supporting plugin sl@0: TransferRequests(plugin->iThreadP); sl@0: sl@0: plugin->iThreadP=NULL; sl@0: sl@0: //Remove the plugin from the chain sl@0: iPluginChain.Remove(aPos); sl@0: iPluginChain.Compress(); sl@0: sl@0: //Close the plugin (destructed when CPluginThread is destructed). sl@0: plugin->Close(); sl@0: plugin=NULL; sl@0: } sl@0: else sl@0: { sl@0: ASSERT(0); // force panic in debug mode sl@0: } sl@0: sl@0: aPluginFactory.DecrementMounted(); sl@0: } sl@0: sl@0: /* sl@0: * This will iterate through a plugins request queue and sl@0: * search for the first occurance it finds of a CancelPluginOp sl@0: * request. sl@0: */ sl@0: void FsPluginManager::GetNextCancelPluginOpRequest(CPluginThread* aPluginThread, CFsRequest*& aCancelPluginRequest) sl@0: { sl@0: __THRD_PRINT(_L("FsPluginManager::GetNextCancelPluginOpRequest")); sl@0: sl@0: TDblQueIter iter(aPluginThread->iList); sl@0: CFsRequest* request = NULL; sl@0: sl@0: while((request=iter++)!=NULL) sl@0: { sl@0: if(request->Operation()->iFunction == KCancelPlugin) sl@0: { sl@0: aCancelPluginRequest = request; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Transfer any outstanding requests to next/previous plugin depending on sl@0: if it is post filter or not sl@0: sl@0: Must be called with the plugin chain locked. sl@0: Attains plugin-thread's listlock. sl@0: */ sl@0: void FsPluginManager::TransferRequests(CPluginThread* aPluginThread) sl@0: { sl@0: aPluginThread->iListLock.Wait(); sl@0: sl@0: __THRD_PRINT(_L("FsPluginManager::TransferRequests - moving requests")); sl@0: sl@0: /* sl@0: * We are transferring requests up and down the chain sl@0: * because this plugin is being removed. sl@0: * sl@0: * There is a potential problem when one of the outstanding requests sl@0: * is CancelPluginOp which is called when the Session is being closed. sl@0: * The CancelPluginOp will try to cancel all of the requests on a plugin's sl@0: * queue which is associated with that session. sl@0: * DismountPlugin(and thus TransferRequests) is trying to preserve the requests sl@0: * by passing them along to the Next/Previous plugins. sl@0: * sl@0: * If there is a cancel in the chain we must NOT pass any requests to Previous Plugins sl@0: * as these have already had their chains emptied. sl@0: * We should also be wary of passing requests up the chain as they will simply be cancelled sl@0: * somewhere closer to the drive [thread]. sl@0: * sl@0: * Therefore, we shall check whether there is a KCancelPlugin op in the sl@0: * chain first. sl@0: * If there is a cancelPluginOp in the chain, we will cancel of the requests sl@0: * that are associated with that session. sl@0: * sl@0: * After that is out of the way we preserve the remaining requests for different sessions by sl@0: * passing them on. sl@0: */ sl@0: if(!aPluginThread->iList.IsEmpty()) sl@0: { sl@0: CFsRequest* cancelRequest = NULL; sl@0: //For every CancelPluginOp sl@0: while(FsPluginManager::GetNextCancelPluginOpRequest(aPluginThread, cancelRequest), cancelRequest!=NULL) sl@0: { sl@0: RDebug::Print(_L("Transferring Plugin Requests - CancelPluginOp")); sl@0: TDblQueIter iter(aPluginThread->iList); sl@0: CFsRequest* request = NULL; sl@0: //For every request sl@0: while((request=iter++)!=NULL) sl@0: { sl@0: if(request->Session() == cancelRequest->Session() && request != cancelRequest) sl@0: { sl@0: request->iLink.Deque(); sl@0: request->Complete(KErrCancel); sl@0: } sl@0: } sl@0: cancelRequest->iLink.Deque(); sl@0: cancelRequest->Complete(KErrNone); sl@0: cancelRequest = NULL; sl@0: } sl@0: sl@0: /* sl@0: * Now that all requests that were to be cancelled have been cancelled, sl@0: * we can now go about moving the remaining ones on to , or back to, sl@0: * the appropriate next or previous plugins. sl@0: * sl@0: * ToDo: This next 'while' might be able to be replaced with a call to sl@0: * DispatchToPlugin/DispatchToDrive instead. sl@0: */ sl@0: while(!aPluginThread->iList.IsEmpty()) sl@0: { sl@0: CFsRequest* pR=aPluginThread->iList.First(); sl@0: CFsMessageRequest& mR = *(CFsMessageRequest*) pR; sl@0: pR->iLink.Deque(); sl@0: pR->iCurrentPlugin=NULL; sl@0: sl@0: if(pR->IsPluginSpecific()) sl@0: { sl@0: pR->Complete(KErrCancel); sl@0: continue; sl@0: } sl@0: sl@0: if(pR->IsPostOperation()) sl@0: { sl@0: //[set the plugin to] pass the request backwards in the chain sl@0: PrevPlugin(pR->iCurrentPlugin, &mR, EFalse); sl@0: } sl@0: else //IsPreOperations sl@0: { sl@0: //[set the plugin to] pass the request forwards in the chain sl@0: NextPlugin(pR->iCurrentPlugin, &mR, EFalse); sl@0: } sl@0: sl@0: if(pR->iCurrentPlugin) sl@0: { sl@0: pR->iCurrentPlugin->iThreadP->DeliverBack(pR); sl@0: } sl@0: else sl@0: { sl@0: if(!pR->IsPostOperation() && (pR->DriveNumber()>=EDriveA && pR->DriveNumber()<=EDriveZ)) sl@0: { sl@0: //Deliver to drive thread sl@0: CDriveThread* dT=NULL; sl@0: TInt r=FsThreadManager::GetDriveThread(pR->DriveNumber(),&dT); sl@0: __ASSERT_ALWAYS(r==KErrNone && dT,Fault(EFsDriveThreadError)); sl@0: CRequestThread* pT = (CRequestThread*)dT; sl@0: pT->DeliverBack(pR); sl@0: } sl@0: else sl@0: { sl@0: pR->Complete(KErrCancel); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: aPluginThread->iExit = ETrue; sl@0: aPluginThread->iListLock.Signal(); sl@0: sl@0: __THRD_PRINT(_L("FsPluginManager::TransferRequests - all requests moved/cancelled")); sl@0: } sl@0: sl@0: /** sl@0: Install a plugin factory sl@0: */ sl@0: TInt FsPluginManager::InstallPluginFactory(CFsPluginFactory* aFactory,RLibrary aLib) sl@0: { sl@0: TInt r=aFactory->Install(); sl@0: __PRINT1TEMP(_L("InstallPluginFactory %S"),aFactory->Name()); sl@0: if (r==KErrNone) sl@0: {TRAP(r,iPluginFactories->AddL(aFactory,ETrue))} sl@0: if (r!=KErrNone) sl@0: aFactory->Remove(); sl@0: if (r==KErrNone) sl@0: aFactory->SetLibrary(aLib); sl@0: else sl@0: aFactory->Close(); sl@0: return(r); sl@0: } sl@0: sl@0: /** sl@0: Find a plugin factory by name sl@0: */ sl@0: CFsPluginFactory* FsPluginManager::GetPluginFactory(const TDesC& aName) sl@0: { sl@0: sl@0: TInt h=0; sl@0: TInt r=iPluginFactories->FindByName(h,aName); sl@0: if (r!=KErrNone) sl@0: return(NULL); sl@0: return((CFsPluginFactory*)iPluginFactories->At(h)); sl@0: } sl@0: sl@0: /** sl@0: Find the next plugin that supports the operation sl@0: sl@0: @param aPlugin - On calling the function this may contain either NULL or the current plugin. sl@0: If it is called with NULL, then we start to look for plugins from the beginning of the chain. sl@0: If is is called with a plugin then we start to look after that plugin for the next one. sl@0: On return, aPlugin shall contain either a plugin or NULL. sl@0: sl@0: @param aLock - If this is set to ETRUE, then the function shall lock the plugin chain. sl@0: If this is set to EFALSE, then the caller of the function MUST already hold the lock. sl@0: sl@0: @param aCheckCurrentOperation - Optional, if false, will return the next plugin, sl@0: whether the plugin is currently registered sl@0: for the current function or not. (so long as mounted on the current drive) sl@0: */ sl@0: TInt FsPluginManager::NextPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest,TBool aLock, TBool aCheckCurrentOperation) sl@0: { sl@0: if(aMsgRequest->DirectToDrive()) sl@0: { sl@0: aPlugin = NULL; sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt start; sl@0: TInt function = aMsgRequest->Operation()->Function(); sl@0: TInt drive = aMsgRequest->DriveNumber(); sl@0: sl@0: if(aLock) sl@0: LockChain(); sl@0: sl@0: //the plugin chain lock must be held by this point. sl@0: TInt count = iPluginChain.Count(); sl@0: sl@0: if(aPlugin == NULL) sl@0: start=0; sl@0: else sl@0: start = iPluginChain.Find(aPlugin)+1; sl@0: sl@0: if(start!=KErrNotFound) sl@0: { sl@0: for(TInt i=start;iIsRegistered(function, CFsPlugin::EPreIntercept)) sl@0: { sl@0: if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive))) sl@0: { sl@0: sl@0: aPlugin = iPluginChain[i]; sl@0: if(aLock) sl@0: UnlockChain(); sl@0: return KErrNone; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: aPlugin = NULL; sl@0: if(aLock) sl@0: UnlockChain(); sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: /** sl@0: Find the next plugin that supports the operation sl@0: sl@0: @see FsPluginManager::NextPlugin sl@0: */ sl@0: TInt FsPluginManager::PrevPlugin(CFsPlugin*& aPlugin, CFsMessageRequest* aMsgRequest, TBool aLock) sl@0: { sl@0: if(aMsgRequest->DirectToDrive() && (aMsgRequest->CurrentOperationPtr() != NULL)) sl@0: { sl@0: aPlugin = NULL; sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt start; sl@0: TInt function = aMsgRequest->Operation()->Function(); sl@0: TInt drive = aMsgRequest->DriveNumber(); sl@0: sl@0: if(aLock) sl@0: LockChain(); sl@0: sl@0: //the plugin chain lock must be held by this point. sl@0: TInt count= iPluginChain.Count(); sl@0: sl@0: if(aPlugin == NULL) sl@0: start = count-1; sl@0: else sl@0: start = iPluginChain.Find(aPlugin)-1; sl@0: sl@0: if(start!=KErrNotFound) sl@0: { sl@0: for(TInt i=start;i>=0;i--) sl@0: { sl@0: CFsPlugin* owner = aMsgRequest->iOwnerPlugin; sl@0: if(owner == iPluginChain[i]) sl@0: break; sl@0: sl@0: if(iPluginChain[i]->IsRegistered(function, CFsPlugin::EPostIntercept)) sl@0: { sl@0: if((function == EFsDismountPlugin) || (iPluginChain[i]->IsMounted(drive))) sl@0: { sl@0: sl@0: aPlugin = iPluginChain[i]; sl@0: if(aLock) sl@0: UnlockChain(); sl@0: return KErrNone; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: aPlugin = NULL; sl@0: if(aLock) sl@0: UnlockChain(); sl@0: return KErrNotFound; sl@0: } sl@0: /** sl@0: Inserts the plugin in the stack (chain) sl@0: sl@0: if aPos absolute postion, it simply inserts it sl@0: if aPos unique position, it walks through chain and checks the unique positions sl@0: */ sl@0: TInt FsPluginManager::InsertInPluginStack(CFsPlugin*& aPlugin,TInt aPos) sl@0: { sl@0: TInt ret=KErrNone; sl@0: TInt count= iPluginChain.Count(); sl@0: if(aPos == KPluginAutoLocate) sl@0: { sl@0: TInt uPos= aPlugin->iUniquePos; sl@0: for(TInt i=0;iiUniquePos) sl@0: { sl@0: return KErrInUse; sl@0: } sl@0: sl@0: if(uPos < iPluginChain[i]->iUniquePos) sl@0: { sl@0: ret=iPluginChain.Insert(aPlugin,i); sl@0: return ret; sl@0: } sl@0: } sl@0: ret=iPluginChain.Append(aPlugin); sl@0: } sl@0: else sl@0: { sl@0: // Absolute position sl@0: sl@0: if(aPos > count) sl@0: return(KErrNotFound); sl@0: if(aPos == count) sl@0: { sl@0: ret=iPluginChain.Append(aPlugin); sl@0: return ret; sl@0: } sl@0: ret=iPluginChain.Insert(aPlugin,aPos); sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: /** sl@0: Looks for a plugin in the chain sl@0: */ sl@0: TInt FsPluginManager::IsInChain(TInt aUPos,TInt aPos, TInt aDrive, CFsPluginFactory* aPluginFactory) sl@0: { sl@0: TInt count= iPluginChain.Count(); sl@0: sl@0: if(aPos == KPluginAutoLocate) sl@0: { sl@0: for(TInt i=0;iSupportedDrives()&KPluginVersionTwo) //Version2 sl@0: { sl@0: //If KPluginAutoAttach, then we're dismounted from all drives. sl@0: //If KPluginMountDriveZ, then check against 25 explicitly (cannot change aDrive:=Z as that==KPluginAutoAttach)) sl@0: //If any other drive mounted. sl@0: if(aUPos == pP->iUniquePos && (aDrive==KPluginAutoAttach || (aDrive==KPluginMountDriveZ && pP->iMountedOn & (1<iMountedOn & (1<iUniquePos && (aDrive==KPluginAutoAttach || pP->iMountedOn & (1<iPluginChain.Count()) sl@0: return(KErrNotFound); sl@0: sl@0: if(iPluginChain[aPos]->iUniquePos == aUPos && aDrive==iPluginChain[aPos]->Drive()) sl@0: return aPos; sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: /** sl@0: Finds a plugin by unique position sl@0: */ sl@0: CFsPlugin* FsPluginManager::FindByUniquePosition(TInt aUniquePosition) sl@0: { sl@0: LockChain(); sl@0: CFsPlugin* plugin = NULL; sl@0: TInt count= iPluginChain.Count(); sl@0: for(TInt i=0;iiUniquePos) sl@0: { sl@0: plugin = iPluginChain[i]; sl@0: break; sl@0: } sl@0: } sl@0: UnlockChain(); sl@0: return plugin; sl@0: } sl@0: sl@0: /** sl@0: Create a connection to a plugin sl@0: */ sl@0: CFsPluginConn* FsPluginManager::CreatePluginConnL(TInt aUniquePosition, TUint aClientId) sl@0: { sl@0: CFsPlugin* pP = FindByUniquePosition(aUniquePosition); sl@0: if(pP != NULL) sl@0: { sl@0: CFsPluginConn* pC = pP->NewPluginConnL(); sl@0: CleanupStack::PushL(pC); sl@0: pC->iPluginP = pP; sl@0: pC->iClientId = aClientId; sl@0: iPluginConns->AddL(pC, ETrue); sl@0: CleanupStack::Pop(pC); sl@0: return pC; sl@0: } sl@0: sl@0: User::Leave(KErrNotFound); sl@0: return NULL; sl@0: } sl@0: sl@0: /** sl@0: Create a plugin thread sl@0: Should only by called from main file server thread with plugin thread unavailable sl@0: */ sl@0: TInt FsPluginManager::InitPlugin(CFsPlugin& aPlugin) sl@0: { sl@0: TInt err = KErrNone; sl@0: sl@0: if(!aPlugin.iThreadP) sl@0: { sl@0: TRAP(err,aPlugin.iThreadP=CPluginThread::NewL(aPlugin)); sl@0: if(err!=KErrNone) sl@0: return err; sl@0: } sl@0: sl@0: aPlugin.iThreadId = aPlugin.iThreadP->StartL(); sl@0: return err; sl@0: } sl@0: /** sl@0: Cancels plugin requests sl@0: */ sl@0: void FsPluginManager::CancelPlugin(CFsPlugin* aPlugin,CSessionFs* aSession) sl@0: { sl@0: aPlugin->iThreadP->CompleteSessionRequests(aSession,KErrCancel); sl@0: } sl@0: sl@0: /** sl@0: Gets number of plugins in the plugin stack sl@0: */ sl@0: TInt FsPluginManager::ChainCount() sl@0: { sl@0: return(iPluginChain.Count()); sl@0: } sl@0: sl@0: /** sl@0: * Returns a CFsPlugin* from aPos in the plugin chain. sl@0: * sl@0: * To be called whilst already holding the iChainLock. sl@0: * sl@0: * @returns (via parameter) CFsPlugin*& aPlugin sl@0: */ sl@0: TInt FsPluginManager::Plugin(CFsPlugin*& aPlugin, TInt aPos) sl@0: { sl@0: if(aPos >= iPluginChain.Count() || aPos < 0) sl@0: return KErrNotFound; sl@0: sl@0: aPlugin = iPluginChain[aPos]; sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Locks the chain sl@0: */ sl@0: void FsPluginManager::LockChain() sl@0: { sl@0: iChainLock.Wait(); sl@0: } sl@0: sl@0: /** sl@0: Unlocks the chain sl@0: */ sl@0: void FsPluginManager::UnlockChain() sl@0: { sl@0: iChainLock.Signal(); sl@0: } sl@0: sl@0: /** sl@0: Gets plugin conn from handle sl@0: */ sl@0: CFsPluginConn* FsPluginManager::GetPluginConnFromHandle(CSessionFs* aSession, TInt aHandle) sl@0: { sl@0: return((CFsPluginConn*)(SessionObjectFromHandle(aHandle,iPluginConns->UniqueID(),aSession))); sl@0: } sl@0: sl@0: /** sl@0: Checks if the current thread is plugin conn's thread sl@0: */ sl@0: TBool FsPluginManager::IsPluginConnThread(TThreadId tid, CFsPlugin* aPlugin) sl@0: { sl@0: iPluginConns->Lock(); sl@0: TInt count = iPluginConns->Count(); sl@0: while(count--) sl@0: { sl@0: CFsPluginConn* conn = (CFsPluginConn*)(*iPluginConns)[count]; sl@0: if(conn->Plugin() == aPlugin) sl@0: { sl@0: if(conn->ClientId() == tid) sl@0: { sl@0: iPluginConns->Unlock(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: } sl@0: iPluginConns->Unlock(); sl@0: return EFalse; sl@0: } sl@0: sl@0: /** sl@0: Dispatch a synchronous message sl@0: */ sl@0: void FsPluginManager::DispatchSync(CFsRequest* aRequest) sl@0: { sl@0: __THRD_PRINT(_L("FsPluginManager::DispatchSync")); sl@0: if(!FsThreadManager::IsMainThread() && iScheduler) sl@0: { sl@0: iScheduler->Dispatch(aRequest); sl@0: } sl@0: else sl@0: { sl@0: aRequest->Process(); sl@0: } sl@0: } sl@0: sl@0: void FsPluginManager::CompleteSessionRequests(CSessionFs* aSession, TInt aValue, CFsInternalRequest* aRequest) sl@0: /** sl@0: * Complete outstanding requests for the specified session sl@0: */ sl@0: { sl@0: __PRINT2(_L("FsPluginManager::CompleteSessionRequests(%08x, %d)"), aSession, aValue); sl@0: sl@0: // Iterate through all plugins, cancelling outstanding session requests sl@0: aRequest->Set(CancelPluginOp, aSession); sl@0: sl@0: FsPluginManager::LockChain(); sl@0: TInt count = FsPluginManager::ChainCount(); sl@0: TInt i; sl@0: for(i=0; iiCurrentPlugin = plugin; sl@0: aRequest->Status() = KRequestPending; sl@0: aRequest->Dispatch(); sl@0: //Cancel is delivered to the front of the request queue sl@0: //so hopefully this wont take too long. sl@0: FsPluginManager::UnlockChain(); sl@0: User::WaitForRequest(aRequest->Status()); sl@0: FsPluginManager::LockChain(); sl@0: __ASSERT_ALWAYS(aRequest->Status().Int()==KErrNone||aRequest->Status().Int()==KErrCancel,Fault(ESessionDisconnectThread2)); sl@0: count = FsPluginManager::ChainCount(); sl@0: } sl@0: FsPluginManager::UnlockChain(); sl@0: sl@0: // RDebug::Print(_L("FsPluginManager::CompleteSessionRequests - CSRs")); sl@0: iScheduler->CompleteSessionRequests(aSession, aValue); sl@0: } sl@0: sl@0: