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