userlibandfileserver/fileserver/sfile/sf_sys.cpp
changeset 0 a41df078684a
child 33 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfile\sf_sys.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "sf_std.h"
       
    19 #include <e32uid.h>
       
    20 #include "sf_file_cache.h"
       
    21 #include <kernel\localise.h>
       
    22 #include <f32file.h>
       
    23 
       
    24 typedef CFileSystem*(*TFileSystemNew)();
       
    25 extern CProxyDriveFactory* GetExtension(const TDesC& aName);
       
    26 
       
    27 #ifndef __WINS__
       
    28 extern TBool gInitCacheCheckDrivesAndAddNotifications;
       
    29 #endif
       
    30 
       
    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
       
    36 
       
    37 /**
       
    38 Default constructor.
       
    39 */
       
    40 EXPORT_C CFileSystem::CFileSystem()
       
    41 	{
       
    42 	TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemConstructor, EF32TraceUidFileSys);
       
    43 	TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemConstructorReturn, EF32TraceUidFileSys);
       
    44 	}
       
    45 
       
    46 /**
       
    47 Destructor.
       
    48 */
       
    49 EXPORT_C CFileSystem::~CFileSystem()
       
    50 	{
       
    51 	TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDestructor, EF32TraceUidFileSys);
       
    52 	TRACE0(UTF::EBorder, UTraceModuleFileSys::ECFileSystemDestructorReturn, EF32TraceUidFileSys);
       
    53 	}
       
    54 
       
    55 /**
       
    56 Uninstalls the file system.
       
    57 
       
    58 This is called just before the file system object is destroyed, and allows
       
    59 any clean up to be carried out.
       
    60 
       
    61 The default implementation does nothing except return KErrNone.
       
    62 Implementations should return an error code on error detection.
       
    63 
       
    64 @return KErrNone if successful, otherwise one of the other system wide error
       
    65         codes.
       
    66 */
       
    67 EXPORT_C TInt CFileSystem::Remove()
       
    68 	{
       
    69 
       
    70 	return(KErrNone);
       
    71 	}
       
    72 
       
    73 /**
       
    74 Tests whether a version is supported.
       
    75 
       
    76 This is done decided by comparing the supplied version with iVersion.
       
    77 
       
    78 The default implementation uses User::QueryVersionSupported() to
       
    79 determine this.
       
    80 
       
    81 @param aVer The version to be tested.
       
    82 
       
    83 @return True, if aVer is supported; false otherwise
       
    84 
       
    85 @see User::QueryVersionSupported
       
    86 @see CFileSystem::iVersion
       
    87 */
       
    88 EXPORT_C TBool CFileSystem::QueryVersionSupported(const TVersion& aVer) const
       
    89 	{
       
    90 
       
    91 	return(User::QueryVersionSupported(iVersion,aVer));
       
    92 	}
       
    93 	
       
    94 //#ifndef __DATA_CAGING__
       
    95 /**
       
    96 Retrieves the default path for the file system.
       
    97 
       
    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
       
   100 of the file server.
       
   101 At file server start-up, this default path is set to the default path returned
       
   102 by the local file system. 
       
   103 
       
   104 The function should return an appropriate error code when the default path
       
   105 cannot be supplied. 
       
   106 
       
   107 The derived class should override this base class function.
       
   108 
       
   109 This default implementation raises an "Fserv fault" 31 panic.
       
   110 
       
   111 @param aPath On return, contains the default path for the file system for derived classes.
       
   112 
       
   113 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   114 
       
   115 @panic Fserv fault 31 if the default implementation
       
   116        for CFileSystem::DefaultPath() is not overridden. 
       
   117 */
       
   118 TInt CFileSystem::DefaultPath(TDes& /*aPath*/) const
       
   119 	{
       
   120 
       
   121 	Fault(ESysDefaultPathNotSupported);
       
   122 	return(KErrNone);
       
   123 	}
       
   124 //#endif
       
   125 
       
   126 /**
       
   127 Sets the file system's resource library.
       
   128 
       
   129 This library represents the loaded file system.
       
   130 
       
   131 This is called internally by InstallFileSystem().
       
   132 
       
   133 @param aLib The resource library to be set.
       
   134 */
       
   135 EXPORT_C void CFileSystem::SetLibrary(RLibrary aLib)
       
   136 	{
       
   137 
       
   138 	iLibrary=aLib;
       
   139 	}
       
   140 
       
   141 /**
       
   142 Gets the file system's resource library.
       
   143 
       
   144 @return The file system's resource library.
       
   145 */
       
   146 EXPORT_C RLibrary CFileSystem::Library() const
       
   147 	{
       
   148 	return(iLibrary);
       
   149 	}
       
   150 
       
   151 /**
       
   152 Tests whether the file system supports extensions.
       
   153 
       
   154 @return True, if the file system supports extensions, false otherwise.
       
   155         The defualt implementation returns false.
       
   156 */
       
   157 EXPORT_C TBool CFileSystem::IsExtensionSupported() const
       
   158 	{
       
   159 	return(EFalse);
       
   160 	}
       
   161 
       
   162 EXPORT_C TInt CFileSystem::GetInterface(TInt /*aInterfaceId*/,TAny*& /*aInterface*/,TAny* /*aInput*/)
       
   163 	{
       
   164 	return(KErrNotSupported);
       
   165 	}
       
   166 
       
   167 EXPORT_C TBool CFileSystem::IsProxyDriveSupported()
       
   168 	{
       
   169 	TAny* dummyInterface;
       
   170 	if(GetInterface(EProxyDriveSupport, dummyInterface, NULL) == KErrNone)
       
   171 		return ETrue;
       
   172 	
       
   173 	return EFalse;
       
   174 	}
       
   175 
       
   176 //----------------------------------------------------------------------------- 
       
   177 /** 
       
   178     Extended CMountCB factory interface.
       
   179     Produces the CMountCB object which can be associated with another CFileSystem owner.
       
   180     Used mostly  with "automounter" file system
       
   181 
       
   182     @param  apDrive         in:  pointer to TDrive, producing right CMountCB can require media access ("automounter" recognising the file system)
       
   183     @param  apFileSystem    out: pointer to the CFileSystem object that actually produced CMountCB instance (might be different from "this")
       
   184     @param  aForceMount     in:  ETrue if it is necessarily to force mounting (formatting the media, for example)
       
   185     @param  aFsNameHash     in:  desired file system name hash (optional). Specifies which file system will be used to produce appropriate CMountCB object.
       
   186                                  The file system that implements NewMountExL() shall decide how to process it. 0 means "default/not specified".
       
   187 
       
   188     @return pointer to the instantiated CMountCB object.
       
   189 */
       
   190 CMountCB* CFileSystem::NewMountExL(TDrive* apDrive, CFileSystem** apFileSystem, TBool aForceMount, TUint32 aFsNameHash)
       
   191     {
       
   192     TAny* pa;
       
   193 
       
   194     if(GetInterface(EExtendedFunctionality, pa, NULL) == KErrNone)
       
   195         {//-- special interface for the case, when CMountCB object will be produced by not _this_ CFileSystem object, but some different.
       
   196          //-- in this case apFileSystem will contain a pointer to the real factory.
       
   197         MFileSystemExtInterface* pExtIf = (CFileSystem::MFileSystemExtInterface*)pa;
       
   198         ASSERT(pExtIf);
       
   199         
       
   200         return pExtIf->NewMountExL(apDrive, apFileSystem, aForceMount, aFsNameHash);
       
   201         }
       
   202     else
       
   203         {//--This interface is not supported by current CFileSystem implementation, call normal legacy factory method
       
   204          //-- and make _this_ object of CFileSystem produce a new CMountCB 
       
   205             ASSERT(aFsNameHash == 0); //-- it is impossible to specify the particular FS to be used
       
   206             *apFileSystem = this; 
       
   207             return NewMountL();
       
   208         }
       
   209         
       
   210     }
       
   211 
       
   212 
       
   213 //----------------------------------------------------------------------------- 
       
   214 /** 
       
   215     Get the name of a filesystem from the list of supported on this drive.
       
   216     Some filesystems (e.g. "automounter" can support more than one real "child" filesystems.
       
   217     For the normal case, only one filesystem is supported (a mouned one).
       
   218 
       
   219     @param  aFsNumber   used to enumerate supported filesystems can be:
       
   220                         special value KRootFileSystem, or
       
   221                         0,1,2... - the sequence number of a "child" FS.
       
   222     
       
   223     @param  aFsName     out: buffer for the returned file system name
       
   224 
       
   225     @return KErrNone        Ok, aFsName contains valid value for the given aFsNumber
       
   226             KErrNotFound    There is no supported filesystem for the given aFsNumber
       
   227 */
       
   228 TInt CFileSystem::GetSupportedFileSystemName(TInt aFsNumber, TDes& aFsName) 
       
   229     {
       
   230     TAny* pa;
       
   231 
       
   232     //-- we need a special interface to find out the name of the supported file system number "aFsNumber"
       
   233     if(GetInterface(EExtendedFunctionality, pa, NULL) == KErrNone)
       
   234         {
       
   235         MFileSystemExtInterface* pExtIf = (CFileSystem::MFileSystemExtInterface*)pa;
       
   236         ASSERT(pExtIf);
       
   237         return pExtIf->GetSupportedFileSystemName(aFsNumber, aFsName);   
       
   238         }
       
   239     else
       
   240         {//--This interface is not supported by current CFileSystem implementation, but in this case "Root" and first "child" filesystem mean
       
   241          //-- the same and this is "this" filesystem
       
   242             
       
   243             if(aFsNumber == RFs::KRootFileSystem || aFsNumber == RFs::KFirstChildFileSystem)
       
   244                 {
       
   245                 aFsName = Name();
       
   246                 return KErrNone;               
       
   247                 }
       
   248             else
       
   249                 {
       
   250                 return KErrNotFound;
       
   251                 }
       
   252         }
       
   253     }
       
   254 
       
   255 //----------------------------------------------------------------------------- 
       
   256 
       
   257 TInt InstallFileSystem(CFileSystem* aSys,RLibrary aLib)
       
   258 //
       
   259 // Install a file system.
       
   260 //
       
   261 	{
       
   262 
       
   263 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemInstall, EF32TraceUidFileSys, aSys);
       
   264 	TInt r=aSys->Install();
       
   265 	TRACERETMULT2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemInstallRet, EF32TraceUidFileSys, r, aSys->Name());
       
   266 
       
   267 	__PRINT1TEMP(_L("InstallFileSystem %S"),aSys->Name());
       
   268 	if (r==KErrNone)
       
   269 		{TRAP(r,FileSystems->AddL(aSys,ETrue))}
       
   270 	if (r!=KErrNone)
       
   271 		{
       
   272 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemove, EF32TraceUidFileSys, aSys);
       
   273 #ifdef SYMBIAN_FTRACE_ENABLE
       
   274 		TInt r = 
       
   275 #endif
       
   276 			aSys->Remove();
       
   277 		
       
   278 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemoveRet, EF32TraceUidFileSys, r);
       
   279 		}
       
   280 	if (r==KErrNone)
       
   281 		aSys->SetLibrary(aLib);
       
   282 	else
       
   283 		aSys->Close();
       
   284 	return(r);
       
   285 	}
       
   286 
       
   287 EXPORT_C CFileSystem* GetFileSystem(const TDesC& aName)
       
   288 //
       
   289 // Lookup a file system by name.
       
   290 //
       
   291 	{
       
   292 
       
   293 	TInt h=0;
       
   294 	TInt r=FileSystems->FindByName(h,aName);
       
   295 	if (r!=KErrNone)
       
   296 		return(NULL);
       
   297 	return((CFileSystem*)FileSystems->At(h));
       
   298 	}
       
   299 
       
   300 TInt TFsAddFileSystem::DoRequestL(CFsRequest* aRequest)
       
   301 //
       
   302 // Add a file system.
       
   303 //
       
   304 	{
       
   305 
       
   306 	__PRINT(_L("TFsAddFileSystem::DoRequestL(CFsRequest* aRequest)"));
       
   307 	
       
   308 	RLibrary lib;
       
   309 	lib.SetHandle(aRequest->Message().Int0()); // Get library handle
       
   310 	if (lib.Type()[1]!=TUid::Uid(KFileSystemUidValue))
       
   311 		return KErrNotSupported;
       
   312 
       
   313 	TFileSystemNew f=(TFileSystemNew)lib.Lookup(1);
       
   314 	if (!f)
       
   315 		return KErrCorrupt;
       
   316 	
       
   317 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNew, EF32TraceUidFileSys, lib.Handle());
       
   318 	CFileSystem* pS=(*f)();
       
   319 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewRet, EF32TraceUidFileSys, pS);
       
   320 	if (!pS)
       
   321 		return KErrNoMemory;
       
   322 	TInt r=InstallFileSystem(pS,lib);
       
   323 	if (r==KErrNone && !LocalFileSystemInitialized)
       
   324 		{
       
   325 		_LIT(KLocFSY, "ELOCAL.FSY");
       
   326 		TFileName fn(lib.FileName());
       
   327 		TParsePtrC ppc(fn);
       
   328 
       
   329 		if (ppc.NameAndExt().CompareF(KLocFSY) == 0)
       
   330 			r = InitializeLocalFileSystem(pS->Name());
       
   331 		}
       
   332 	return r;
       
   333 	}
       
   334 
       
   335 TInt TFsAddFileSystem::Initialise(CFsRequest* aRequest)
       
   336 //
       
   337 //
       
   338 //
       
   339 	{
       
   340 	TSecurityPolicy policy(RProcess().SecureId(), ECapabilityTCB);
       
   341 	if (!policy.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Add File System")))
       
   342 		return KErrPermissionDenied;
       
   343 	return KErrNone;
       
   344 	}
       
   345 
       
   346 TInt TFsRemoveFileSystem::DoRequestL(CFsRequest* aRequest)
       
   347 //
       
   348 // Remove a file system.
       
   349 //
       
   350 	{
       
   351 
       
   352 	TFullName name;
       
   353 	aRequest->ReadL(KMsgPtr0,name);
       
   354 	CFileSystem* pF=GetFileSystem(name);
       
   355 	if (pF==NULL)
       
   356 		return(KErrNotFound);
       
   357 
       
   358 	CFileSystem* pFs = NULL;
       
   359 	for(TInt drvNum=0; drvNum<KMaxDrives; drvNum++)
       
   360 		{
       
   361 		FsThreadManager::LockDrive(drvNum);
       
   362 		pFs=TheDrives[drvNum].GetFSys();
       
   363 		FsThreadManager::UnlockDrive(drvNum);
       
   364 		if(!pFs)
       
   365 			continue;
       
   366 		
       
   367         if(name.CompareF(pFs->Name()) == 0)
       
   368 			return KErrInUse;
       
   369 		}
       
   370 	
       
   371     TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemove, EF32TraceUidFileSys, pF);
       
   372 	TInt r=pF->Remove();
       
   373 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileSystemRemoveRet, EF32TraceUidFileSys, r);
       
   374 	if (r!=KErrNone)
       
   375 		return(r);
       
   376 	
       
   377     RLibrary lib=pF->Library();
       
   378 	pF->Close();
       
   379 	lib.Close();
       
   380 
       
   381     return KErrNone;
       
   382 	}
       
   383 
       
   384 TInt TFsRemoveFileSystem::Initialise(CFsRequest* aRequest)
       
   385 //
       
   386 //
       
   387 //
       
   388 	{
       
   389 	if (!KCapFsRemoveFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Remove File System")))
       
   390 		return KErrPermissionDenied;
       
   391 	return KErrNone;
       
   392 	}
       
   393 
       
   394 LOCAL_C TInt DoMountFileSystem(CFsRequest* aRequest)
       
   395 //
       
   396 //
       
   397 //
       
   398 	{
       
   399 	TInt r = TFileCacheSettings::ReadPropertiesFile(aRequest->Drive()->DriveNumber());
       
   400 	if (r != KErrNone)
       
   401 		return r;
       
   402 
       
   403 	return(aRequest->Drive()->CheckMount());
       
   404 	}
       
   405 
       
   406 
       
   407 LOCAL_C TInt DoMountFsInitialise(CFsRequest* aRequest,TDesC& aFsName,TBool aIsExtension,TBool aIsSync)
       
   408 //
       
   409 //
       
   410 //
       
   411 	{
       
   412 	if (!KCapFsMountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Mount File System")))
       
   413 		return KErrPermissionDenied;
       
   414 
       
   415 	TInt r=ValidateDrive(aRequest->Message().Int1(),aRequest);
       
   416 	if(r!=KErrNone)
       
   417 		return(r);
       
   418 
       
   419 	TBool driveThreadExists = FsThreadManager::IsDriveAvailable(aRequest->DriveNumber(), ETrue);
       
   420 	if(driveThreadExists)
       
   421 		{
       
   422 		// A drive thread already exists for this drive.This could be because a filesystem
       
   423 		// is already mounted, or a proxy drive is loaded.  Check the mount to be sure...
       
   424 		if(aRequest->Drive()->GetFSys())
       
   425 			{
       
   426 			// Yes, a mount already exists so we can't mount another one!
       
   427 			return(KErrAccessDenied);
       
   428 			}
       
   429 
       
   430 		__ASSERT_DEBUG(IsProxyDrive(aRequest->DriveNumber()), User::Panic(_L("Bad thread state - No Mount or Proxy Drive Exists!"), -999));
       
   431 		}
       
   432 
       
   433 	// ...therefore no drive thread can be present
       
   434 	__ASSERT_DEBUG(!&aRequest->Drive()->FSys(),Fault(EMountFileSystemFSys));
       
   435 
       
   436 	if(aRequest->Drive()->IsSubsted())
       
   437 		return(KErrAccessDenied);
       
   438 
       
   439 	CFileSystem* pF = GetFileSystem(aFsName);
       
   440 	
       
   441 	if (pF == NULL)
       
   442 		return(KErrNotFound);
       
   443 
       
   444 	// Check that if the drive is a proxy drive (not using TBusLocalDrive) then the filesystem supports these...
       
   445 	TInt driveNumber = aRequest->DriveNumber();
       
   446 	if(IsProxyDrive(driveNumber))
       
   447 		{
       
   448 		if(!pF->IsProxyDriveSupported())
       
   449 			return KErrNotSupported;
       
   450 		
       
   451 		r = LocalDrives::SetupMediaChange(driveNumber);
       
   452 		}
       
   453 
       
   454 	TDriveInfo driveInfo;
       
   455 	driveInfo.iDriveAtt=0;
       
   456 	pF->DriveInfo(driveInfo, driveNumber);
       
   457 	if(!driveInfo.iDriveAtt)
       
   458 		r = KErrArgument;
       
   459 	
       
   460     if(r == KErrNone && !driveThreadExists)
       
   461 	    {
       
   462     	// determine whether file system synchronous or not not by flag passed in
       
   463 		r=FsThreadManager::InitDrive(driveNumber, aIsSync);
       
   464         }
       
   465 
       
   466 	if(r!=KErrNone)
       
   467 		return(r);
       
   468 
       
   469     
       
   470     //-- let TDrive object know if the drive is synchronous
       
   471 	aRequest->Drive()->SetSynchronous(aIsSync);
       
   472 
       
   473     if(aIsExtension && aRequest->Message().Ptr2()!=NULL)
       
   474 		{
       
   475 		TFullName extName;
       
   476 		r = aRequest->Read(KMsgPtr2,extName);
       
   477 		if (r!=KErrNone)
       
   478 			return r;
       
   479 		CProxyDriveFactory* pE=GetExtension(extName);
       
   480 		if(pE==NULL)
       
   481 			return(KErrNotFound);
       
   482 		r=aRequest->Drive()->MountExtension(pE,ETrue);
       
   483 		if(r!=KErrNone)
       
   484 			return(r);
       
   485 		}
       
   486 
       
   487 	TInt32 newAtt = 0;
       
   488 	TInt32 oldAtt = 0;
       
   489 	_LIT8( KAddAtt, "AddDriveAttributes");
       
   490 	_LIT8( KRemoveAtt, "RemoveDriveAttributes");
       
   491 	_LIT8( KLogicallyRemovableAtt, "KDRIVEATTLOGICALLYREMOVABLE");
       
   492 	_LIT8( KHiddenAtt, "KDRIVEATTHIDDEN");
       
   493 	_LIT8( KLogicallyRemovableAttHex, "0X200");
       
   494 	_LIT8( KHiddenAttHex, "0X400");
       
   495 	TBuf8<0x1000> addbuf;
       
   496 	addbuf.FillZ();
       
   497 	TBuf8<0x1000> removebuf;
       
   498 	removebuf.FillZ();
       
   499 	TInt drive = aRequest->Message().Int1();
       
   500 	_LIT8(KLitSectionNameDrive,"Drive%C");
       
   501 	TBuf8<8> sectionName;
       
   502 	sectionName.Format(KLitSectionNameDrive, 'A' + drive);
       
   503 	F32Properties::GetString(sectionName, KAddAtt, addbuf);
       
   504 	F32Properties::GetString(sectionName, KRemoveAtt, removebuf);  //oldAtt now contains value of the attributes to be removed from iDriveAtt.
       
   505 	
       
   506 	if(addbuf.Length() != 0)
       
   507 		{
       
   508 		TInt pos = 0;
       
   509 		TInt length = 0;
       
   510 		TPtrC8 ptr;
       
   511 		TBool endOfFlag=EFalse; 
       
   512 
       
   513 		while(!endOfFlag)
       
   514 		{
       
   515 		ptr.Set(addbuf.Mid(pos));
       
   516 		length = ptr.Locate(',');
       
   517 	
       
   518 		if(length == KErrNotFound)
       
   519 			{
       
   520 			endOfFlag = ETrue;
       
   521 			} 
       
   522 		else{
       
   523 			ptr.Set(ptr.Left(length));
       
   524 			pos += (length +1);
       
   525 			}
       
   526 		
       
   527 		if(((ptr.MatchF(KLogicallyRemovableAtt)) != KErrNotFound) || ((ptr.MatchF(KLogicallyRemovableAttHex)) != KErrNotFound))
       
   528 			newAtt |= KDriveAttLogicallyRemovable;
       
   529 		if(((ptr.MatchF(KHiddenAtt)) != KErrNotFound)  || ((ptr.MatchF(KHiddenAttHex)) != KErrNotFound))
       
   530 			newAtt |= KDriveAttHidden;
       
   531 		
       
   532 		}
       
   533 		}
       
   534 
       
   535 	if(removebuf.Length() != 0)
       
   536 		{
       
   537 		TInt pos = 0;
       
   538 		TInt length = 0;
       
   539 		TPtrC8 ptr;
       
   540 		TBool endOfFlag=EFalse; 
       
   541 
       
   542 		while(!endOfFlag)
       
   543 		{
       
   544 		ptr.Set(removebuf.Mid(pos));
       
   545 		length = ptr.Locate(',');
       
   546 	
       
   547 		if(length == KErrNotFound)
       
   548 			{
       
   549 			endOfFlag = ETrue;
       
   550 			} 
       
   551 		else{
       
   552 			ptr.Set(ptr.Left(length));
       
   553 			pos += (length +1);
       
   554 			}
       
   555 		
       
   556 		if(((ptr.MatchF(KLogicallyRemovableAtt)) != KErrNotFound) || ((ptr.MatchF(KLogicallyRemovableAttHex)) != KErrNotFound))
       
   557 			oldAtt |= KDriveAttLogicallyRemovable;
       
   558 		if(((ptr.MatchF(KHiddenAtt)) != KErrNotFound) || ((ptr.MatchF(KHiddenAttHex)) != KErrNotFound))
       
   559 			oldAtt |= KDriveAttHidden;
       
   560 		
       
   561 		}
       
   562 		}
       
   563 	
       
   564 	if ((newAtt & KDriveAttLogicallyRemovable) && (!(driveInfo.iDriveAtt & KDriveAttRemovable)) && (!(newAtt & KDriveAttRemovable)))
       
   565 		{
       
   566 		newAtt |= KDriveAttRemovable; 	//KDriveAttLogicallyRemovale should always set KDriveAttRemovale
       
   567 		}
       
   568 	if ((oldAtt & KDriveAttRemovable)  && (!(oldAtt & KDriveAttLogicallyRemovable)))
       
   569 		{
       
   570 		oldAtt |= KDriveAttLogicallyRemovable;
       
   571 		}
       
   572 	if(newAtt)
       
   573 		{
       
   574 		driveInfo.iDriveAtt |= newAtt;
       
   575 		}
       
   576 	if(oldAtt)
       
   577 		{
       
   578 		if(oldAtt & driveInfo.iDriveAtt)
       
   579 			{
       
   580 			driveInfo.iDriveAtt ^= oldAtt;  
       
   581 			}
       
   582 		}
       
   583 	aRequest->Drive()->SetAtt(driveInfo.iDriveAtt);
       
   584 	aRequest->Drive()->GetFSys()=pF;
       
   585 
       
   586 	// empty the closed file queue
       
   587 	TClosedFileUtils::Remove(aRequest->DriveNumber());
       
   588 
       
   589 	return(KErrNone);
       
   590 	}
       
   591 
       
   592 
       
   593 TInt TFsMountFileSystem::DoRequestL(CFsRequest* aRequest)
       
   594 //
       
   595 // Mount a filesystem on a drive.
       
   596 //
       
   597 	{
       
   598 	TInt r=DoMountFileSystem(aRequest);
       
   599 	if( KErrNone == r )
       
   600 		{
       
   601 		FsNotify::DiskChange(aRequest->DriveNumber());
       
   602 		}
       
   603 		
       
   604 	// Refresh the loader cache to ensure that the new drive is monitored.
       
   605 #ifndef __WINS__
       
   606 	gInitCacheCheckDrivesAndAddNotifications = EFalse;
       
   607 #endif 
       
   608 
       
   609 	return r;
       
   610 	}
       
   611 
       
   612 
       
   613 TInt TFsMountFileSystem::Initialise(CFsRequest* aRequest)
       
   614 //
       
   615 //	
       
   616 //
       
   617 	{
       
   618 	TFullName name;
       
   619 	TInt r = aRequest->Read(KMsgPtr0,name);
       
   620 	if (r == KErrNone)
       
   621 		r = DoMountFsInitialise(aRequest,name,ETrue,aRequest->Message().Int3());
       
   622 	return r;
       
   623 	}
       
   624 
       
   625 TInt TFsMountFileSystemScan::DoRequestL(CFsRequest* aRequest)
       
   626 //
       
   627 // mount file system and then call scandrive
       
   628 //
       
   629 	{
       
   630 	TInt r=DoMountFileSystem(aRequest);
       
   631 	// run scandrive if successful mount
       
   632 	TBool isMountSuccess=(KErrNone==r);
       
   633 	if(isMountSuccess)
       
   634 		{
       
   635 		r=aRequest->Drive()->ScanDrive();
       
   636 		FsNotify::DiskChange(aRequest->DriveNumber());
       
   637 		}
       
   638 	TPtrC8 pMS((TUint8*)&isMountSuccess,sizeof(TBool));
       
   639 	aRequest->WriteL(KMsgPtr3,pMS);
       
   640 	return(r);
       
   641 	}
       
   642 
       
   643 
       
   644 TInt TFsMountFileSystemScan::Initialise(CFsRequest* aRequest)
       
   645 //
       
   646 //	
       
   647 //
       
   648 	{
       
   649 	TFullName name;
       
   650 	TInt r = aRequest->Read(KMsgPtr0,name);
       
   651 	if (r == KErrNone)
       
   652 		r = DoMountFsInitialise(aRequest,name,ETrue,EFalse);
       
   653 	return r;
       
   654 	}
       
   655 
       
   656 LOCAL_C TInt DoDismountFileSystem(const TDesC& aName, TDrive* aDrive, TBool aAllowRom, TBool aForceDismount)
       
   657 //
       
   658 // Do file system dismount
       
   659 //
       
   660 	{
       
   661 	TInt drvNumber=aDrive->DriveNumber();
       
   662 
       
   663 	FsThreadManager::LockDrive(drvNumber);
       
   664 	CFileSystem* pF=GetFileSystem(aName);
       
   665 	if(pF==NULL)
       
   666 		{
       
   667 		FsThreadManager::UnlockDrive(drvNumber);
       
   668 		return(KErrNotFound);
       
   669 		}
       
   670 	if(aDrive->IsRom() && !aAllowRom)
       
   671 		{
       
   672 		FsThreadManager::UnlockDrive(drvNumber);
       
   673 		return(KErrAccessDenied);
       
   674 		}
       
   675 
       
   676 	if(!aForceDismount)
       
   677 		{
       
   678 		if(aDrive->IsMounted() && aDrive->CurrentMount().LockStatus()!=0)
       
   679 			{
       
   680 			FsThreadManager::UnlockDrive(drvNumber);
       
   681 			return(KErrInUse);
       
   682 			}
       
   683 		if(aDrive->ActiveMounts() > 1)
       
   684 			{
       
   685 			FsThreadManager::UnlockDrive(drvNumber);
       
   686 			return(KErrInUse);
       
   687 			}
       
   688 		
       
   689 		aDrive->ReactivateMounts();
       
   690 		}
       
   691 
       
   692 	// ensure that current mount is dismounted
       
   693 	if(aForceDismount)
       
   694 		{
       
   695 		TInt r = aDrive->FlushCachedFileInfo(ETrue);
       
   696 
       
   697 		// Dismount the file system even if the flush fails for some reason (media permanently removed, user cancels notifier etc
       
   698 		if (r!=KErrNone && r!=KErrAbort)
       
   699 			{
       
   700 			FsThreadManager::UnlockDrive(drvNumber);
       
   701 			return(r);
       
   702 			}
       
   703 		aDrive->ForceDismount();
       
   704 		}
       
   705 	else
       
   706 		{
       
   707 		aDrive->Dismount();
       
   708 		}
       
   709 
       
   710 	aDrive->GetFSys()=NULL;
       
   711 	aDrive->SetAtt(0);
       
   712 	aDrive->ExtInfo().iCount=0;
       
   713 
       
   714 	// no need to cancel requests if synchronous since queued
       
   715 	if(!FsThreadManager::IsDriveSync(drvNumber,EFalse))
       
   716 		{
       
   717 		CDriveThread* pT=NULL;
       
   718 		TInt r=FsThreadManager::GetDriveThread(drvNumber,&pT);
       
   719 		__ASSERT_ALWAYS(r==KErrNone && pT,Fault(EDismountFsDriveThread));
       
   720 		pT->CompleteAllRequests(KErrNotReady);
       
   721 		}
       
   722 
       
   723 	if(!IsProxyDrive(drvNumber))
       
   724 		{
       
   725 		// Proxy drives are responsible for managing the drive threads...
       
   726 		FsThreadManager::CloseDrive(drvNumber);
       
   727 		}
       
   728 
       
   729 	FsThreadManager::UnlockDrive(drvNumber);
       
   730 	FsNotify::DiskChange(drvNumber);
       
   731 	return(KErrNone);
       
   732 	}
       
   733 
       
   734 TInt TFsDismountFileSystem::DoRequestL(CFsRequest* aRequest)
       
   735 //
       
   736 // Dismount a filesystem from a drive.
       
   737 //
       
   738 	{
       
   739 	TDrive* drive=aRequest->Drive();
       
   740 	__ASSERT_DEBUG(&aRequest->Drive()->FSys() && !drive->IsSubsted(),Fault(EDisMountFileSystemFSys));
       
   741 	TFullName name;
       
   742 	aRequest->ReadL(KMsgPtr0,name);
       
   743 
       
   744 	if(drive->DismountDeferred())
       
   745 		return KErrInUse;
       
   746 
       
   747 	return DoDismountFileSystem(name, drive, EFalse, EFalse);
       
   748 	}
       
   749 
       
   750 TInt TFsDismountFileSystem::Initialise(CFsRequest* aRequest)
       
   751 //
       
   752 //	
       
   753 //
       
   754 	{
       
   755 	if (!KCapFsDismountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Dismount File System")))
       
   756 		return KErrPermissionDenied;
       
   757 	TInt r = ValidateDrive(aRequest->Message().Int1(),aRequest);
       
   758 	if(r == KErrNone)
       
   759 		{
       
   760 		TInt driveNumber = aRequest->DriveNumber();
       
   761 		if(IsProxyDrive(driveNumber))
       
   762 			{
       
   763 			LocalDrives::NotifyChangeCancel(driveNumber);
       
   764 			}
       
   765 		}
       
   766 	return r;
       
   767 	}
       
   768 
       
   769 /**
       
   770     Return name of file system mounted on a specified drive or one of the file system names if 
       
   771     the drive supports several of them.
       
   772 */
       
   773 TInt TFsFileSystemName::DoRequestL(CFsRequest* aRequest)
       
   774 	{
       
   775 	//-- ipc parameters: 
       
   776     //-- 0 out: file system name decriptor
       
   777     //-- 1 drive number
       
   778     //-- 2 file system enumerator 
       
   779     
       
   780     const TInt driveNumber = aRequest->Message().Int1();
       
   781 	if (driveNumber < 0 || driveNumber >= KMaxDrives)
       
   782 		return KErrArgument;
       
   783 	
       
   784     const TInt fsNumber = aRequest->Message().Int2(); //-- file system number; for RFs::FileSystemName() it is "-1"
       
   785 
       
   786     TFullName fsName;
       
   787 	// lock drive to synchronise with dismounting a file system
       
   788 	FsThreadManager::LockDrive(driveNumber);
       
   789 	CFileSystem* pF=TheDrives[driveNumber].GetFSys();
       
   790 	FsThreadManager::UnlockDrive(driveNumber);
       
   791     
       
   792     TInt err = KErrNone;
       
   793 	
       
   794     if(pF)
       
   795         {
       
   796 		if(fsNumber == -1)
       
   797             fsName = pF->Name(); //-- this is RFs::FileSystemName() call
       
   798         else
       
   799             err = pF->GetSupportedFileSystemName(fsNumber, fsName); //-- this is RFs::SupportedFileSystemName() call
       
   800 	    }
       
   801 	else
       
   802 		{//-- the drive doesn't have file system installed
       
   803         fsName=_L("");
       
   804 		err = KErrNotFound;
       
   805 	    }
       
   806     
       
   807     aRequest->WriteL(KMsgPtr0, fsName);
       
   808 	
       
   809     return err;
       
   810 	}
       
   811 
       
   812 TInt TFsFileSystemName::Initialise(CFsRequest* /*aRequest*/)
       
   813 	{
       
   814 	return KErrNone;
       
   815 	}
       
   816 
       
   817 TInt TFsRemountDrive::DoRequestL(CFsRequest* aRequest)
       
   818 //
       
   819 // Force a remount of the specified drive
       
   820 //
       
   821 	{	
       
   822 	const TDesC8 *mountInfo=REINTERPRET_CAST(const TDesC8*,aRequest->Message().Ptr1());
       
   823 	return(aRequest->Drive()->ForceRemountDrive(mountInfo,aRequest->Message().Handle(),aRequest->Message().Int2()));//changed from thread to message handle
       
   824 	}
       
   825 
       
   826 TInt TFsRemountDrive::Initialise(CFsRequest* aRequest)
       
   827 //
       
   828 //	
       
   829 //
       
   830 	{
       
   831 
       
   832 	TInt r=ValidateDriveDoSubst(aRequest->Message().Int0(),aRequest);
       
   833 	return(r);
       
   834 	}
       
   835 
       
   836 TInt TFsSetLocalDriveMapping::DoRequestL(CFsRequest* aRequest)
       
   837 //
       
   838 // set up drive letter to local drive mapping
       
   839 //
       
   840 	{
       
   841 	return(LocalDrives::SetDriveMappingL(aRequest));
       
   842 	}
       
   843 
       
   844 TInt TFsSetLocalDriveMapping::Initialise(CFsRequest* /*aRequest*/)
       
   845 //
       
   846 //
       
   847 //
       
   848 	{
       
   849 	return KErrNone;
       
   850 	}
       
   851 	
       
   852 _LIT(KCompositeFsName,"Composite");
       
   853 
       
   854 TInt TFsSwapFileSystem::DoRequestL(CFsRequest* aRequest)
       
   855 //
       
   856 // Swap a filesystem on a drive
       
   857 // Should always leave a filesystem mounted on the drive
       
   858 //
       
   859 	{
       
   860 	TFileName newName;
       
   861 	aRequest->ReadL(KMsgPtr0,newName);										
       
   862 	CFileSystem* pF=GetFileSystem(newName);												
       
   863 	if (pF==NULL)															
       
   864 		return(KErrNotFound);
       
   865 	TFileName oldName;			
       
   866 	aRequest->ReadL(KMsgPtr2,oldName);										
       
   867 	TInt drvNumber=aRequest->Message().Int1();	
       
   868 	TBool newFsIsComposite = (newName.CompareF(KCompositeFsName) == 0);	
       
   869 							
       
   870 	if (newFsIsComposite)
       
   871 		{
       
   872 		if(CompFsMounted)
       
   873 			return(KErrAlreadyExists);
       
   874 		if(EDriveZ!=drvNumber)
       
   875 			return(KErrNotSupported);
       
   876 		}	
       
   877 	else
       
   878 		 // swapping filesystem on z: only allow for romfs + compfs
       
   879 		if(EDriveZ==drvNumber)
       
   880 			return(KErrNotSupported);
       
   881 	
       
   882 	TDrive& drive=TheDrives[drvNumber];
       
   883 	
       
   884 	if(drive.DismountDeferred())
       
   885 		return KErrInUse;
       
   886 
       
   887 	TBool clamps=drive.ClampFlag();
       
   888 	if(clamps)
       
   889 		return KErrInUse;
       
   890 
       
   891 	// Return an error if the drive is asynchronous.
       
   892 	// This function is only supported on synchronous drives.
       
   893 	TBool isSync = FsThreadManager::IsDriveSync(drvNumber,EFalse);
       
   894 	if(!isSync)
       
   895 		return KErrNotSupported;
       
   896 	
       
   897 	TInt r=DoDismountFileSystem(oldName,&drive,ETrue,EFalse);
       
   898 	if(r!=KErrNone)
       
   899 		return(r);
       
   900 	
       
   901 	__ASSERT_ALWAYS(drive.GetFSys()==NULL,Fault(ESwapFileSystemNull));
       
   902 
       
   903 	r=DoMountFsInitialise(aRequest,newName,EFalse,isSync);
       
   904 	if(r==KErrNone)
       
   905 		r=DoMountFileSystem(aRequest);
       
   906 
       
   907 	if(drive.GetFSys()==NULL || (newFsIsComposite && r!=KErrNone)) 
       
   908 		{
       
   909 		// remounting of the original filesystem should not fail
       
   910 		if(drive.GetFSys()!=NULL)
       
   911 			r=DoDismountFileSystem(newName,&drive,ETrue,EFalse);
       
   912 
       
   913 		r=DoMountFsInitialise(aRequest,oldName,EFalse,isSync);
       
   914 		if(r==KErrNone)
       
   915 			r=DoMountFileSystem(aRequest);
       
   916 
       
   917 		__ASSERT_ALWAYS(r==KErrNone && drive.GetFSys()!=NULL,Fault(ESwapFileSystemMount));
       
   918 		}
       
   919 	else if (newFsIsComposite)
       
   920 		{
       
   921 		FsThreadManager::ChangeSync(drvNumber,CompFsSync);
       
   922 		CompFsMounted=ETrue;
       
   923 		}
       
   924 			
       
   925 	if(drvNumber==EDriveZ)
       
   926 		{
       
   927 		__ASSERT_ALWAYS(r==KErrNone,Fault(ESwapFileSystemRom));
       
   928 		RefreshZDriveCache=ETrue;
       
   929 		}
       
   930 	return(r);
       
   931 	}
       
   932 
       
   933 TInt TFsSwapFileSystem::Initialise(CFsRequest* /*aRequest*/)
       
   934 //
       
   935 //	
       
   936 //
       
   937 	{
       
   938 	return KErrNone;
       
   939 	}	
       
   940 
       
   941 
       
   942 TInt TFsAddCompositeMount::DoRequestL(CFsRequest* aRequest)
       
   943 //
       
   944 // Input fsyName, localDriveNUmber, CompositeDriveNumber
       
   945 // 
       
   946 //
       
   947 	{
       
   948 	__PRINT(_L("TFsAddCompositeMount::DoRequestL"));
       
   949 
       
   950 	TFileName fsyName;
       
   951 	aRequest->ReadL(KMsgPtr0,fsyName);										
       
   952 	CFileSystem* pNewFileSystem=GetFileSystem(fsyName);
       
   953 
       
   954 	if (pNewFileSystem==NULL)
       
   955 		return KErrNotFound;
       
   956 	
       
   957 	const TInt localDriveNumber=aRequest->Message().Int1();								
       
   958 	const TInt compositeDriveNumber=aRequest->Message().Int2();
       
   959 	const TInt sync=aRequest->Message().Int3();									
       
   960 	
       
   961     __PRINT3(_L("TFsAddCompositeMount::DoRequestL fsy:%S, locDrv:%d, compDrv:%d"),&fsyName, localDriveNumber,compositeDriveNumber);
       
   962 
       
   963 	// Currently, compFS assumed its mounting on romfs, on z:
       
   964 	if (compositeDriveNumber!=EDriveZ)
       
   965 		return KErrNotSupported;
       
   966 	
       
   967 	// Mounts can only be added to the compfs, before it is mounted.
       
   968 	if (CompFsMounted)
       
   969 		return KErrInUse;
       
   970 	
       
   971 	// The drive is needed, so the new sub mount, can be mounted
       
   972 	// on it temporarily.  ROMFS doest care if we do this as it
       
   973 	// has no local mapping.
       
   974 	FsThreadManager::LockDrive(compositeDriveNumber);
       
   975 		
       
   976 	TRAPD(err, AddFsToCompositeMountL(compositeDriveNumber, *pNewFileSystem, localDriveNumber));
       
   977 	if (err!=KErrNone)
       
   978 		{
       
   979 		FsThreadManager::UnlockDrive(compositeDriveNumber);
       
   980 		return err;
       
   981 		}
       
   982 //		Fault(EMountFileSystemFSys);
       
   983 
       
   984 	FsThreadManager::UnlockDrive(compositeDriveNumber);
       
   985 	
       
   986 	// The drive will end up asynchronous if any sub mounts are.
       
   987 	if (!sync)
       
   988 		CompFsSync=EFalse;
       
   989 
       
   990 	return KErrNone;
       
   991 	}
       
   992 
       
   993 
       
   994 TInt TFsAddCompositeMount::Initialise(CFsRequest* aRequest)
       
   995 //
       
   996 //	
       
   997 //
       
   998 	{
       
   999 	if (!KCapFsAddCompositeMount.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Add Composite Mount")))
       
  1000 		return KErrPermissionDenied;
       
  1001 	return KErrNone;
       
  1002 	}	
       
  1003 
       
  1004 void TFsAddCompositeMount::AddFsToCompositeMountL(TInt aDriveNumber, CFileSystem& aFileSystem, TInt aLocalDriveNumber)
       
  1005 	{
       
  1006 	__PRINT3(_L("TFsAddCompositeMount::AddFsToCompositeMountL()  FS:0x%x, drv:%d, local drive:%d"),&aFileSystem, aDriveNumber,aLocalDriveNumber);
       
  1007 	TInt err;
       
  1008 
       
  1009 	TDrive& theDrive=TheDrives[aDriveNumber];
       
  1010 	CFileSystem* pFs = theDrive.GetFSys();
       
  1011 	
       
  1012 	CFileSystem* pCompFS = GetFileSystem(_L("Composite"));
       
  1013 	if ((pCompFS == NULL) || (pFs==NULL))
       
  1014 		User::Leave(KErrNotReady);
       
  1015 	
       
  1016 	CMountCB* pMount = pCompFS->NewMountL(); //-- pMount is, actually, a singleton.
       
  1017     pMount->InitL(theDrive, pCompFS);
       
  1018 
       
  1019     
       
  1020 	// invalidate the drive previously used by the local drive just added, and swap with a DriveNumber
       
  1021 	TInt drv;
       
  1022 	drv = LocalDrives::GetDriveFromLocalDrive(aLocalDriveNumber);
       
  1023 	__ASSERT_ALWAYS(drv!=KDriveInvalid, User::Leave(KErrNotSupported));
       
  1024 	//__PRINT1(_L("TFsAddCompositeMount::AddFsToCompositeMountL : drive to invalidate %d"),drv);
       
  1025 	LocalDrives::iMapping[drv] = KDriveInvalid;
       
  1026 	LocalDrives::iMapping[aDriveNumber] = aLocalDriveNumber;
       
  1027 
       
  1028 	// Ask the composite mount to mount the new filesystem.
       
  1029 	TAny* dummy=NULL;
       
  1030 	err = pMount->GetInterfaceTraced(CMountCB::EAddFsToCompositeMount, dummy, &aFileSystem);
       
  1031 	if(err != KErrNone)
       
  1032 		User::Leave(err);
       
  1033 	}
       
  1034 
       
  1035 
       
  1036 TInt TDrive::DeferredDismount()
       
  1037 	{
       
  1038 	// Dismount
       
  1039 	TInt err = DoDismountFileSystem(GetFSys()->Name(), this, EFalse, ETrue);
       
  1040 	if (err == CFsRequest::EReqActionBusy)
       
  1041 		return err;
       
  1042 
       
  1043     DoCompleteDismountNotify(err);
       
  1044 
       
  1045 	SetDismountDeferred(EFalse);
       
  1046 
       
  1047 	return err;
       
  1048 	}
       
  1049 
       
  1050 TInt TFsNotifyDismount::Initialise(CFsRequest* aRequest)
       
  1051 //
       
  1052 // Initialise a dismount notifier. 
       
  1053 // - All clients may register with EFsDismountRegisterClient.
       
  1054 // - DiskAdmin is required for EFsDismountNotifyClients and EFsDismountForceDismount
       
  1055 //
       
  1056 	{
       
  1057 	const RMessage2& m=aRequest->Message();
       
  1058 	const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
       
  1059 
       
  1060 	switch(mode)
       
  1061 		{
       
  1062 		case EFsDismountForceDismount:
       
  1063 		case EFsDismountNotifyClients:
       
  1064 			{
       
  1065 			// Capabilities are required to dismount a file system
       
  1066 			if(!KCapFsDismountFileSystem.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Notify Dismount")))
       
  1067 				return KErrPermissionDenied;
       
  1068 			break;
       
  1069 			}
       
  1070 
       
  1071 		case EFsDismountRegisterClient:
       
  1072 			{
       
  1073 			// No capabilities are required for a client to register for notification
       
  1074 			break;
       
  1075 			}
       
  1076 
       
  1077 		default:
       
  1078 			{
       
  1079 			return KErrArgument;
       
  1080 			//break;
       
  1081 			}
       
  1082 		}
       
  1083 
       
  1084 	return ValidateDrive(aRequest->Message().Int0() ,aRequest);
       
  1085 	}	
       
  1086 
       
  1087 TInt TFsNotifyDismount::DoRequestL(CFsRequest* aRequest)
       
  1088 //
       
  1089 // Register for notification of pending dismount [EFsDismountRegisterClient]
       
  1090 // or notify clients of a pending dismount		 [EFsDismountNotifyClients]
       
  1091 // or forcibly dismount the file system			 [EFsDismountForceDismount]
       
  1092 //
       
  1093 	{
       
  1094 	__ASSERT_DEBUG(&aRequest->Drive()->FSys() && !aRequest->Drive()->IsSubsted(), Fault(ENotifyDismount));
       
  1095 
       
  1096 	TInt err = KErrNone;
       
  1097 
       
  1098 	const RMessage2& m=aRequest->Message();
       
  1099 	const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
       
  1100 	TDrive* theDrive = aRequest->Drive();
       
  1101 	const TInt driveNumber = theDrive->DriveNumber();
       
  1102 
       
  1103 	switch(mode)
       
  1104 		{
       
  1105 		case EFsDismountRegisterClient:
       
  1106 			{
       
  1107 			err = RegisterNotify(aRequest);
       
  1108 			break;
       
  1109 			}
       
  1110 
       
  1111 		case EFsDismountNotifyClients:
       
  1112 			{
       
  1113 			if(aRequest->Drive()->DismountLocked())
       
  1114 				{
       
  1115 				err = RegisterNotify(aRequest);
       
  1116 				if (err != KErrNone)
       
  1117 					return err;
       
  1118 				// Complete outstanding client dismount notifiers and flag the drive as pending dismount.
       
  1119 				FsNotify::HandleDismount(EFsDismountRegisterClient, driveNumber, EFalse, KErrNone);
       
  1120 				theDrive->SetDismountDeferred(ETrue);
       
  1121 				}
       
  1122 			else
       
  1123 				{
       
  1124 				// There are no interested clients, so dismount immediately - if no clamps are present
       
  1125 				err = theDrive->ClampsOnDrive();
       
  1126 
       
  1127 				// If there are no clamps or clamping is not supported, proceed with the enforced dismount
       
  1128 				// If there are clamps, wait for the clamps to be removed
       
  1129 				if (err > 0)
       
  1130 					{
       
  1131 					err = RegisterNotify(aRequest);
       
  1132 					theDrive->SetDismountDeferred(ETrue);
       
  1133 					}
       
  1134 				else if (err == 0 || err == KErrNotSupported)
       
  1135 					{
       
  1136 					// No clamps to worry about, so dismount immediately and complete the request
       
  1137 					err = DoDismountFileSystem(theDrive->GetFSys()->Name(), theDrive, EFalse, ETrue);
       
  1138 					if (err == CFsRequest::EReqActionBusy)
       
  1139 						return err;
       
  1140 					m.Complete(err);
       
  1141 					}
       
  1142 				}
       
  1143 			break;
       
  1144 			}
       
  1145 
       
  1146 		case EFsDismountForceDismount:
       
  1147 			{
       
  1148 			// Prepare for deferred dismount due to the presence of file clamps
       
  1149 			err = theDrive->ClampsOnDrive();
       
  1150 
       
  1151 			// If there are no clamps or clamping is not supported, proceed with the enforced dismount
       
  1152 			// If there are clamps, wait for the clamps to be removed
       
  1153 			if(err > 0)
       
  1154 				{
       
  1155 				err = RegisterNotify(aRequest);
       
  1156 				theDrive->SetDismountDeferred(ETrue);
       
  1157 				}
       
  1158 			else if (err == 0 || err == KErrNotSupported)
       
  1159 				{
       
  1160 				// Forced dismount - notify/remove all client notifiers and complete immediately
       
  1161 				err = theDrive->DeferredDismount();
       
  1162 				if (err == CFsRequest::EReqActionBusy)
       
  1163 					return err;
       
  1164 				m.Complete(err);
       
  1165 				}
       
  1166 			break;
       
  1167 			}
       
  1168 
       
  1169 		default:
       
  1170 			{
       
  1171 			// We shouldn't ever get here
       
  1172 			Fault(ENotifyDismount);
       
  1173 			break;
       
  1174 			}
       
  1175 		}
       
  1176 
       
  1177 	return err;
       
  1178 	}
       
  1179 
       
  1180 TInt TFsNotifyDismount::RegisterNotify(CFsRequest* aRequest)
       
  1181 //
       
  1182 // Register for notification of pending dismount [EFsDismountRegisterClient]
       
  1183 // or notify clients of a pending dismount		 [EFsDismountNotifyClients]
       
  1184 // or forcibly dismount the file system			 [EFsDismountForceDismount]
       
  1185 //
       
  1186 	{
       
  1187 	const RMessage2& m=aRequest->Message();
       
  1188 	const TNotifyDismountMode mode = (TNotifyDismountMode)m.Int1();
       
  1189 	TDrive* theDrive = aRequest->Drive();
       
  1190 	const TInt driveNumber = theDrive->DriveNumber();
       
  1191 
       
  1192 	if (mode == EFsDismountNotifyClients && theDrive->DismountDeferred())
       
  1193 		{
       
  1194 		return KErrInUse;
       
  1195 		}
       
  1196 
       
  1197 	CDismountNotifyInfo* info = new CDismountNotifyInfo;
       
  1198 	if(info == NULL)
       
  1199 		{
       
  1200 		return KErrNoMemory;
       
  1201 		}
       
  1202 
       
  1203 	info->Initialise(mode, driveNumber, (TRequestStatus*)m.Ptr2(), m, aRequest->Session());
       
  1204 	TInt err = FsNotify::AddDismountNotify(info);
       
  1205 	if(err != KErrNone)
       
  1206 		{
       
  1207 		delete info;
       
  1208 		return err;
       
  1209 		}
       
  1210 
       
  1211 	return KErrNone;
       
  1212 	}
       
  1213 
       
  1214 TInt TFsNotifyDismountCancel::DoRequestL(CFsRequest* aRequest)
       
  1215 //
       
  1216 // Cancel a pending dismount notifier - Request
       
  1217 //
       
  1218 	{
       
  1219 	CSessionFs* session = aRequest->Session();
       
  1220 	FsNotify::CancelDismountNotifySession(session, (TRequestStatus*)aRequest->Message().Ptr0());
       
  1221 	return KErrNone;
       
  1222 	}
       
  1223 
       
  1224 TInt TFsNotifyDismountCancel::Initialise(CFsRequest* /*aRequest*/)
       
  1225 //
       
  1226 //	Cancel a pending dismount notifier - Initialise
       
  1227 //
       
  1228 	{
       
  1229 	return KErrNone;
       
  1230 	}	
       
  1231 
       
  1232 TInt TFsAllowDismount::DoRequestL(CFsRequest* aRequest)
       
  1233 //
       
  1234 // Notifies the file server that the client is finished with the drive.
       
  1235 // The last client to allow the dismount signals the dismounting thread.
       
  1236 //
       
  1237 	{
       
  1238 	TDrive* theDrive = aRequest->Drive();
       
  1239 	const TInt driveNumber = theDrive->DriveNumber();
       
  1240 
       
  1241 	// Verify that the client has registered for notification
       
  1242 	if(!FsNotify::HandlePendingDismount(aRequest->Session(), driveNumber))
       
  1243 		return KErrNotFound;
       
  1244 
       
  1245 	if(theDrive->DismountLocked())
       
  1246 		return KErrNone;
       
  1247 
       
  1248 	TInt clampErr = theDrive->ClampsOnDrive();
       
  1249 	TInt err = KErrNone;
       
  1250 
       
  1251 	if ((theDrive->DismountDeferred()) && (clampErr == 0 || clampErr == KErrNotSupported))
       
  1252 		{
       
  1253 		// No clamps to worry about, so dismount immediately and complete the request
       
  1254 		__ASSERT_DEBUG(aRequest->Drive()->GetFSys(), Fault(EAllowDismount));
       
  1255 
       
  1256 		// When the last client has responded, allow the media to be forcibly dismounted
       
  1257 		err = theDrive->DeferredDismount();
       
  1258 		}
       
  1259 
       
  1260 	return err;
       
  1261 	}
       
  1262 
       
  1263 TInt TFsAllowDismount::Initialise(CFsRequest* aRequest)
       
  1264 //
       
  1265 // Notifies the file server that the client is finished with the drive
       
  1266 //
       
  1267 	{
       
  1268 	return ValidateDrive(aRequest->Message().Int0(),aRequest);
       
  1269 	}	
       
  1270 
       
  1271 
       
  1272 TInt TFsMountProxyDrive::DoRequestL(CFsRequest* aRequest)
       
  1273 	{
       
  1274 	return LocalDrives::MountProxyDrive(aRequest);
       
  1275 	}
       
  1276 
       
  1277 TInt TFsMountProxyDrive::Initialise(CFsRequest* aRequest)
       
  1278 	{
       
  1279 	if (!KCapFsMountProxyDrive.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Mount Proxy Drive")))
       
  1280 		return KErrPermissionDenied;
       
  1281 
       
  1282     TInt err = LocalDrives::InitProxyDrive(aRequest);
       
  1283 	if(err == KErrNone)
       
  1284 	    {
       
  1285     	// Now create the drive thread - proxy extensions are always asynchronous...
       
  1286 		err = FsThreadManager::InitDrive(aRequest->DriveNumber(), EFalse);
       
  1287         }
       
  1288 
       
  1289 	return err;
       
  1290 	}
       
  1291 
       
  1292 TInt TFsLoadCodePage::DoRequestL(CFsRequest* aRequest)
       
  1293 //
       
  1294 // Installs a code page
       
  1295 //
       
  1296 	{
       
  1297 	__PRINT(_L("TFsLoadCodePage::DoRequestL(CFsRequest* aRequest)"));
       
  1298 
       
  1299 	RLibrary lib;
       
  1300 	lib.SetHandle(aRequest->Message().Int0());
       
  1301 	if (lib.Type()[1]!=TUid::Uid(KLocaleDllUidValue16))
       
  1302 		return(KErrNotSupported);
       
  1303 
       
  1304 	if(TheCodePage.CodepageLoaded() == TCodePageUtils::ECodePageDll)
       
  1305 		{
       
  1306 		return(KErrAlreadyExists);
       
  1307 		}
       
  1308 
       
  1309 	/*
       
  1310 	// Actual Functions form the Codepage Dll (fatCnvU.def)
       
  1311 	1	:	void UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &)
       
  1312 	2	:	void UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &)
       
  1313 	3	:	int UnicodeConv::IsLegalShortNameCharacter(unsigned int)
       
  1314 	4	:	int UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &, int)
       
  1315 	5	:	int UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &, int)
       
  1316 	*/
       
  1317 
       
  1318 	/*
       
  1319 	Read only the following fns from Codepage Dll ( lib.Lookup(1) and lib.Lookup(2) retained in cpnnn.dll for backward compatibility)
       
  1320 	3	:	int UnicodeConv::IsLegalShortNameCharacter(unsigned int)
       
  1321 	4	:	int UnicodeConv::ConvertFromUnicodeL(class TDes8 &, class TDesC16 const &, int)
       
  1322 	5	:	int UnicodeConv::ConvertToUnicodeL(class TDes16 &, class TDesC8 const &, int)
       
  1323 	*/
       
  1324 
       
  1325 	TheCodePage.iCodePageFunctions.iIsLegalShortNameCharacter = (TCodePageFunctions::TIsLegalShortNameCharacter)(lib.Lookup(3));
       
  1326 	TheCodePage.iCodePageFunctions.iConvertFromUnicodeL = (TCodePageFunctions::TConvertFromUnicodeL)(lib.Lookup(4));
       
  1327 	TheCodePage.iCodePageFunctions.iConvertToUnicodeL = (TCodePageFunctions::TConvertToUnicodeL)(lib.Lookup(5));
       
  1328 
       
  1329 	if( TheCodePage.iCodePageFunctions.iIsLegalShortNameCharacter == NULL || 
       
  1330 		TheCodePage.iCodePageFunctions.iConvertFromUnicodeL == NULL ||
       
  1331 		TheCodePage.iCodePageFunctions.iConvertToUnicodeL == NULL )
       
  1332 		{
       
  1333 		return(KErrCorrupt);
       
  1334 		}
       
  1335 	TheCodePage.iCodepageLoaded = TCodePageUtils::ECodePageDll;
       
  1336 
       
  1337 	return(KErrNone);
       
  1338 	}
       
  1339 
       
  1340 TInt TFsLoadCodePage::Initialise(CFsRequest* aRequest)
       
  1341 //
       
  1342 // Installs a code page
       
  1343 //
       
  1344 	{
       
  1345 	__PRINT(_L("TFsLoadCodePage::Initialise(CFsRequest* aRequest)"));
       
  1346 	
       
  1347 	// Set the drive
       
  1348 	TInt drive = aRequest->Session()->CurrentDrive();
       
  1349 	aRequest->SetDrive(&TheDrives[drive]);
       
  1350 
       
  1351 	TSecurityPolicy policy(RProcess().SecureId(), ECapabilityDiskAdmin);
       
  1352 	if (!policy.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("TFsLoadCodePage::Initialise")))
       
  1353 		{
       
  1354 		return KErrPermissionDenied;
       
  1355 		}
       
  1356 	
       
  1357 	return KErrNone;
       
  1358 	}
       
  1359 
       
  1360 // use second half of ISO Latin 1 character set for extended chars
       
  1361 const TUint KExtendedCharStart=0x80;
       
  1362 const TUint KExtendedCharEnd=0xff;
       
  1363 
       
  1364 _LIT8(KLit8ReplacementForUnconvertibleUnicodeCharacters, "_");
       
  1365 
       
  1366 TCodePageUtils::TCodePageUtils()
       
  1367 //
       
  1368 // Constructor
       
  1369 //
       
  1370   :	iCodePageFunctions(),
       
  1371 	iLocaleFatUtilityFunctions(NULL),
       
  1372 	iCodepageLoaded(ENone)
       
  1373 	{
       
  1374 	}
       
  1375 
       
  1376 TBool TCodePageUtils::IsCodepageLoaded() const
       
  1377 //
       
  1378 // Returns ETrue if a codepage is loaded
       
  1379 //
       
  1380 	{
       
  1381 	return(iCodepageLoaded != ENone);
       
  1382 	}
       
  1383 
       
  1384 TCodePageUtils::TCodepageLoaded TCodePageUtils::CodepageLoaded() const
       
  1385 //
       
  1386 // Returns the type of active codepage
       
  1387 //
       
  1388 	{
       
  1389 	return(iCodepageLoaded);
       
  1390 	}
       
  1391 
       
  1392 void TCodePageUtils::SetLocaleCodePage(TFatUtilityFunctions* aFunctions)
       
  1393 //
       
  1394 // Sets the current codepage to that provided by the current Locale DLL
       
  1395 //
       
  1396 	{
       
  1397 	if(iCodepageLoaded == ENone && aFunctions)
       
  1398 		{
       
  1399 		iLocaleFatUtilityFunctions = aFunctions;
       
  1400 		iCodepageLoaded = ELocaleDll;
       
  1401 		}
       
  1402 	}
       
  1403 
       
  1404 TFatUtilityFunctions* TCodePageUtils::LocaleFatUtilityFunctions() const
       
  1405 //
       
  1406 // Returns function pointer to the read Locale conversions functions
       
  1407 //
       
  1408 	{
       
  1409 	return(iLocaleFatUtilityFunctions);
       
  1410 	}
       
  1411 
       
  1412 TCodePageFunctions TCodePageUtils::CodepageFatUtilityFunctions() const
       
  1413 //
       
  1414 // Returns structure to function pointers to the read Codepage conversions functions
       
  1415 //
       
  1416 	{
       
  1417 	return(iCodePageFunctions);
       
  1418 	}
       
  1419 
       
  1420 TBool TCodePageUtils::ConvertFromUnicode(TDes8& aForeign, const TDesC16& aUnicode, TOverflowAction aOverflowAction) const
       
  1421 /**
       
  1422 Convert from Unicode, truncating if there is not enough room in the output.
       
  1423 
       
  1424 @param aForeign The output is appended here.
       
  1425 @param aUnicode The input.
       
  1426 
       
  1427 @return False if and only if aForeign has not enough space remaining. 
       
  1428 */
       
  1429 	{
       
  1430 	TBool allConverted = ETrue;
       
  1431 	const TInt maximumLength=aForeign.MaxLength();
       
  1432 	TInt lengthToCopy=aUnicode.Length();
       
  1433 	// do not cross the maximum foreign length
       
  1434 	if (maximumLength<lengthToCopy)
       
  1435 		{
       
  1436 		if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
       
  1437 			{
       
  1438 			allConverted = EFalse;
       
  1439 			return allConverted;
       
  1440 			}
       
  1441 		lengthToCopy=maximumLength;
       
  1442 		}
       
  1443 
       
  1444 	aForeign.SetLength(lengthToCopy);
       
  1445 
       
  1446 	TInt j=0; // offset for aForeign[]
       
  1447 	TInt i=0; // offset for aUnicode[]
       
  1448 	for (i=0; i<lengthToCopy; ++i)
       
  1449 		{
       
  1450 		const TDesC8& replacementChar = KLit8ReplacementForUnconvertibleUnicodeCharacters;
       
  1451 		TUint32 unicodeChar = aUnicode[i];
       
  1452 
       
  1453 		// if High Surrogate
       
  1454 		if (IsHighSurrogate((TText16)unicodeChar))
       
  1455 			{
       
  1456 			// check for low surrogate
       
  1457 			if (!IsLowSurrogate(aUnicode[++i]))
       
  1458 				{
       
  1459 				aForeign[j++] = (TUint8)replacementChar[0];
       
  1460 				continue;
       
  1461 				}
       
  1462 			unicodeChar = JoinSurrogate((TText16)unicodeChar, (TText16)aUnicode[i]);
       
  1463 			}
       
  1464 
       
  1465 		// if Low Surrogate
       
  1466 		if (IsLowSurrogate((TText16)unicodeChar))
       
  1467 			{
       
  1468 			aForeign[j++] = (TUint8)replacementChar[0];
       
  1469 			continue;
       
  1470 			}
       
  1471 		// if Supplementary - Non BMP
       
  1472 		if (IsSupplementary(unicodeChar))
       
  1473 			{
       
  1474 			aForeign[j++] = (TUint8)replacementChar[0];
       
  1475 			}
       
  1476 		else
       
  1477 			{
       
  1478 			// ASCII support
       
  1479 			if((TUint)unicodeChar>=0x100)
       
  1480 				{
       
  1481 				aForeign[j++] = (TUint8)replacementChar[0];
       
  1482 				}
       
  1483 			else
       
  1484 				{
       
  1485 				aForeign[j++] = (TUint8)unicodeChar;
       
  1486 				}
       
  1487 			}
       
  1488 		}
       
  1489 
       
  1490 	// if any replacementChar used, aForeign offset(j) shall be less than 
       
  1491 	// lengthToCopy aUnicode offset(i)
       
  1492 	if(j<i)
       
  1493 		{
       
  1494 		aForeign.SetLength(j);
       
  1495 		}
       
  1496 
       
  1497 	return(allConverted);
       
  1498 	}
       
  1499 
       
  1500 EXPORT_C void TCodePageUtils::ConvertFromUnicodeL(TDes8& aForeign, const TDesC16& aUnicode, TOverflowAction aOverflowAction) const
       
  1501 /**
       
  1502 Convert from Unicode, truncating if there is not enough room in the output.
       
  1503 
       
  1504 @param aForeign The output is appended here.
       
  1505 @param aUnicode The input.
       
  1506 
       
  1507 @leave KErrOverflow if aForeign is too short for the output.
       
  1508 */
       
  1509 	{
       
  1510 	TInt r = KErrNone;
       
  1511 	TBool LeaveWhenError = (TBool)((aOverflowAction==TCodePageUtils::EOverflowActionLeave)?(TBool)ETrue:(TBool)EFalse);
       
  1512 	// if CodePage dll
       
  1513 	if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iConvertFromUnicodeL)
       
  1514 		{
       
  1515 		r = (*iCodePageFunctions.iConvertFromUnicodeL)(aForeign, aUnicode, LeaveWhenError);
       
  1516 		}
       
  1517 	// if Locale dll
       
  1518 	else if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iConvertFromUnicodeL)
       
  1519 		{
       
  1520 		if(aOverflowAction == TCodePageUtils::EOverflowActionLeave)
       
  1521 			{
       
  1522 			(*iLocaleFatUtilityFunctions->iConvertFromUnicodeL)(aForeign, aUnicode, KLit8ReplacementForUnconvertibleUnicodeCharacters, TFatUtilityFunctions::EOverflowActionLeave);
       
  1523 			}
       
  1524 		else
       
  1525 			{
       
  1526 			(*iLocaleFatUtilityFunctions->iConvertFromUnicodeL)(aForeign, aUnicode, KLit8ReplacementForUnconvertibleUnicodeCharacters, TFatUtilityFunctions::EOverflowActionTruncate);
       
  1527 			}
       
  1528 		}
       
  1529 	// default implementation
       
  1530 	else if (!ConvertFromUnicode(aForeign, aUnicode, aOverflowAction))
       
  1531 		{
       
  1532 		if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
       
  1533 			{
       
  1534 			User::Leave(KErrBadName);
       
  1535 			}
       
  1536 		}
       
  1537 
       
  1538 	r = r; // remove warning
       
  1539 	// File Server do not use this error code so do not send this error code right to File Server
       
  1540 	// rather suppress it. Can be used in future.
       
  1541 	return;
       
  1542 	}
       
  1543 
       
  1544 TBool TCodePageUtils::ConvertToUnicode(TDes16& aUnicode, const TDesC8& aForeign) const
       
  1545 /* 
       
  1546 Convert to Unicode, truncating if there is not enough room in the output.
       
  1547 
       
  1548 @param aUnicode The output is appended here.
       
  1549 @param aForeign The input.
       
  1550 
       
  1551 @return False if and only if aUnicode has not enough space remaining.
       
  1552 */
       
  1553 	{
       
  1554 	// A workaround to handle leading 'E5' byte in short file names 
       
  1555 	TBuf8<KMaxLengthShortNameWithDot> shortFileNameWithLeadingE5;
       
  1556 	TBool convertedLeading05toE5 = EFalse;
       
  1557 
       
  1558 	if (0 < aForeign.Length() && aForeign.Length() <= 12 && aForeign[0] == KLeadingE5Replacement)
       
  1559 		{
       
  1560 		shortFileNameWithLeadingE5 = aForeign;
       
  1561 		shortFileNameWithLeadingE5[0] = KEntryErasedMarker;
       
  1562 		convertedLeading05toE5 = ETrue;
       
  1563 		}
       
  1564 
       
  1565 	const TInt maximumLength=aUnicode.MaxLength();
       
  1566 	if (maximumLength>=aForeign.Length())
       
  1567 		{
       
  1568 		if (convertedLeading05toE5)
       
  1569 			{
       
  1570 			aUnicode.Copy(shortFileNameWithLeadingE5);
       
  1571 			}
       
  1572 		else
       
  1573 			{
       
  1574 			aUnicode.Copy(aForeign);
       
  1575 			}
       
  1576 		return ETrue;
       
  1577 		}
       
  1578 	else
       
  1579 		{
       
  1580 		if (convertedLeading05toE5)
       
  1581 			{
       
  1582 			aUnicode.Copy(shortFileNameWithLeadingE5.Left(maximumLength));
       
  1583 			}
       
  1584 		else
       
  1585 			{
       
  1586 			aUnicode.Copy(aForeign.Left(maximumLength));
       
  1587 			}
       
  1588 		return EFalse;
       
  1589 		}
       
  1590 	}
       
  1591 
       
  1592 EXPORT_C void TCodePageUtils::ConvertToUnicodeL(TDes16& aUnicode, const TDesC8& aForeign, TOverflowAction aOverflowAction) const
       
  1593 /* 
       
  1594 Convert to Unicode, leaving if there is not enough room in the output.
       
  1595 
       
  1596 @param aUnicode The output is appended here.
       
  1597 @param aForeign The input.
       
  1598 
       
  1599 @leave KErrOverflow if aUnicode is too short for the output.
       
  1600 */
       
  1601 	{
       
  1602 	TInt r = KErrNone;
       
  1603 	TBool LeaveWhenError = (TBool)((aOverflowAction==TCodePageUtils::EOverflowActionLeave)?(TBool)ETrue:(TBool)EFalse);
       
  1604 	// if CodePage dll
       
  1605 	if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iConvertToUnicodeL)
       
  1606 		{
       
  1607 		r = (*iCodePageFunctions.iConvertToUnicodeL)(aUnicode, aForeign, LeaveWhenError);
       
  1608 		}
       
  1609 	// if Locale dll
       
  1610 	else if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iConvertToUnicodeL)
       
  1611 		{
       
  1612 		if(aOverflowAction == TCodePageUtils::EOverflowActionLeave)
       
  1613 			{
       
  1614 			(*iLocaleFatUtilityFunctions->iConvertToUnicodeL)(aUnicode, aForeign, TFatUtilityFunctions::EOverflowActionLeave);
       
  1615 			}
       
  1616 		else
       
  1617 			{
       
  1618 			(*iLocaleFatUtilityFunctions->iConvertToUnicodeL)(aUnicode, aForeign, TFatUtilityFunctions::EOverflowActionTruncate);
       
  1619 			}
       
  1620 		}
       
  1621 	// default implementation
       
  1622 	else if (!ConvertToUnicode(aUnicode, aForeign))
       
  1623 		{
       
  1624 		if (aOverflowAction==TCodePageUtils::EOverflowActionLeave)
       
  1625 			{
       
  1626 			User::Leave(KErrBadName);
       
  1627 			}
       
  1628 		}
       
  1629 
       
  1630 	r = r; // remove warning
       
  1631 	// File Server do not use this error code so do not send this error code right to File Server
       
  1632 	// rather suppress it. Can be used in future.
       
  1633 	return;
       
  1634 	}
       
  1635 
       
  1636 EXPORT_C TBool TCodePageUtils::IsLegalShortNameCharacter(TUint aCharacter,TBool aUseExtendedChars) const
       
  1637 /** 
       
  1638 Returns true if the input character is legal in a short name.
       
  1639 
       
  1640 @param aCharacter Character, in the foreign character encoding.
       
  1641 
       
  1642 @return true if aCharacter is legal in a FAT short name.
       
  1643 */
       
  1644 	{
       
  1645 	if(GetFatUtilityFunctions() && iCodepageLoaded == ECodePageDll && iCodePageFunctions.iIsLegalShortNameCharacter)
       
  1646 		{
       
  1647 		return (*iCodePageFunctions.iIsLegalShortNameCharacter)(aCharacter);
       
  1648 		}
       
  1649 
       
  1650 	if(GetFatUtilityFunctions() && iCodepageLoaded == ELocaleDll && iLocaleFatUtilityFunctions->iIsLegalShortNameCharacter)
       
  1651 		{
       
  1652 		return (*iLocaleFatUtilityFunctions->iIsLegalShortNameCharacter)(aCharacter);
       
  1653 		}
       
  1654 
       
  1655 	// For most common cases:
       
  1656 	// Note: lower case characters are considered legal DOS char here.
       
  1657 	if ((aCharacter>='a' && aCharacter<='z') ||
       
  1658 		(aCharacter>='A' && aCharacter<='Z') ||
       
  1659 		(aCharacter>='0' && aCharacter<='9'))
       
  1660 		{
       
  1661 		return ETrue;
       
  1662 		}
       
  1663 
       
  1664 	// Default Implmentation
       
  1665 	// Checking for illegal chars:
       
  1666 	// 1. aCharacter <= 0x20
       
  1667 	// Note: leading 0x05 byte should be guarded by callers of this function
       
  1668 	//  as the information of the position of the character is required.
       
  1669 	if (aCharacter < 0x20)
       
  1670 		return EFalse;
       
  1671 	// Space (' ') is not considered as a legal DOS char here.
       
  1672 	if (aCharacter == 0x20)
       
  1673 		return EFalse;
       
  1674 
       
  1675 	// 2. 0x20 < aCharacter < 0x80
       
  1676 	if (0x20 < aCharacter && aCharacter < KExtendedCharStart)
       
  1677 		{
       
  1678 		// According to FAT Spec, "following characters are not legal in any bytes of DIR_Name":
       
  1679 		switch (aCharacter)
       
  1680 			{
       
  1681 			case 0x22:	// '"'
       
  1682 			case 0x2A:	// '*'
       
  1683 			case 0x2B:	// '+'
       
  1684 			case 0x2C:	// ','
       
  1685 	//		case 0x2E:	// '.'		// Although '.' is not allowed in any bytes of DIR_Name, it 
       
  1686 									// is a valid character in short file names.
       
  1687 			case 0x2F:	// '/'
       
  1688 			case 0x3A:	// ':'
       
  1689 			case 0x3B:	// ';'
       
  1690 			case 0x3C:	// '<'
       
  1691 			case 0x3D:	// '='
       
  1692 			case 0x3E:	// '>'
       
  1693 			case 0x3F:	// '?'
       
  1694 			case 0x5B:	// '['
       
  1695 			case 0x5C:	// '\'
       
  1696 			case 0x5D:	// ']'
       
  1697 			case 0x7C:	// '|'
       
  1698 				return EFalse;
       
  1699 			default:
       
  1700 			    return ETrue;
       
  1701 			}
       
  1702 		}
       
  1703 
       
  1704 	// 3. 0x80 <= aCharacter <= 0xFF
       
  1705 	if (KExtendedCharStart <= aCharacter  && aCharacter <= KExtendedCharEnd)
       
  1706 		{
       
  1707 		if(aUseExtendedChars)
       
  1708 			return(ETrue);
       
  1709 		else
       
  1710 			return EFalse;
       
  1711 		}
       
  1712 
       
  1713 	// 4. aCharacter => 0xFF
       
  1714 	return EFalse;
       
  1715 	}