Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfile\sf_plugin.cpp
25 #include "sf_plugin_priv.h"
28 EXPORT_C CFsPluginFactory::CFsPluginFactory()
31 EXPORT_C CFsPluginFactory::~CFsPluginFactory()
36 Uninstalls the plugin factory.
38 This is called just before the plugin factory object is destroyed, and allows
39 any clean up to be carried out.
41 The default implementation does nothing except return KErrNone.
42 Implementations should return an error code on error detection.
44 @return KErrNone if successful, otherwise one of the other system wide error
47 EXPORT_C TInt CFsPluginFactory::Remove()
54 Sets the plugin factory's resource library.
55 This library represents the loaded plugin factory.
56 This is called internally by InstallPluginFactory().
58 @param aLib The resource library to be set.
60 EXPORT_C void CFsPluginFactory::SetLibrary(RLibrary aLib)
66 Gets the plugin factory's resource library.
68 @return The plugin factory's resource library.
70 EXPORT_C RLibrary CFsPluginFactory::Library() const
78 TBool CFsPluginFactory::IsDriveSupported(TInt aDrive)
80 //If this is version 1 of the plugins, then if KPluginAutoAttach was specified at mount
81 //then it just returned ETrue! This behaviour is preserved here:
82 if(!(iSupportedDrives & KPluginVersionTwo) && (aDrive == KPluginAutoAttach))
87 //If we're version 2 plugin (or version1 && !KPluginAutoAttach) then check against what's been set in iSupportedDrives
88 return((iSupportedDrives & (1 << aDrive)) ? (TBool)ETrue : (TBool)EFalse);
92 EXPORT_C CFsPlugin::CFsPlugin()
95 Mem::FillZ(iRegisteredIntercepts, sizeof(iRegisteredIntercepts));
98 EXPORT_C CFsPlugin::~CFsPlugin()
103 Delivers the request to the end of plugin thread's queue.
104 In certain circumstances, where the request requires priority handling
105 it adds it to the front of the queue.
107 @param aRequest: The request to be delivered
110 EXPORT_C TInt CFsPlugin::Deliver(TFsPluginRequest& aRequest)
112 __ASSERT_ALWAYS(iThreadP != NULL, User::Panic(_L("CFsPlugin::Dispatch"),999));
114 TInt function = aRequest.Function();
116 if(function == EFsPluginOpen)
118 // Don't dispatch open requests to the plugin thread
119 return KPluginMessageForward;
122 if(function == EFsPluginDoRequest ||
123 function == EFsPluginDoControl ||
124 function == EFsPluginDoCancel)
126 iThreadP->DeliverFront(aRequest.Request());
130 iThreadP->DeliverBack(aRequest.Request());
137 Initialises the plugin but setting all registered intercepts to zero.
138 Derived classes might wish to implement their own InitialiseL to add intercepts
140 EXPORT_C void CFsPlugin::InitialiseL()
145 Creates a new pluginconn object
146 Leaves with KErrNotSupported
150 EXPORT_C CFsPluginConn* CFsPlugin::NewPluginConnL()
152 User::Leave(KErrNotSupported);
157 Registers a particular function with plugin to be intercepted
159 @param aMessage: the message to be intercepted
160 @param aInterceptAtts: If it is post or pre intercept
161 @return KErrNone on successful completion
162 KErrNotSupported if message is invalid
164 EXPORT_C TInt CFsPlugin::RegisterIntercept(TInt aMessage, TInterceptAtts aInterceptAtts)
166 if(aMessage >= EMaxClientOperations)
168 return KErrNotSupported;
171 const TUint32 index = aMessage >> 2; //-- index in the intercepts array
173 if(index >= KIntcArrSize)
175 __ASSERT_DEBUG(0,Fault(EArrayIndexOutOfRange));
176 return KErrNotSupported;
179 const TUint8 msk = (TUint8)(aInterceptAtts << ((aMessage & 0x03) << 1));
180 iRegisteredIntercepts[index] |= msk;
186 Unregisters a particular function with plugin
188 @param aMessage: the message which should be unregistered
189 @param aInterceptAtts: If it is post or pre intercept
190 @return KErrNone on successful completion
191 KErrNotSupported if message is invalid
193 EXPORT_C TInt CFsPlugin::UnregisterIntercept(TInt aMessage, TInterceptAtts aInterceptAtts)
195 if(aMessage >= EMaxClientOperations)
197 return KErrNotSupported;
200 const TUint32 index = aMessage >> 2; //-- index in the intercepts array
201 if(index >= KIntcArrSize)
203 __ASSERT_DEBUG(0,Fault(EArrayIndexOutOfRange));
204 return KErrNotSupported;
207 const TUint8 msk = (TUint8)(aInterceptAtts << ((aMessage & 0x03) << 1));
208 iRegisteredIntercepts[index] &= ~msk;
214 @return ETrue if the message aMessage is registered with any TInterceptAtts type
216 TBool CFsPlugin::IsRegistered(TInt aMessage)
218 if(IsRegistered(aMessage,(TInterceptAtts)EPreIntercept) ||
219 IsRegistered(aMessage,(TInterceptAtts)EPrePostIntercept) ||
220 IsRegistered(aMessage, (TInterceptAtts)EPostIntercept))
224 return (TBool)EFalse;
228 @return ETrue if the message aMessage is registered with the given aInterceptAtts attrubutes
230 TBool CFsPlugin::IsRegistered(TInt aMessage, TInterceptAtts aInterceptAtts)
232 if(aMessage >= EMaxClientOperations)
237 const TUint32 index = aMessage >> 2; //-- index in the intercepts array
238 if(index >= KIntcArrSize)
240 __ASSERT_DEBUG(0,Fault(EArrayIndexOutOfRange));
244 const TUint8 msk = (TUint8)(aInterceptAtts << ((aMessage & 0x03) << 1));
246 return((iRegisteredIntercepts[index] & msk) == msk);
250 Return ETrue if the calling thread is the plugin thread
252 TBool CFsPlugin::IsPluginThread(CFsRequest& aRequest)
254 if(aRequest.iOwnerPlugin == this)
257 if(aRequest.iClientThreadId == iThreadId)
260 // Allow specific requests from the client connection...
261 if(aRequest.IsPluginSpecific())
264 // Check the client connections
265 return FsPluginManager::IsPluginConnThread(aRequest.iClientThreadId, this);
268 TBool CFsPlugin::IsMounted(TInt aDrive)
270 CFsPluginFactory* pF = FsPluginManager::GetPluginFactory(this->Name());
271 TInt supportedDrives = pF->SupportedDrives();
273 //Version1 plugins could not mount on Z Drive as KPluginAutoAttach==0x19==25==EDriveZ
274 //Drive Z is only supported for version two of the plugins.
275 //Prevent version 1 plugins here.
276 if (!(supportedDrives & KPluginVersionTwo) && (aDrive == EDriveZ))
279 //Some requests have aDrive as -1, so for those requests
280 // so long as the plugin was registered we shall say it's mounted.
281 if(aDrive > EDriveZ || aDrive < EDriveA)
284 //Otherwise Check iMountedOn
285 if(iMountedOn&(1<<aDrive))
293 // NOTE: The following API classification might need changing
298 @see RFilePlugin::Read
300 EXPORT_C TInt CFsPlugin::FileRead(TFsPluginRequest& aRequest, TDes8& aDes, TInt64 aPos)
304 GetFileFromScratch((CFsMessageRequest*) aRequest.Request(), share, file);
305 TInt64 fileSize = file->CachedSize64();
308 TInt len = aDes.Length();
309 if (aPos >= fileSize)
311 if (aPos + len > fileSize)
312 // filesize - pos shall of TInt size
313 // Hence to suppress warning
314 len = (TInt)(fileSize - aPos);
317 return DispatchOperation(aRequest, aDes, aPos, EFsFileRead);
323 @see RFilePlugin::Write
325 EXPORT_C TInt CFsPlugin::FileWrite(TFsPluginRequest& aRequest, const TDesC8& aDes, TInt64 aPos)
327 return DispatchOperation(aRequest, (TDes8&) aDes, aPos, EFsFileWrite);
335 Pushes a msgop, dispatches it and waits for it to complete
337 TInt CFsPlugin::DispatchOperation(TFsPluginRequest& aRequest, TDes8& aDes, TInt64 aPos, TInt aFunction)
339 if (aRequest.Function() != EFsFileRead && aRequest.Function() != EFsFileWrite)
340 return KErrNotSupported;
341 if (aFunction != EFsFileRead && aFunction != EFsFileWrite)
342 return KErrNotSupported;
344 CFsMessageRequest& msgRequest = * (CFsMessageRequest*) aRequest.Request();
347 TInt len = aDes.Length();
349 return CFsRequest::EReqActionComplete;
351 TUint8* ptr = (TUint8*) aDes.Ptr();
353 TInt r = msgRequest.PushOperation(
356 Complete, // callback
363 CFsPlugin* plugin = this;
364 FsPluginManager::NextPlugin(plugin, &msgRequest,(TBool)ETrue);
365 msgRequest.iCurrentPlugin = plugin;
366 msgRequest.Dispatch();
367 iThreadP->OperationLockWait();
371 return msgRequest.LastError(); // KErrNone;
374 TInt CFsPlugin::WaitForRequest()
376 iLastError = KErrNone;
377 iThreadP->OperationLockWait();
383 TInt CFsPlugin::Complete(CFsRequest* aRequest, TInt aError)
385 CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
387 CFsPlugin* plugin = msgRequest.iOwnerPlugin;
390 plugin->iLastError = aError;
391 plugin->iThreadP->OperationLockSignal();
392 msgRequest.iOwnerPlugin = NULL;
393 return CFsRequest::EReqActionComplete;
396 TMsgOperation& currentOperation = msgRequest.CurrentOperation();
398 if (currentOperation.iState == 0) // waiting ?
400 currentOperation.iState = 1;
401 msgRequest.iCurrentPlugin->iThreadP->OperationLockSignal();
402 // DON'T dispatch message again, DON'T complete message
403 return CFsRequest::EReqActionOwnedByPlugin;
407 return CFsRequest::EReqActionComplete;
412 TInt CFsPlugin::Complete(CFsRequest* aRequest)
414 return CFsPlugin::Complete(aRequest, KErrNone);
418 EXPORT_C TInt CFsPlugin::ClientWrite(TFsPluginRequest& aRequest, const TDesC8& aDes, TInt aOffset)
420 CFsMessageRequest& msgRequest = * (CFsMessageRequest*) aRequest.Request();
421 TMsgOperation& currentOperation = msgRequest.CurrentOperation();
424 if (currentOperation.iClientRequest)
426 r = msgRequest.Write(0, aDes, aOffset);
430 TInt len = aDes.Length();
431 if (len > (currentOperation.iReadWriteArgs.iTotalLength - aOffset))
433 memcpy(((TUint8*) currentOperation.iReadWriteArgs.iData) + aOffset, aDes.Ptr(), len);
434 currentOperation.iReadWriteArgs.iOffset = aOffset + len;
440 EXPORT_C TInt CFsPlugin::ClientRead(TFsPluginRequest& aRequest, TDes8& aDes, TInt aOffset)
442 CFsMessageRequest& msgRequest = * (CFsMessageRequest*) aRequest.Request();
443 TMsgOperation& currentOperation = msgRequest.CurrentOperation();
446 if (currentOperation.iClientRequest)
448 r = msgRequest.Read(0, aDes, aOffset);
452 TInt len = aDes.Length();
453 if (len > (currentOperation.iReadWriteArgs.iTotalLength - aOffset))
455 aDes.Copy ( (TUint8*) currentOperation.iReadWriteArgs.iData + aOffset, len );
456 currentOperation.iReadWriteArgs.iOffset = aOffset + len;
462 Constructs a TFsPluginRequest object
463 @param aReuqest client's request, to be wrapped by TFsPluginRequest object
465 EXPORT_C TFsPluginRequest::TFsPluginRequest(CFsRequest* aRequest)
466 : iFsRequest(aRequest)
470 @return The function of the request
472 EXPORT_C TInt TFsPluginRequest::Function() const
473 { return(iFsRequest->Operation()->Function()); }
476 @return The drive number of the request
478 EXPORT_C TInt TFsPluginRequest::DriveNumber() const
479 { return(iFsRequest->DriveNumber()); }
482 @return The source of the request (often the filename)
484 EXPORT_C TParse& TFsPluginRequest::Src() const
485 { return(iFsRequest->Src()); }
488 @return The destination of the request (often the filename)
490 EXPORT_C TParse& TFsPluginRequest::Dest() const
491 { return(iFsRequest->Dest()); }
494 @return The drive of the request
496 EXPORT_C TDrive* TFsPluginRequest::Drive() const
497 { return(iFsRequest->Drive()); }
500 @return The substitude drive of the request
502 EXPORT_C TDrive* TFsPluginRequest::SubstedDrive() const
503 { return(iFsRequest->SubstedDrive()); }
506 @return The message of the request
508 EXPORT_C const RMessage2& TFsPluginRequest::Message() const
509 { return(iFsRequest->Message()); }
512 @return The request itself
514 EXPORT_C CFsRequest* TFsPluginRequest::Request() const
516 __ASSERT_DEBUG(iFsRequest != NULL, User::Invariant());
521 @return The scratch value of the request
523 EXPORT_C TUint TFsPluginRequest::ScratchValue() const
524 { return iFsRequest->ScratchValue(); }
527 @return The scratch value of the request
529 EXPORT_C TInt64 TFsPluginRequest::ScratchValue64() const
530 { return iFsRequest->ScratchValue64(); }
533 @return ETrue if the operation is in Post-Intercept
535 EXPORT_C TInt TFsPluginRequest::IsPostOperation() const
536 { return(iFsRequest->IsPostOperation()); }
539 EXPORT_C TInt TFsPluginRequest::Read(TF32ArgType aType, TDes8& aDes, TInt aOffset)
541 return(iFsRequest->Read(aType, aDes, aOffset));
544 EXPORT_C TInt TFsPluginRequest::Read(TF32ArgType aType, TDes16& aDes, TInt aOffset)
546 //The following if packaged correctly will never come here
547 //but just in case someone tries something wrong with a wonky wide descriptor
550 case (TF32ArgType)EEntryArray:
551 case (TF32ArgType)EEntry:
552 case (TF32ArgType)EUid:
553 case (TF32ArgType)ETime:
554 return KErrBadDescriptor;
558 return(iFsRequest->Read(aType, aDes, aOffset));
561 EXPORT_C TInt TFsPluginRequest::Read(TF32ArgType aType, TInt& aVal)
564 // Some messages require special handling...
566 if(aType == (TF32ArgType)EPosition)
571 return iFsRequest->Read(aType, aVal);
574 EXPORT_C TInt TFsPluginRequest::Read(TF32ArgType aType, TUint& aVal)
577 // Some messages require special handling...
579 if(aType == (TF32ArgType)EPosition)
584 return iFsRequest->Read(aType, aVal);
587 EXPORT_C TInt TFsPluginRequest::Read(TF32ArgType aType, TInt64& aVal)
589 TInt err = iFsRequest->Read(aType, aVal);
594 // Some messages require special handling...
596 if(aType == (TF32ArgType)EPosition)
598 TInt op = Function();
599 if(op == EFsFileRead || op == EFsFileWrite)
601 if (aVal == KCurrentPosition64)
603 CFileShare* share = (CFileShare*)iFsRequest->ScratchValue();
605 return KErrBadHandle;
615 EXPORT_C TInt TFsPluginRequest::Write(TF32ArgType aType, const TDesC8& aDes, TInt aOffset)
617 return(iFsRequest->Write(aType, aDes, aOffset));
621 EXPORT_C TInt TFsPluginRequest::Write(TF32ArgType aType, const TDesC16& aDes, TInt aOffset)
623 return(iFsRequest->Write(aType, aDes, aOffset));
626 EXPORT_C TInt TFsPluginRequest::FileName(TDes& aName)
628 //Special handling required for directories.
634 aName.Copy(Request()->Src().FullName());
638 case EFsDirReadPacked:
641 //Get the name from CDirCB::iName
642 CDirCB* dir = (CDirCB*) ScratchValue();
643 __ASSERT_ALWAYS(dir!= NULL, Fault(EPluginOpError));
644 TName name = dir->Name();
655 TInt err = ShareFromClientHandle(share);
656 if(err != KErrNone || share == NULL)
659 NameFromShare(*share, aName);
665 EXPORT_C TInt TFsPluginRequest::SetSharePos(TInt64& aPos)
668 TInt err = ShareFromClientHandle(share);
669 if(err != KErrNone || share == NULL)
670 return(KErrBadHandle);
672 share->File().Drive().Lock();
674 share->File().Drive().UnLock();
679 TInt TFsPluginRequest::ShareFromClientHandle(CFileShare*& aShare)
684 TInt err = ClientSubSessionHandle(handle);
688 aShare = GetShareFromHandle(iFsRequest->Session(), handle);
690 return aShare ? KErrNone : KErrBadHandle;
693 TInt TFsPluginRequest::ClientSubSessionHandle(TInt& aHandle)
697 // Subsession handle is in Arg[3] for read/write etc, but
698 // when subsession create it's contained in client descriptor
699 if(iFsRequest->Operation()->IsOpenSubSess())
701 if(!IsPostOperation())
702 return KErrNotSupported;
704 TPtr8 handleDes((TUint8*)&aHandle,sizeof(TInt));
705 TInt err = iFsRequest->Read(KMsgPtr3,handleDes);
711 aHandle = iFsRequest->Message().Int3();
720 Utility function to obtain the file name from a file share object
722 @param aFileShare A pointer to the file share
723 @param aName A reference to the descriptor to contain the file name
725 void TFsPluginRequest::NameFromShare(CFileShare& aFileShare, TDes& aName)
727 CFileCB& theFile = aFileShare.File();
729 aName[0] = TText('A' + theFile.Drive().DriveNumber());
730 aName.Append(theFile.FileName());
735 Constructor of plugin connection object
737 EXPORT_C CFsPluginConn::CFsPluginConn()
742 Destructor of plugin conn. object
744 EXPORT_C CFsPluginConn::~CFsPluginConn()
749 Closes the plugin conn.
751 EXPORT_C void CFsPluginConn::Close()
753 iRequestQue.DoCancelAll(KErrCancel);
757 CFsPluginConnRequest::CFsPluginConnRequest(CFsPluginConn* aPluginConn)
758 : iPluginConn(*aPluginConn)
762 TInt CFsPluginConnRequest::InitControl(CFsRequest* aRequest)
764 iMessage = aRequest->Message();
765 const RMessage2& m = aRequest->Message();
766 iFunction = m.Int0();
767 iParam1 = (TDes8*)m.Ptr1();
768 iParam2 = (TDes8*)m.Ptr2();
772 TInt CFsPluginConnRequest::DoControl()
774 return iPluginConn.DoControl(*this);
777 TInt CFsPluginConnRequest::InitRequest(CFsRequest* aRequest)
779 InitControl(aRequest);
780 iPluginConn.iRequestQue.DoAddRequest(this);
784 void CFsPluginConnRequest::DoRequest()
786 iPluginConn.DoRequest(*this);
789 TPluginConnRequestQue::TPluginConnRequestQue()
791 iHeader.SetOffset(_FOFF(CFsPluginConnRequest,iLink));
794 TPluginConnRequestQue::~TPluginConnRequestQue()
798 void TPluginConnRequestQue::DoAddRequest(CFsPluginConnRequest* aRequest)
800 iHeader.AddLast(*aRequest);
804 Cancels all the requests of plugin connection
806 @param aCompletionCode: the code the request are completed
808 EXPORT_C void TPluginConnRequestQue::DoCancelAll(TInt aCompletionCode)
810 TDblQueIter<CFsPluginConnRequest> q(iHeader);
811 CFsPluginConnRequest* info;
812 while((info=q++)!=NULL)
814 info->Complete(aCompletionCode);
816 __ASSERT_DEBUG(iHeader.IsEmpty(),Fault(EBaseQueCancel));
822 EXPORT_C TDes8& TRawEntryArray::Buf()
827 EXPORT_C void TRawEntryArray::SetBuf(TDes8& aBuf)
829 iCount = KCountNeeded;
835 EXPORT_C TInt TRawEntryArray::EntrySize(TInt aIdx)
836 { return Align4(::EntrySize((*this)[aIdx])); }