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_sys.cpp
20 #include "sf_file_cache.h"
21 #include <kernel\localise.h>
24 typedef CFileSystem*(*TFileSystemNew)();
25 extern CProxyDriveFactory* GetExtension(const TDesC& aName);
28 extern TBool gInitCacheCheckDrivesAndAddNotifications;
31 struct TFatUtilityFunctions;
32 GLREF_D TCodePageUtils TheCodePage;
33 const TInt KMaxLengthShortNameWithDot = 12;
34 const TUint8 KLeadingE5Replacement = 0x05;
35 const TUint8 KEntryErasedMarker=0xE5; ///< Erased entry marker for a directory entry
40 EXPORT_C CFileSystem::CFileSystem()
42 TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemConstructor, EF32TraceUidFileSys);
43 TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemConstructorReturn, EF32TraceUidFileSys);
49 EXPORT_C CFileSystem::~CFileSystem()
51 TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDestructor, EF32TraceUidFileSys);
52 TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDestructorReturn, EF32TraceUidFileSys);
56 Uninstalls the file system.
58 This is called just before the file system object is destroyed, and allows
59 any clean up to be carried out.
61 The default implementation does nothing except return KErrNone.
62 Implementations should return an error code on error detection.
64 @return KErrNone if successful, otherwise one of the other system wide error
67 EXPORT_C TInt CFileSystem::Remove()
74 Tests whether a version is supported.
76 This is done decided by comparing the supplied version with iVersion.
78 The default implementation uses User::QueryVersionSupported() to
81 @param aVer The version to be tested.
83 @return True, if aVer is supported; false otherwise
85 @see User::QueryVersionSupported
86 @see CFileSystem::iVersion
88 EXPORT_C TBool CFileSystem::QueryVersionSupported(const TVersion& aVer) const
91 return(User::QueryVersionSupported(iVersion,aVer));
94 //#ifndef __DATA_CAGING__
96 Retrieves the default path for the file system.
98 Each session with the file server has a current session path.
99 When a new session is opened, its session path is set to the default path
101 At file server start-up, this default path is set to the default path returned
102 by the local file system.
104 The function should return an appropriate error code when the default path
107 The derived class should override this base class function.
109 This default implementation raises an "Fserv fault" 31 panic.
111 @param aPath On return, contains the default path for the file system for derived classes.
113 @return KErrNone if successful, otherwise one of the other system wide error codes.
115 @panic Fserv fault 31 if the default implementation
116 for CFileSystem::DefaultPath() is not overridden.
118 TInt CFileSystem::DefaultPath(TDes& /*aPath*/) const
121 Fault(ESysDefaultPathNotSupported);
127 Sets the file system's resource library.
129 This library represents the loaded file system.
131 This is called internally by InstallFileSystem().
133 @param aLib The resource library to be set.
135 EXPORT_C void CFileSystem::SetLibrary(RLibrary aLib)
142 Gets the file system's resource library.
144 @return The file system's resource library.
146 EXPORT_C RLibrary CFileSystem::Library() const
152 Tests whether the file system supports extensions.
154 @return True, if the file system supports extensions, false otherwise.
155 The defualt implementation returns false.
157 EXPORT_C TBool CFileSystem::IsExtensionSupported() const
162 EXPORT_C void CFileSystem::DriveInfo(TDriveInfo& aInfo, TInt aDriveNumber) const
164 GetDriveInfo(aInfo, aDriveNumber);
168 EXPORT_C TInt CFileSystem::GetInterface(TInt /*aInterfaceId*/,TAny*& /*aInterface*/,TAny* /*aInput*/)
170 return(KErrNotSupported);
173 EXPORT_C TBool CFileSystem::IsProxyDriveSupported()
175 TAny* dummyInterface;
176 if(GetInterface(EProxyDriveSupport, dummyInterface, NULL) == KErrNone)
182 //-----------------------------------------------------------------------------
184 Extended CMountCB factory interface.
185 Produces the CMountCB object which can be associated with another CFileSystem owner.
186 Used mostly with "automounter" file system
188 @param apDrive in: pointer to TDrive, producing right CMountCB can require media access ("automounter" recognising the file system)
189 @param apFileSystem out: pointer to the CFileSystem object that actually produced CMountCB instance (might be different from "this")
190 @param aForceMount in: ETrue if it is necessarily to force mounting (formatting the media, for example)
191 @param aFsNameHash in: desired file system name hash (optional). Specifies which file system will be used to produce appropriate CMountCB object.
192 The file system that implements NewMountExL() shall decide how to process it. 0 means "default/not specified".
194 @return pointer to the instantiated CMountCB object.
196 CMountCB* CFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash)
200 if(GetInterface(EExtendedFunctionality, pa, NULL) == KErrNone)
201 {//-- special interface for the case, when CMountCB object will be produced by not _this_ CFileSystem object, but some different.
202 //-- in this case apFileSystem will contain a pointer to the real factory.
203 MFileSystemExtInterface* pExtIf = (CFileSystem::MFileSystemExtInterface*)pa;
206 return pExtIf->NewMountExL(apDrive, apFileSystem, aForceMount, aFsNameHash);
209 {//--This interface is not supported by current CFileSystem implementation, call normal legacy factory method
210 //-- and make _this_ object of CFileSystem produce a new CMountCB
211 ASSERT(aFsNameHash == 0); //-- it is impossible to specify the particular FS to be used
212 *apFileSystem = this;
219 //-----------------------------------------------------------------------------
221 Get the name of a filesystem from the list of supported on this drive.
222 Some filesystems (e.g. "automounter" can support more than one real "child" filesystems.
223 For the normal case, only one filesystem is supported (a mouned one).
225 @param aFsNumber used to enumerate supported filesystems can be:
226 special value KRootFileSystem, or
227 0,1,2... - the sequence number of a "child" FS.
229 @param aFsName out: buffer for the returned file system name
231 @return KErrNone Ok, aFsName contains valid value for the given aFsNumber
232 KErrNotFound There is no supported filesystem for the given aFsNumber
234 TInt CFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName)
238 //-- we need a special interface to find out the name of the supported file system number "aFsNumber"
239 if(GetInterface(EExtendedFunctionality, pa, NULL) == KErrNone)
241 MFileSystemExtInterface* pExtIf = (CFileSystem::MFileSystemExtInterface*)pa;
243 return pExtIf->GetSupportedFileSystemName(aFsNumber, aFsName);
246 {//--This interface is not supported by current CFileSystem implementation, but in this case "Root" and first "child" filesystem mean
247 //-- the same and this is "this" filesystem
249 if(aFsNumber == RFs::KRootFileSystem || aFsNumber == RFs::KFirstChildFileSystem)
261 //-----------------------------------------------------------------------------
263 TInt InstallFileSystem(CFileSystem* aSys,RLibrary aLib)
265 // Install a file system.
269 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemInstall, EF32TraceUidFileSys, aSys);
270 TInt r=aSys->Install();
271 TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemInstallRet, EF32TraceUidFileSys, r, aSys->Name());
273 __PRINT1TEMP(_L("InstallFileSystem %S"),aSys->Name());
275 {TRAP(r,FileSystems->AddL(aSys,ETrue))}
278 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemove, EF32TraceUidFileSys, aSys);
279 #ifdef SYMBIAN_FTRACE_ENABLE
284 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemoveRet, EF32TraceUidFileSys, r);
287 aSys->SetLibrary(aLib);
293 EXPORT_C CFileSystem* GetFileSystem(const TDesC& aName)
295 // Lookup a file system by name.
300 TInt r=FileSystems->FindByName(h,aName);
303 return((CFileSystem*)FileSystems->At(h));
306 TInt TFsAddFileSystem::DoRequestL(CFsRequest* aRequest)
308 // Add a file system.
312 __PRINT(_L("TFsAddFileSystem::DoRequestL(CFsRequest* aRequest)"));
315 lib.SetHandle(aRequest->Message().Int0()); // Get library handle
316 if (lib.Type()[1]!=TUid::Uid(KFileSystemUidValue))
317 return KErrNotSupported;
319 TFileSystemNew f=(TFileSystemNew)lib.Lookup(1);
323 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNew, EF32TraceUidFileSys, lib.Handle());
324 CFileSystem* pS=(*f)();
325 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewRet, EF32TraceUidFileSys, pS);
328 TInt r=InstallFileSystem(pS,lib);
329 if (r==KErrNone && !LocalFileSystemInitialized)
331 _LIT(KLocFSY, "ELOCAL.FSY");
332 TFileName fn(lib.FileName());
335 if (ppc.NameAndExt().CompareF(KLocFSY) == 0)
336 r = InitializeLocalFileSystem(pS->Name());
341 TInt TFsAddFileSystem::Initialise(CFsRequest* aRequest)
346 TSecurityPolicy policy(RProcess().SecureId(), ECapabilityTCB);
347 if (!policy.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Add File System")))
348 return KErrPermissionDenied;
352 TInt TFsRemoveFileSystem::DoRequestL(CFsRequest* aRequest)
354 // Remove a file system.
359 aRequest->ReadL(KMsgPtr0,name);
360 CFileSystem* pF=GetFileSystem(name);
362 return(KErrNotFound);
364 CFileSystem* pFs = NULL;
365 for(TInt drvNum=0; drvNum<KMaxDrives; drvNum++)
367 FsThreadManager::LockDrive(drvNum);
368 pFs=TheDrives[drvNum].GetFSys();
369 FsThreadManager::UnlockDrive(drvNum);
373 if(name.CompareF(pFs->Name()) == 0)
377 TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemove, EF32TraceUidFileSys, pF);
379 TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemoveRet, EF32TraceUidFileSys, r);
383 RLibrary lib=pF->Library();
390 TInt TFsRemoveFileSystem::Initialise(CFsRequest* aRequest)
395 if (!KCapFsRemoveFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Remove File System")))
396 return KErrPermissionDenied;
400 LOCAL_C TInt DoMountFileSystem(CFsRequest* aRequest)
405 TInt r = TFileCacheSettings::ReadPropertiesFile(aRequest->Drive()->DriveNumber());
409 return(aRequest->Drive()->CheckMount());
413 LOCAL_C TInt DoMountFsInitialise(CFsRequest* aRequest,TDesC& aFsName,TBool aIsExtension,TBool aIsSync)
418 if (!KCapFsMountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Mount File System")))
419 return KErrPermissionDenied;
421 TInt r=ValidateDrive(aRequest->Message().Int1(),aRequest);
425 TBool driveThreadExists = FsThreadManager::IsDriveAvailable(aRequest->DriveNumber(), ETrue);
426 if(driveThreadExists)
428 // A drive thread already exists for this drive.This could be because a filesystem
429 // is already mounted, or a proxy drive is loaded. Check the mount to be sure...
430 if(aRequest->Drive()->GetFSys())
432 // Yes, a mount already exists so we can't mount another one!
433 return(KErrAccessDenied);
436 __ASSERT_DEBUG(IsProxyDrive(aRequest->DriveNumber()), User::Panic(_L("Bad thread state - No Mount or Proxy Drive Exists!"), -999));
439 // ...therefore no drive thread can be present
440 __ASSERT_DEBUG(!&aRequest->Drive()->FSys(),Fault(EMountFileSystemFSys));
442 if(aRequest->Drive()->IsSubsted())
443 return(KErrAccessDenied);
445 CFileSystem* pF = GetFileSystem(aFsName);
448 return(KErrNotFound);
450 // Check that if the drive is a proxy drive (not using TBusLocalDrive) then the filesystem supports these...
451 TInt driveNumber = aRequest->DriveNumber();
452 if(IsProxyDrive(driveNumber))
454 if(!pF->IsProxyDriveSupported())
455 return KErrNotSupported;
457 r = LocalDrives::SetupMediaChange(driveNumber);
460 TDriveInfo driveInfo;
461 driveInfo.iDriveAtt=0;
462 pF->DriveInfo(driveInfo, driveNumber);
463 if(!driveInfo.iDriveAtt)
466 if(r == KErrNone && !driveThreadExists)
468 // determine whether file system synchronous or not not by flag passed in
469 r=FsThreadManager::InitDrive(driveNumber, aIsSync);
476 //-- let TDrive object know if the drive is synchronous
477 aRequest->Drive()->SetSynchronous(aIsSync);
479 if(aIsExtension && aRequest->Message().Ptr2()!=NULL)
482 r = aRequest->Read(KMsgPtr2,extName);
485 CProxyDriveFactory* pE=GetExtension(extName);
487 return(KErrNotFound);
488 r=aRequest->Drive()->MountExtension(pE,ETrue);
495 _LIT8( KAddAtt, "AddDriveAttributes");
496 _LIT8( KRemoveAtt, "RemoveDriveAttributes");
497 _LIT8( KLogicallyRemovableAtt, "KDRIVEATTLOGICALLYREMOVABLE");
498 _LIT8( KHiddenAtt, "KDRIVEATTHIDDEN");
499 _LIT8( KLogicallyRemovableAttHex, "0X200");
500 _LIT8( KHiddenAttHex, "0X400");
501 TBuf8<0x1000> addbuf;
503 TBuf8<0x1000> removebuf;
505 TInt drive = aRequest->Message().Int1();
506 _LIT8(KLitSectionNameDrive,"Drive%C");
507 TBuf8<8> sectionName;
508 sectionName.Format(KLitSectionNameDrive, 'A' + drive);
509 F32Properties::GetString(sectionName, KAddAtt, addbuf);
510 F32Properties::GetString(sectionName, KRemoveAtt, removebuf); //oldAtt now contains value of the attributes to be removed from iDriveAtt.
512 if(addbuf.Length() != 0)
517 TBool endOfFlag=EFalse;
521 ptr.Set(addbuf.Mid(pos));
522 length = ptr.Locate(',');
524 if(length == KErrNotFound)
529 ptr.Set(ptr.Left(length));
533 if(((ptr.MatchF(KLogicallyRemovableAtt)) != KErrNotFound) || ((ptr.MatchF(KLogicallyRemovableAttHex)) != KErrNotFound))
534 newAtt |= KDriveAttLogicallyRemovable;
535 if(((ptr.MatchF(KHiddenAtt)) != KErrNotFound) || ((ptr.MatchF(KHiddenAttHex)) != KErrNotFound))
536 newAtt |= KDriveAttHidden;
541 if(removebuf.Length() != 0)
546 TBool endOfFlag=EFalse;
550 ptr.Set(removebuf.Mid(pos));
551 length = ptr.Locate(',');
553 if(length == KErrNotFound)
558 ptr.Set(ptr.Left(length));
562 if(((ptr.MatchF(KLogicallyRemovableAtt)) != KErrNotFound) || ((ptr.MatchF(KLogicallyRemovableAttHex)) != KErrNotFound))
563 oldAtt |= KDriveAttLogicallyRemovable;
564 if(((ptr.MatchF(KHiddenAtt)) != KErrNotFound) || ((ptr.MatchF(KHiddenAttHex)) != KErrNotFound))
565 oldAtt |= KDriveAttHidden;
570 if ((newAtt & KDriveAttLogicallyRemovable) && (!(driveInfo.iDriveAtt & KDriveAttRemovable)) && (!(newAtt & KDriveAttRemovable)))
572 newAtt |= KDriveAttRemovable; //KDriveAttLogicallyRemovale should always set KDriveAttRemovale
574 if ((oldAtt & KDriveAttRemovable) && (!(oldAtt & KDriveAttLogicallyRemovable)))
576 oldAtt |= KDriveAttLogicallyRemovable;
580 driveInfo.iDriveAtt |= newAtt;
584 if(oldAtt & driveInfo.iDriveAtt)
586 driveInfo.iDriveAtt ^= oldAtt;
589 aRequest->Drive()->SetAtt(driveInfo.iDriveAtt);
590 aRequest->Drive()->GetFSys()=pF;
592 // empty the closed file queue
593 TClosedFileUtils::Remove(aRequest->DriveNumber());
599 TInt TFsMountFileSystem::DoRequestL(CFsRequest* aRequest)
601 // Mount a filesystem on a drive.
604 TInt r=DoMountFileSystem(aRequest);
607 FsNotify::DiskChange(aRequest->DriveNumber());
610 // Refresh the loader cache to ensure that the new drive is monitored.
612 gInitCacheCheckDrivesAndAddNotifications = EFalse;
619 TInt TFsMountFileSystem::Initialise(CFsRequest* aRequest)
625 TInt r = aRequest->Read(KMsgPtr0,name);
627 r = DoMountFsInitialise(aRequest,name,ETrue,aRequest->Message().Int3());
631 TInt TFsMountFileSystemScan::DoRequestL(CFsRequest* aRequest)
633 // mount file system and then call scandrive
636 TInt r=DoMountFileSystem(aRequest);
637 // run scandrive if successful mount
638 TBool isMountSuccess=(KErrNone==r);
641 r=aRequest->Drive()->ScanDrive();
642 FsNotify::DiskChange(aRequest->DriveNumber());
644 TPtrC8 pMS((TUint8*)&isMountSuccess,sizeof(TBool));
645 aRequest->WriteL(KMsgPtr3,pMS);
650 TInt TFsMountFileSystemScan::Initialise(CFsRequest* aRequest)
656 TInt r = aRequest->Read(KMsgPtr0,name);
658 r = DoMountFsInitialise(aRequest,name,ETrue,EFalse);
662 LOCAL_C TInt DoDismountFileSystem(const TDesC& aName, TDrive* aDrive, TBool aAllowRom, TBool aForceDismount)
664 // Do file system dismount
667 TInt drvNumber=aDrive->DriveNumber();
669 FsThreadManager::LockDrive(drvNumber);
670 CFileSystem* pF=GetFileSystem(aName);
673 FsThreadManager::UnlockDrive(drvNumber);
674 return(KErrNotFound);
676 if(aDrive->IsRom() && !aAllowRom)
678 FsThreadManager::UnlockDrive(drvNumber);
679 return(KErrAccessDenied);
684 if(aDrive->IsMounted() && aDrive->CurrentMount().LockStatus()!=0)
686 FsThreadManager::UnlockDrive(drvNumber);
689 if(aDrive->ActiveMounts() > 1)
691 FsThreadManager::UnlockDrive(drvNumber);
695 aDrive->ReactivateMounts();
698 // ensure that current mount is dismounted
701 TInt r = aDrive->FlushCachedFileInfo(ETrue);
703 // Dismount the file system even if the flush fails for some reason (media permanently removed, user cancels notifier etc
704 if (r!=KErrNone && r!=KErrAbort)
706 FsThreadManager::UnlockDrive(drvNumber);
709 aDrive->ForceDismount();
716 aDrive->GetFSys()=NULL;
718 aDrive->ExtInfo().iCount=0;
720 // no need to cancel requests if synchronous since queued
721 if(!FsThreadManager::IsDriveSync(drvNumber,EFalse))
723 CDriveThread* pT=NULL;
724 TInt r=FsThreadManager::GetDriveThread(drvNumber,&pT);
725 __ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDismountFsDriveThread));
726 pT->CompleteAllRequests(KErrNotReady);
729 if(!IsProxyDrive(drvNumber))
731 // Proxy drives are responsible for managing the drive threads...
732 FsThreadManager::CloseDrive(drvNumber);
735 FsThreadManager::UnlockDrive(drvNumber);
736 FsNotify::DiskChange(drvNumber);
740 TInt TFsDismountFileSystem::DoRequestL(CFsRequest* aRequest)
742 // Dismount a filesystem from a drive.
745 TDrive* drive=aRequest->Drive();
746 __ASSERT_DEBUG(&aRequest->Drive()->FSys() && !drive->IsSubsted(),Fault(EDisMountFileSystemFSys));
748 aRequest->ReadL(KMsgPtr0,name);
750 if(drive->DismountDeferred())
753 return DoDismountFileSystem(name, drive, EFalse, EFalse);
756 TInt TFsDismountFileSystem::Initialise(CFsRequest* aRequest)
761 if (!KCapFsDismountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Dismount File System")))
762 return KErrPermissionDenied;
763 TInt r = ValidateDrive(aRequest->Message().Int1(),aRequest);
766 TInt driveNumber = aRequest->DriveNumber();
767 if(IsProxyDrive(driveNumber))
769 LocalDrives::NotifyChangeCancel(driveNumber);
776 Return name of file system mounted on a specified drive or one of the file system names if
777 the drive supports several of them.
779 TInt TFsFileSystemName::DoRequestL(CFsRequest* aRequest)
782 //-- 0 out: file system name decriptor
784 //-- 2 file system enumerator
786 const TInt driveNumber = aRequest->Message().Int1();
787 if (driveNumber < 0 || driveNumber >= KMaxDrives)
790 const TInt fsNumber = aRequest->Message().Int2(); //-- file system number; for RFs::FileSystemName() it is "-1"
793 // lock drive to synchronise with dismounting a file system
794 FsThreadManager::LockDrive(driveNumber);
795 CFileSystem* pF=TheDrives[driveNumber].GetFSys();
796 FsThreadManager::UnlockDrive(driveNumber);
803 fsName = pF->Name(); //-- this is RFs::FileSystemName() call
805 err = pF->GetSupportedFileSystemName(fsNumber, fsName); //-- this is RFs::SupportedFileSystemName() call
808 {//-- the drive doesn't have file system installed
813 aRequest->WriteL(KMsgPtr0, fsName);
818 TInt TFsFileSystemName::Initialise(CFsRequest* /*aRequest*/)
823 TInt TFsRemountDrive::DoRequestL(CFsRequest* aRequest)
825 // Force a remount of the specified drive
828 const TDesC8 *mountInfo=REINTERPRET_CAST(const TDesC8*,aRequest->Message().Ptr1());
829 return(aRequest->Drive()->ForceRemountDrive(mountInfo,aRequest->Message().Handle(),aRequest->Message().Int2()));//changed from thread to message handle
832 TInt TFsRemountDrive::Initialise(CFsRequest* aRequest)
838 TInt r=ValidateDriveDoSubst(aRequest->Message().Int0(),aRequest);
842 TInt TFsSetLocalDriveMapping::DoRequestL(CFsRequest* aRequest)
844 // set up drive letter to local drive mapping
847 return(LocalDrives::SetDriveMappingL(aRequest));
850 TInt TFsSetLocalDriveMapping::Initialise(CFsRequest* /*aRequest*/)
858 _LIT(KCompositeFsName,"Composite");
860 TInt TFsSwapFileSystem::DoRequestL(CFsRequest* aRequest)
862 // Swap a filesystem on a drive
863 // Should always leave a filesystem mounted on the drive
867 aRequest->ReadL(KMsgPtr0,newName);
868 CFileSystem* pF=GetFileSystem(newName);
870 return(KErrNotFound);
872 aRequest->ReadL(KMsgPtr2,oldName);
873 TInt drvNumber=aRequest->Message().Int1();
874 TBool newFsIsComposite = (newName.CompareF(KCompositeFsName) == 0);
876 if (newFsIsComposite)
879 return(KErrAlreadyExists);
880 if(EDriveZ!=drvNumber)
881 return(KErrNotSupported);
884 // swapping filesystem on z: only allow for romfs + compfs
885 if(EDriveZ==drvNumber)
886 return(KErrNotSupported);
888 TDrive& drive=TheDrives[drvNumber];
890 if(drive.DismountDeferred())
893 TBool clamps=drive.ClampFlag();
897 // Return an error if the drive is asynchronous.
898 // This function is only supported on synchronous drives.
899 TBool isSync = FsThreadManager::IsDriveSync(drvNumber,EFalse);
901 return KErrNotSupported;
903 TInt r=DoDismountFileSystem(oldName,&drive,ETrue,EFalse);
907 __ASSERT_ALWAYS(drive.GetFSys()==NULL,Fault(ESwapFileSystemNull));
909 r=DoMountFsInitialise(aRequest,newName,EFalse,isSync);
911 r=DoMountFileSystem(aRequest);
913 if(drive.GetFSys()==NULL || (newFsIsComposite && r!=KErrNone))
915 // remounting of the original filesystem should not fail
916 if(drive.GetFSys()!=NULL)
917 r=DoDismountFileSystem(newName,&drive,ETrue,EFalse);
919 r=DoMountFsInitialise(aRequest,oldName,EFalse,isSync);
921 r=DoMountFileSystem(aRequest);
923 __ASSERT_ALWAYS(r==KErrNone && drive.GetFSys()!=NULL,Fault(ESwapFileSystemMount));
925 else if (newFsIsComposite)
927 FsThreadManager::ChangeSync(drvNumber,CompFsSync);
931 if(drvNumber==EDriveZ)
933 __ASSERT_ALWAYS(r==KErrNone,Fault(ESwapFileSystemRom));
934 RefreshZDriveCache=ETrue;
939 TInt TFsSwapFileSystem::Initialise(CFsRequest* /*aRequest*/)
948 TInt TFsAddCompositeMount::DoRequestL(CFsRequest* aRequest)
950 // Input fsyName, localDriveNUmber, CompositeDriveNumber
954 __PRINT(_L("TFsAddCompositeMount::DoRequestL"));
957 aRequest->ReadL(KMsgPtr0,fsyName);
958 CFileSystem* pNewFileSystem=GetFileSystem(fsyName);
960 if (pNewFileSystem==NULL)
963 const TInt localDriveNumber=aRequest->Message().Int1();
964 const TInt compositeDriveNumber=aRequest->Message().Int2();
965 const TInt sync=aRequest->Message().Int3();
967 __PRINT3(_L("TFsAddCompositeMount::DoRequestL fsy:%S, locDrv:%d, compDrv:%d"),&fsyName, localDriveNumber,compositeDriveNumber);
969 // Currently, compFS assumed its mounting on romfs, on z:
970 if (compositeDriveNumber!=EDriveZ)
971 return KErrNotSupported;
973 // Mounts can only be added to the compfs, before it is mounted.
977 // The drive is needed, so the new sub mount, can be mounted
978 // on it temporarily. ROMFS doest care if we do this as it
979 // has no local mapping.
980 FsThreadManager::LockDrive(compositeDriveNumber);
982 TRAPD(err, AddFsToCompositeMountL(compositeDriveNumber, *pNewFileSystem, localDriveNumber));
985 FsThreadManager::UnlockDrive(compositeDriveNumber);
988 // Fault(EMountFileSystemFSys);
990 FsThreadManager::UnlockDrive(compositeDriveNumber);
992 // The drive will end up asynchronous if any sub mounts are.
1000 TInt TFsAddCompositeMount::Initialise(CFsRequest* aRequest)
1005 if (!KCapFsAddCompositeMount.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Add Composite Mount")))
1006 return KErrPermissionDenied;
1010 void TFsAddCompositeMount::AddFsToCompositeMountL(TInt aDriveNumber, CFileSystem& aFileSystem, TInt aLocalDriveNumber)
1012 __PRINT3(_L("TFsAddCompositeMount::AddFsToCompositeMountL() FS:0x%x, drv:%d, local drive:%d"),&aFileSystem, aDriveNumber,aLocalDriveNumber);
1015 TDrive& theDrive=TheDrives[aDriveNumber];
1016 CFileSystem* pFs = theDrive.GetFSys();
1018 CFileSystem* pCompFS = GetFileSystem(_L("Composite"));
1019 if ((pCompFS == NULL) || (pFs==NULL))
1020 User::Leave(KErrNotReady);
1022 CMountCB* pMount = pCompFS->NewMountL(); //-- pMount is, actually, a singleton.
1023 pMount->InitL(theDrive, pCompFS);
1026 // invalidate the drive previously used by the local drive just added, and swap with a DriveNumber
1028 drv = LocalDrives::GetDriveFromLocalDrive(aLocalDriveNumber);
1029 __ASSERT_ALWAYS(drv!=KDriveInvalid, User::Leave(KErrNotSupported));
1030 //__PRINT1(_L("TFsAddCompositeMount::AddFsToCompositeMountL : drive to invalidate %d"),drv);
1031 LocalDrives::iMapping[drv] = KDriveInvalid;
1032 LocalDrives::iMapping[aDriveNumber] = aLocalDriveNumber;
1034 // Ask the composite mount to mount the new filesystem.
1036 err = pMount->GetInterfaceTraced(CMountCB::EAddFsToCompositeMount, dummy, &aFileSystem);
1042 TInt TDrive::DeferredDismount()
1045 TInt err = DoDismountFileSystem(GetFSys()->Name(), this, EFalse, ETrue);
1046 if (err == CFsRequest::EReqActionBusy)
1049 DoCompleteDismountNotify(err);
1051 SetDismountDeferred(EFalse);
1056 TInt TFsNotifyDismount::Initialise(CFsRequest* aRequest)
1058 // Initialise a dismount notifier.
1059 // - All clients may register with EFsDismountRegisterClient.
1060 // - DiskAdmin is required for EFsDismountNotifyClients and EFsDismountForceDismount
1063 const RMessage2& m=aRequest->Message();
1064 const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
1068 case EFsDismountForceDismount:
1069 case EFsDismountNotifyClients:
1071 // Capabilities are required to dismount a file system
1072 if(!KCapFsDismountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Notify Dismount")))
1073 return KErrPermissionDenied;
1077 case EFsDismountRegisterClient:
1079 // No capabilities are required for a client to register for notification
1085 return KErrArgument;
1090 return ValidateDrive(aRequest->Message().Int0() ,aRequest);
1093 TInt TFsNotifyDismount::DoRequestL(CFsRequest* aRequest)
1095 // Register for notification of pending dismount [EFsDismountRegisterClient]
1096 // or notify clients of a pending dismount [EFsDismountNotifyClients]
1097 // or forcibly dismount the file system [EFsDismountForceDismount]
1100 __ASSERT_DEBUG(&aRequest->Drive()->FSys() && !aRequest->Drive()->IsSubsted(), Fault(ENotifyDismount));
1102 TInt err = KErrNone;
1104 const RMessage2& m=aRequest->Message();
1105 const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
1106 TDrive* theDrive = aRequest->Drive();
1107 const TInt driveNumber = theDrive->DriveNumber();
1111 case EFsDismountRegisterClient:
1113 err = RegisterNotify(aRequest);
1117 case EFsDismountNotifyClients:
1119 if(aRequest->Drive()->DismountLocked())
1121 err = RegisterNotify(aRequest);
1122 if (err != KErrNone)
1124 // Complete outstanding client dismount notifiers and flag the drive as pending dismount.
1125 FsNotify::HandleDismount(EFsDismountRegisterClient, driveNumber, EFalse, KErrNone);
1126 theDrive->SetDismountDeferred(ETrue);
1130 // There are no interested clients, so dismount immediately - if no clamps are present
1131 err = theDrive->ClampsOnDrive();
1133 // If there are no clamps or clamping is not supported, proceed with the enforced dismount
1134 // If there are clamps, wait for the clamps to be removed
1137 err = RegisterNotify(aRequest);
1138 theDrive->SetDismountDeferred(ETrue);
1140 else if (err == 0 || err == KErrNotSupported)
1142 // No clamps to worry about, so dismount immediately and complete the request
1143 err = DoDismountFileSystem(theDrive->GetFSys()->Name(), theDrive, EFalse, ETrue);
1144 if (err == CFsRequest::EReqActionBusy)
1152 case EFsDismountForceDismount:
1154 // Prepare for deferred dismount due to the presence of file clamps
1155 err = theDrive->ClampsOnDrive();
1157 // If there are no clamps or clamping is not supported, proceed with the enforced dismount
1158 // If there are clamps, wait for the clamps to be removed
1161 err = RegisterNotify(aRequest);
1162 theDrive->SetDismountDeferred(ETrue);
1164 else if (err == 0 || err == KErrNotSupported)
1166 // Forced dismount - notify/remove all client notifiers and complete immediately
1167 err = theDrive->DeferredDismount();
1168 if (err == CFsRequest::EReqActionBusy)
1177 // We shouldn't ever get here
1178 Fault(ENotifyDismount);
1186 TInt TFsNotifyDismount::RegisterNotify(CFsRequest* aRequest)
1188 // Register for notification of pending dismount [EFsDismountRegisterClient]
1189 // or notify clients of a pending dismount [EFsDismountNotifyClients]
1190 // or forcibly dismount the file system [EFsDismountForceDismount]
1193 const RMessage2& m=aRequest->Message();
1194 const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
1195 TDrive* theDrive = aRequest->Drive();
1196 const TInt driveNumber = theDrive->DriveNumber();
1198 if (mode == EFsDismountNotifyClients && theDrive->DismountDeferred())
1203 CDismountNotifyInfo* info = new CDismountNotifyInfo;
1206 return KErrNoMemory;
1209 info->Initialise(mode, driveNumber, (TRequestStatus*)m.Ptr2(), m, aRequest->Session());
1210 TInt err = FsNotify::AddDismountNotify(info);
1220 TInt TFsNotifyDismountCancel::DoRequestL(CFsRequest* aRequest)
1222 // Cancel a pending dismount notifier - Request
1225 CSessionFs* session = aRequest->Session();
1226 FsNotify::CancelDismountNotifySession(session, (TRequestStatus*)aRequest->Message().Ptr0());
1230 TInt TFsNotifyDismountCancel::Initialise(CFsRequest* /*aRequest*/)
1232 // Cancel a pending dismount notifier - Initialise
1238 TInt TFsAllowDismount::DoRequestL(CFsRequest* aRequest)
1240 // Notifies the file server that the client is finished with the drive.
1241 // The last client to allow the dismount signals the dismounting thread.
1244 TDrive* theDrive = aRequest->Drive();
1245 const TInt driveNumber = theDrive->DriveNumber();
1247 // Verify that the client has registered for notification
1248 if(!FsNotify::HandlePendingDismount(aRequest->Session(), driveNumber))
1249 return KErrNotFound;
1251 if(theDrive->DismountLocked())
1254 TInt clampErr = theDrive->ClampsOnDrive();
1255 TInt err = KErrNone;
1257 if ((theDrive->DismountDeferred()) && (clampErr == 0 || clampErr == KErrNotSupported))
1259 // No clamps to worry about, so dismount immediately and complete the request
1260 __ASSERT_DEBUG(aRequest->Drive()->GetFSys(), Fault(EAllowDismount));
1262 // When the last client has responded, allow the media to be forcibly dismounted
1263 err = theDrive->DeferredDismount();
1269 TInt TFsAllowDismount::Initialise(CFsRequest* aRequest)
1271 // Notifies the file server that the client is finished with the drive
1274 return ValidateDrive(aRequest->Message().Int0(),aRequest);
1278 TInt TFsMountProxyDrive::DoRequestL(CFsRequest* aRequest)
1280 return LocalDrives::MountProxyDrive(aRequest);
1283 TInt TFsMountProxyDrive::Initialise(CFsRequest* aRequest)
1285 if (!KCapFsMountProxyDrive.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Mount Proxy Drive")))
1286 return KErrPermissionDenied;
1288 TInt err = LocalDrives::InitProxyDrive(aRequest);
1291 // Now create the drive thread - proxy extensions are always asynchronous...
1292 err = FsThreadManager::InitDrive(aRequest->DriveNumber(), EFalse);
1298 TInt TFsLoadCodePage::DoRequestL(CFsRequest* aRequest)
1300 // Installs a code page
1303 __PRINT(_L("TFsLoadCodePage::DoRequestL(CFsRequest* aRequest)"));
1306 lib.SetHandle(aRequest->Message().Int0());
1307 if (lib.Type()[1]!=TUid::Uid(KLocaleDllUidValue16))
1308 return(KErrNotSupported);
1310 if(TheCodePage.CodepageLoaded() == TCodePageUtils::ECodePageDll)
1312 return(KErrAlreadyExists);
1316 // Actual Functions form the Codepage Dll (fatCnvU.def)
1317 1 : void UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &)
1318 2 : void UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &)
1319 3 : int UnicodeConv::IsLegalShortNameCharacter(unsigned int)
1320 4 : int UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &, int)
1321 5 : int UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &, int)
1325 Read only the following fns from Codepage Dll ( lib.Lookup(1) and lib.Lookup(2) retained in cpnnn.dll for backward compatibility)
1326 3 : int UnicodeConv::IsLegalShortNameCharacter(unsigned int)
1327 4 : int UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &, int)
1328 5 : int UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &, int)
1331 TheCodePage.iCodePageFunctions.iIsLegalShortNameCharacter = (TCodePageFunctions::TIsLegalShortNameCharacter)(lib.Lookup(3));
1332 TheCodePage.iCodePageFunctions.iConvertFromUnicodeL = (TCodePageFunctions::TConvertFromUnicodeL)(lib.Lookup(4));
1333 TheCodePage.iCodePageFunctions.iConvertToUnicodeL = (TCodePageFunctions::TConvertToUnicodeL)(lib.Lookup(5));
1335 if( TheCodePage.iCodePageFunctions.iIsLegalShortNameCharacter == NULL ||
1336 TheCodePage.iCodePageFunctions.iConvertFromUnicodeL == NULL ||
1337 TheCodePage.iCodePageFunctions.iConvertToUnicodeL == NULL )
1339 return(KErrCorrupt);
1341 TheCodePage.iCodepageLoaded = TCodePageUtils::ECodePageDll;
1346 TInt TFsLoadCodePage::Initialise(CFsRequest* aRequest)
1348 // Installs a code page
1351 __PRINT(_L("TFsLoadCodePage::Initialise(CFsRequest* aRequest)"));
1354 TInt drive = aRequest->Session()->CurrentDrive();
1355 aRequest->SetDrive(&TheDrives[drive]);
1357 TSecurityPolicy policy(RProcess().SecureId(), ECapabilityDiskAdmin);
1358 if (!policy.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("TFsLoadCodePage::Initialise")))
1360 return KErrPermissionDenied;
1366 // use second half of ISO Latin 1 character set for extended chars
1367 const TUint KExtendedCharStart=0x80;
1368 const TUint KExtendedCharEnd=0xff;
1370 _LIT8(KLit8ReplacementForUnconvertibleUnicodeCharacters, "_");
1372 TCodePageUtils::TCodePageUtils()
1376 : iCodePageFunctions(),
1377 iLocaleFatUtilityFunctions(NULL),
1378 iCodepageLoaded(ENone)
1382 TBool TCodePageUtils::IsCodepageLoaded() const
1384 // Returns ETrue if a codepage is loaded
1387 return(iCodepageLoaded != ENone);
1390 TCodePageUtils::TCodepageLoaded TCodePageUtils::CodepageLoaded() const
1392 // Returns the type of active codepage
1395 return(iCodepageLoaded);
1398 void TCodePageUtils::SetLocaleCodePage(TFatUtilityFunctions* aFunctions)
1400 // Sets the current codepage to that provided by the current Locale DLL
1403 if(iCodepageLoaded == ENone && aFunctions)
1405 iLocaleFatUtilityFunctions = aFunctions;
1406 iCodepageLoaded = ELocaleDll;
1410 TFatUtilityFunctions* TCodePageUtils::LocaleFatUtilityFunctions() const
1412 // Returns function pointer to the read Locale conversions functions
1415 return(iLocaleFatUtilityFunctions);
1418 TCodePageFunctions TCodePageUtils::CodepageFatUtilityFunctions() const
1420 // Returns structure to function pointers to the read Codepage conversions functions
1423 return(iCodePageFunctions);
1426 TBool TCodePageUtils::ConvertFromUnicode(TDes8& aForeign, const TDesC16& aUnicode, TOverflowAction aOverflowAction) const
1428 Convert from Unicode, truncating if there is not enough room in the output.
1430 @param aForeign The output is appended here.
1431 @param aUnicode The input.
1433 @return False if and only if aForeign has not enough space remaining.
1436 TBool allConverted = ETrue;
1437 const TInt maximumLength=aForeign.MaxLength();
1438 TInt lengthToCopy=aUnicode.Length();
1439 // do not cross the maximum foreign length
1440 if (maximumLength<lengthToCopy)
1442 if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
1444 allConverted = EFalse;
1445 return allConverted;
1447 lengthToCopy=maximumLength;
1450 aForeign.SetLength(lengthToCopy);
1452 TInt j=0; // offset for aForeign[]
1453 TInt i=0; // offset for aUnicode[]
1454 for (i=0; i<lengthToCopy; ++i)
1456 const TDesC8& replacementChar = KLit8ReplacementForUnconvertibleUnicodeCharacters;
1457 TUint32 unicodeChar = aUnicode[i];
1459 // if High Surrogate
1460 if (IsHighSurrogate((TText16)unicodeChar))
1462 // check for low surrogate
1463 if (!IsLowSurrogate(aUnicode[++i]))
1465 aForeign[j++] = (TUint8)replacementChar[0];
1468 unicodeChar = JoinSurrogate((TText16)unicodeChar, (TText16)aUnicode[i]);
1472 if (IsLowSurrogate((TText16)unicodeChar))
1474 aForeign[j++] = (TUint8)replacementChar[0];
1477 // if Supplementary - Non BMP
1478 if (IsSupplementary(unicodeChar))
1480 aForeign[j++] = (TUint8)replacementChar[0];
1485 if((TUint)unicodeChar>=0x100)
1487 aForeign[j++] = (TUint8)replacementChar[0];
1491 aForeign[j++] = (TUint8)unicodeChar;
1496 // if any replacementChar used, aForeign offset(j) shall be less than
1497 // lengthToCopy aUnicode offset(i)
1500 aForeign.SetLength(j);
1503 return(allConverted);
1506 EXPORT_C void TCodePageUtils::ConvertFromUnicodeL(TDes8& aForeign, const TDesC16& aUnicode, TOverflowAction aOverflowAction) const
1508 Convert from Unicode, truncating if there is not enough room in the output.
1510 @param aForeign The output is appended here.
1511 @param aUnicode The input.
1513 @leave KErrOverflow if aForeign is too short for the output.
1517 TBool LeaveWhenError = (TBool)((aOverflowAction==TCodePageUtils::EOverflowActionLeave)?(TBool)ETrue:(TBool)EFalse);
1519 if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iConvertFromUnicodeL)
1521 r = (*iCodePageFunctions.iConvertFromUnicodeL)(aForeign, aUnicode, LeaveWhenError);
1524 else if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iConvertFromUnicodeL)
1526 if(aOverflowAction == TCodePageUtils::EOverflowActionLeave)
1528 (*iLocaleFatUtilityFunctions->iConvertFromUnicodeL)(aForeign, aUnicode, KLit8ReplacementForUnconvertibleUnicodeCharacters, TFatUtilityFunctions::EOverflowActionLeave);
1532 (*iLocaleFatUtilityFunctions->iConvertFromUnicodeL)(aForeign, aUnicode, KLit8ReplacementForUnconvertibleUnicodeCharacters, TFatUtilityFunctions::EOverflowActionTruncate);
1535 // default implementation
1536 else if (!ConvertFromUnicode(aForeign, aUnicode, aOverflowAction))
1538 if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
1540 User::Leave(KErrBadName);
1544 r = r; // remove warning
1545 // File Server do not use this error code so do not send this error code right to File Server
1546 // rather suppress it. Can be used in future.
1550 TBool TCodePageUtils::ConvertToUnicode(TDes16& aUnicode, const TDesC8& aForeign) const
1552 Convert to Unicode, truncating if there is not enough room in the output.
1554 @param aUnicode The output is appended here.
1555 @param aForeign The input.
1557 @return False if and only if aUnicode has not enough space remaining.
1560 // A workaround to handle leading 'E5' byte in short file names
1561 TBuf8<KMaxLengthShortNameWithDot> shortFileNameWithLeadingE5;
1562 TBool convertedLeading05toE5 = EFalse;
1564 if (0 < aForeign.Length() && aForeign.Length() <= 12 && aForeign[0] == KLeadingE5Replacement)
1566 shortFileNameWithLeadingE5 = aForeign;
1567 shortFileNameWithLeadingE5[0] = KEntryErasedMarker;
1568 convertedLeading05toE5 = ETrue;
1571 const TInt maximumLength=aUnicode.MaxLength();
1572 if (maximumLength>=aForeign.Length())
1574 if (convertedLeading05toE5)
1576 aUnicode.Copy(shortFileNameWithLeadingE5);
1580 aUnicode.Copy(aForeign);
1586 if (convertedLeading05toE5)
1588 aUnicode.Copy(shortFileNameWithLeadingE5.Left(maximumLength));
1592 aUnicode.Copy(aForeign.Left(maximumLength));
1598 EXPORT_C void TCodePageUtils::ConvertToUnicodeL(TDes16& aUnicode, const TDesC8& aForeign, TOverflowAction aOverflowAction) const
1600 Convert to Unicode, leaving if there is not enough room in the output.
1602 @param aUnicode The output is appended here.
1603 @param aForeign The input.
1605 @leave KErrOverflow if aUnicode is too short for the output.
1609 TBool LeaveWhenError = (TBool)((aOverflowAction==TCodePageUtils::EOverflowActionLeave)?(TBool)ETrue:(TBool)EFalse);
1611 if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iConvertToUnicodeL)
1613 r = (*iCodePageFunctions.iConvertToUnicodeL)(aUnicode, aForeign, LeaveWhenError);
1616 else if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iConvertToUnicodeL)
1618 if(aOverflowAction == TCodePageUtils::EOverflowActionLeave)
1620 (*iLocaleFatUtilityFunctions->iConvertToUnicodeL)(aUnicode, aForeign, TFatUtilityFunctions::EOverflowActionLeave);
1624 (*iLocaleFatUtilityFunctions->iConvertToUnicodeL)(aUnicode, aForeign, TFatUtilityFunctions::EOverflowActionTruncate);
1627 // default implementation
1628 else if (!ConvertToUnicode(aUnicode, aForeign))
1630 if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
1632 User::Leave(KErrBadName);
1636 r = r; // remove warning
1637 // File Server do not use this error code so do not send this error code right to File Server
1638 // rather suppress it. Can be used in future.
1642 EXPORT_C TBool TCodePageUtils::IsLegalShortNameCharacter(TUint aCharacter,TBool aUseExtendedChars) const
1644 Returns true if the input character is legal in a short name.
1646 @param aCharacter Character, in the foreign character encoding.
1648 @return true if aCharacter is legal in a FAT short name.
1651 if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iIsLegalShortNameCharacter)
1653 return (*iCodePageFunctions.iIsLegalShortNameCharacter)(aCharacter);
1656 if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iIsLegalShortNameCharacter)
1658 return (*iLocaleFatUtilityFunctions->iIsLegalShortNameCharacter)(aCharacter);
1661 // For most common cases:
1662 // Note: lower case characters are considered legal DOS char here.
1663 if ((aCharacter>='a' && aCharacter<='z') ||
1664 (aCharacter>='A' && aCharacter<='Z') ||
1665 (aCharacter>='0' && aCharacter<='9'))
1670 // Default Implmentation
1671 // Checking for illegal chars:
1672 // 1. aCharacter <= 0x20
1673 // Note: leading 0x05 byte should be guarded by callers of this function
1674 // as the information of the position of the character is required.
1675 if (aCharacter < 0x20)
1677 // Space (' ') is not considered as a legal DOS char here.
1678 if (aCharacter == 0x20)
1681 // 2. 0x20 < aCharacter < 0x80
1682 if (0x20 < aCharacter && aCharacter < KExtendedCharStart)
1684 // According to FAT Spec, "following characters are not legal in any bytes of DIR_Name":
1691 // case 0x2E: // '.' // Although '.' is not allowed in any bytes of DIR_Name, it
1692 // is a valid character in short file names.
1710 // 3. 0x80 <= aCharacter <= 0xFF
1711 if (KExtendedCharStart <= aCharacter && aCharacter <= KExtendedCharEnd)
1713 if(aUseExtendedChars)
1719 // 4. aCharacter => 0xFF