Exemple #1
0
TInt TFsFormatNext::DoRequestL(CFsRequest* aRequest)
//
// Format the next part of the media.
//
	{

	__PRINT1(_L("TFsFormatNext::DoRequestL() drv:%d"), aRequest->DriveNumber());
	CFormatCB* format=(CFormatCB*)aRequest->ScratchValue();
	TInt r=format->CheckMount();
	if (r!=KErrNone && r!=KErrInUse)
        {
    	__PRINT1(_L("TFsFormatNext::DoRequestL() err:%d"), r);
        return r;
        }

	TPtr8 pStep((TUint8*)&format->CurrentStep(),sizeof(TInt));
	aRequest->ReadL(KMsgPtr0,pStep);

	OstTrace1(TRACE_FILESYSTEM, FSYS_ECFORMATCBDOFORMATSTEPL, "this %x", format);

	TRAP(r,format->DoFormatStepL());

	OstTraceExt2(TRACE_FILESYSTEM, FSYS_ECFORMATCBDOFORMATSTEPLRET, "r %d  iCurrentStep %d", r, (TUint) format->CurrentStep());

	if (r==KErrNone)
		aRequest->WriteL(KMsgPtr0,pStep);
	if (r==KErrNone && format->CurrentStep()==0)
		{
		FsNotify::DiskChange(aRequest->DriveNumber());
		}
	return(r);
	}
Exemple #2
0
static void DumpOpenedObjects(TDrive& aDrive)
    {
        {//-- 1. files 
        const TInt nFiles = Files->Count();
        for(TInt i=0; i<nFiles; ++i)
            {
            CFileCB* pFile=(CFileCB*)(*Files)[i];
            if(pFile->Drive().DriveNumber() == aDrive.DriveNumber())
                {
                __PRINT1(_L("FsFormatOpen() opened file:'%S'"), &pFile->FileName());
                }
            }
        
        }

        {//-- 2. directories; CDirCB doesn't have associated name.
        const TInt nDirs = Dirs->Count();
        TInt cntDirs = 0;
        for(TInt i=0; i<nDirs; ++i)
            {
            CDirCB* pDir = (CDirCB*)(*Dirs)[i];
            if(pDir->Drive().DriveNumber() == aDrive.DriveNumber())
                {
                ++cntDirs;
                }
            }
            
        if(cntDirs)
            {
            __PRINT1(_L("FsFormatOpen() opened directories:%d"), cntDirs);
            }

        }

    }
/**
Publishing method

Sends a property event on behalf of CMassStorageDrive, with the mountstate and drivestate
values encoded into one 32-bit word.
*/
void RDriveStateChangedPublisher::DriveStateChanged()
	{
	__MSFNLOG
	TUsbMsDrivesStatus allDrivesStatus;

	for(TUint8 i = 0; i < iDrives.Count(); i++)
		{
		allDrivesStatus.Append(iDriveMap[i]);

		CMassStorageDrive::TMountState ms = iDrives[i]->MountState();
		TLocalDriveRef::TDriveState ds = iDrives[i]->DriveState();
		TInt driveStatus = EUsbMsDriveState_Error;
		if((TUint8)ds < sizeof(table[0]) && (TUint8)ms < sizeof(table)/sizeof(table[0]))
			{
			driveStatus = table[ms][ds];
			__PRINT3(_L("ms=%d ds=%d %d"), ms, ds, driveStatus);
			}
		allDrivesStatus.Append(driveStatus);
		}


	__PRINT1(_L("Publishing EUsbMsDriveState_DriveStatus for %d drives\n"),
				allDrivesStatus.Length()/2);

	if(KErrNone != RProperty::Set(KUsbMsDriveState_Category,
								  EUsbMsDriveState_DriveStatus,
								  allDrivesStatus))
		{
		__ASSERT_DEBUG(EFalse,User::Invariant());
		}
	}
Exemple #4
0
CFsObjectIx::~CFsObjectIx()
//
// Destructor
// Assumes that no need to lock
//
	{
	__PRINT1(_L("CFsObjectIx::~CFsObjectIx() 0x%x"),this);
    
	// We have to be very careful here. Calling Close() on the objects in the array
	// may result in other entries being removed from the array before we delete
	// them here, and may result in the array being ReAlloc()ed, corrupting the removed
	// entries, hence we must check the iHighWaterMark value each time round the loop.
	TInt i=-1;
	while(++i<iHighWaterMark)
		{
		SFsObjectIxRec* pS=iObjects+i;
		CFsObject *pO=pS->obj;
		if (pO)
			{
			// invalidate entry before closing it
			pS->obj=NULL;
			pO->Close();	
			}
		}
	delete iObjects;
	iLock.Close();
	}
TInt CMediaWTCache::Control(TUint32 aFunction, TUint32 aParam1, TAny* /*aParam2*/)
    {
    TInt nRes = KErrNotSupported;

#ifdef _DEBUG
    switch(aFunction)
        {
        //-- disable / enable cache, for debug
        //-- if aParam1 !=0 cache will be disabled, enabled otherwise
        case EDisableCache: 
            iCacheDisabled = aParam1 ? 1 : 0;
            nRes = KErrNone;
        break;

        case EDumpCache:
        break;
           
        case ECacheInfo:
        break;
   
        default:
            __PRINT1(_L("CMediaWTCache::Control() invalid function: %d"), aFunction);
            ASSERT(0);
        break;
        }
#else
    (void)aFunction; //-- supress warnings
    (void)aParam1;
    User::Invariant(); //-- don't call this method in release build
#endif //_DEBUG   
    
    return nRes;
    }
Exemple #6
0
/**
Destructor.
 
Deallocates memory associated with this objects name, if a name 
has been set.
 
@panic FSERV 104 if the reference count is not zero when
       the destructor is called.
*/
EXPORT_C  CFsObject::~CFsObject()
	{
	__PRINT1(_L("CFsObject::~CFsObject() 0x%x"),this);
	__ASSERT_ALWAYS(Dec()==0,Fault(EObjDestructorAccessCount));	
	__ASSERT_ALWAYS(!iContainer,Fault(EObjDestructorContainer));
	if(iName)
		User::Free(iName);
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
	__e32_atomic_add_ord32(&ObjectCount, (TUint32) -1);
#endif
	}
/**
Unlock a locked page.
@return TInt    KErrNone if unlocking was successful, otherwise system-wide error code.
@param  aPage   the pointer of the page to be unlocked.
*/
TInt CDynamicDirCache::UnlockPage(TDynamicDirCachePage* aPage)
    {
    ASSERT(aPage != NULL);
    __PRINT1(_L("CDynamicDirCache::UnlockPage(%lx)"), aPage->StartPos());
    TInt r = iCacheMemoryClient->UnlockSegments(aPage->StartPtr(), PageSizeInSegs());
    if (r == KErrNone)
        {
        aPage->SetLocked(EFalse);
        }
    return r;
    }
/**
Destructor of CLeafDirTree
*/
CLeafDirTree::~CLeafDirTree()
	{
	__PRINT1(_L("~CLeafDirTree[0x%x]"), this);

	Reset();
	delete iRoot;
	iLruList.Close();

#ifdef _DEBUG
	iContainer.Close();
#endif //_DEBUG
	}
/**
Implementation of pure virtual function.
@see    MWTCacheInterface::Control()
*/
TInt CDynamicDirCache::Control(TUint32 aFunction, TUint32 aParam1, TAny* aParam2)
    {
    TInt r = KErrNotSupported;
#ifdef _DEBUG
    (void)aParam2;
    switch(aFunction)
        {
        // disable / enable cache, for debug
        // if aParam1 != 0 cache will be disabled, enabled otherwise
        case EDisableCache:
            iCacheDisabled = aParam1 ? 1 : 0;
            r = KErrNone;
        break;

        // dump cache, for debug
        case EDumpCache:
            {
            RFs fs;
            fs.Connect();
            const TUint32 debugRegister = DebugRegister();
            fs.SetDebugRegister(debugRegister|KFSYS);
            Dump();
            fs.SetDebugRegister(debugRegister);
            fs.Close();
            break;
            }
        case ECacheInfo:
            {
            RFs fs;
            fs.Connect();
            const TUint32 debugRegister = DebugRegister();
            fs.SetDebugRegister(debugRegister|KFSYS);
            Info();
            fs.SetDebugRegister(debugRegister);
            fs.Close();
            break;
            }

        default:
            __PRINT1(_L("CDynamicDirCache::Control() invalid function: %d"), aFunction);
            ASSERT(0);
        break;
        }

#else
    (void)aFunction; //-- supress warnings
    (void)aParam1;
    (void)aParam2;
    User::Invariant(); //-- don't call this method in release build
#endif //_DEBUG

    return r;
    }
/**
Set the Drive State to Active or Idle.
Ref: 3.6.3.2 - PREVENT_MEDIUM_REMOVAL
@return KErrNone on success, otherwise system wide error code
@param aLun The Logical Drive Unit identifier (0..numDrives-1)
@param aCritical ETrue for Active, EFalse for Idle
*/
TInt CDriveManager::SetCritical(TUint aLun, TBool aCritical)
	{
	__PRINT1(_L("CDriveManager::SetCritical lun=%d\n"), aLun);
	
	TInt err = KErrUnknown; // never return this
	CMassStorageDrive* drive = Drive(aLun, err);
	if(drive)
		{
		err = drive->SetCritical(aCritical);
		}
		
	return err;
	}
/**
Publishing method

Publishes the Media Error property event

@param aError ETrue if drive media has an error else EFalse for no error
*/
void RDriveMediaErrorPublisher::PublishErrorL(TBool aError)
	{
    __MSFNLOG
	__PRINT1(_L("<< RDriveMediaErrorPublisher::PublishError %x"), aError);

	TInt oldValue;
	iMediaErrorProperty.Get(oldValue);

	if (oldValue != aError)
		{
		User::LeaveIfError(iMediaErrorProperty.Set(aError));
		}
	}
/**
@return KErrNone on success, KErrArgument if arguments are illegal
@param aNewState
@param aLocalDrive Only provide this if aNewState is EConnected, in which case it is required.
Only sets/clears iLocalDrive if new state is Connected or Disconnected.
*/
TInt CMassStorageDrive::SetMountState(TMountState aNewState, CLocalDriveRef* aLocalDrive/*=NULL*/)
	{
	__FNLOG("CMassStorageDrive::SetMountState");
	TInt err = KErrUnknown; //Never return this
	
	if(iMountState != aNewState)
		{

		if 	(iMountState == EConnected 		&& aNewState==EConnecting ||
			iMountState == EDisconnected 	&& aNewState==EDisconnecting)
			{
			return KErrNone;
			}
		
		iMountState = aNewState;
		if(aNewState==EDisconnected || aNewState==EConnecting)
			{
			// Reset the drive state on disconnection.
			// Note: This should be called before ProxyDrive is NULLed.
			SetDriveState(EErrDisMounted);
			}

		// Only mounting and unmounting transitions affect iProxyDrive
		if(aNewState==EConnected || aNewState==EDisconnected)
			{
			delete iLocalDrive;
			iLocalDrive = aLocalDrive;  // possibly NULL
			}

#ifndef USB_TRANSFER_PUBLISHER
		// The data transferred counts are "since the host connected to the drive"
		// so reset them when going to the connected state.
		if(aNewState==EConnected)
			{			
			iBytesWritten = iBytesRead = 0;
			}
#endif			
		
		__PRINT1(_L("SetMountState: state=%d\n"), iMountState);

		err = KErrNone;
		}
	else if(aLocalDrive != iLocalDrive)
		{
		// Caller is not allowed to change the proxy drive
		err = KErrArgument;
		}
		
	return err;
	}
/**
Internal query function, to check if aPos is cached or not. iActive page is included in searching.
*/
TDynamicDirCachePage* CDynamicDirCache::FindPageByPos(TInt64 aPos)
    {
    __PRINT1(_L("CDynamicDirCache::FindPageByPos(aPos=%lx)"), aPos);
    // align the page position
    TInt64 pageStartMedPos = CalcPageStartPos(aPos);

    if ((iActivePage->StartPos() == pageStartMedPos))
        {
        ASSERT(iActivePage->IsValid());
        return iActivePage;
        }

    // search in lookup table
    return LookupTblFind(pageStartMedPos);
    }
/**
Try to create a new page and lock the page content when it is created. This function should only be called
when creating iActive page or making a page MRU (which might result in page evictions).
@return the pointer of the newly created page, or NULL if allocation failed.
@param  aStartMedPos    the starting media address of the page to be created.
@pre    aStartMedPos should not already be existing in the cache.
*/
TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
    {
    __PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);

    TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
    if (startRamAddr)
        {
        // create new page and return
        TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
        pPage->SetLocked(ETrue);
        pPage->SetValid(EFalse);
        return pPage;
        }

    return NULL;
    }
Exemple #15
0
CFatFileCB::~CFatFileCB()
{
    __PRINT1(_L("CFatFileCB deleted 0x%x"),this);

    //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
    //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
    //-- implies valid iMount.
    const CMountCB* pMount  = &Mount();
    if(pMount)
    {   //-- do some finalisation work if CMountCB is valid
        if (iAtt&KEntryAttModified)
            TRAP_IGNORE(FlushAllL());
    }

    delete[] iSeekIndex;
}
/**
Decommit a locked or unlocked page.
@return TInt    KErrNone if decommition was successful, otherwise system-wide error code.
@param  aPage   the pointer of the page to be decommitted.
*/
TInt CDynamicDirCache::DecommitPage(TDynamicDirCachePage* aPage)
    {
    ASSERT(aPage != NULL);
    __PRINT1(_L("CDynamicDirCache::DecommitPage(%lx)"), aPage->StartPos());
    if (aPage)
        {
        TInt r = iCacheMemoryClient->DecommitSegments(aPage->StartPtr(), PageSizeInSegs());
        if (r == KErrNone)
            {
            aPage->SetLocked(EFalse);
            aPage->SetValid(EFalse);
            }
        return r;
        }
    return KErrArgument;
    }
Exemple #17
0
/**
Initialize the FAT cache and disk access

@param  aLocDrvCaps local drive capabilities
@param  aIgnoreFSInfo if ETrue, FSInfo sector shall be ignored. Used on volume remount to force FAT free clusters counting.

@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool aIgnoreFSInfo/*=EFalse*/) 
	{
    __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());

    ASSERT(State() == EMounting); //-- we must get here only from MountL()
   
    //========== Find out number of clusters on the volume
	if(iRamDrive && SectorsPerCluster()!=1)
		{// Align iFirstFreeByte to cluster boundary if internal ram drive
		const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
		const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
		const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
		iFirstFreeByte=alignedSector<<SectorSizeLog2();
		}
	else
		{
		if(Is32BitFat())
void CDevice::MountLogicalUnitsL()
    {
    __MSFNLOG
    iExt.OpenL();

    for (TInt lun = 0; lun < iNumLuns; lun++)
        {
        TDriveNumber driveNumber = iExt.GetDriveL();
        __PRINT2(_L("Mounting drive=%d lun=%d..."), driveNumber, lun);
        RDebug::Print(_L("Mounting drive=%d lun=%d..."), driveNumber, lun);
        TRAPD(err, iExt.MountL(iUsbHostMsDevice, driveNumber, iDeviceToken, lun));
        if (err == KErrNone || err == KErrNotReady || err == KErrCorrupt)
            {
            iLuList.Append(driveNumber);
            }
        __PRINT1(_L("%d"), err);
        RDebug::Print(_L("err=%d"), err);
        }
    }
Exemple #19
0
CFatFileCB::~CFatFileCB()
    {
    __PRINT1(_L("~CFatFileCB deleted 0x%x"),this);

    //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
    //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
    //-- implies valid iMount.
    const CMountCB* pMount  = &Mount();
    if(pMount)
        {//-- do some finalisation work if CMountCB is valid
        if(FileAttModified())
            {
            IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush
            TRAP_IGNORE(FlushAllL());
            }
        }

    delete[] iSeekIndex;
    }
//-------------------------------------------------------------------------------------------------------------------
void Dump_TLDFormatInfo(const TLDFormatInfo& aInfo)
{
    (void)aInfo;
#ifdef _DEBUG
    __PRINT(_L("----- TLDFormatInfo dump:"));
    __PRINT1(_L("iCapacity:%d"), aInfo.iCapacity);
    __PRINT1(_L("iSectorsPerCluster:%d"), aInfo.iSectorsPerCluster);
    __PRINT1(_L("iSectorsPerTrack:%d"), aInfo.iSectorsPerTrack);
    __PRINT1(_L("iFATBits:%d"), aInfo.iFATBits);
    __PRINT1(_L("iReservedSectors:%d"), aInfo.iReservedSectors);
    __PRINT1(_L("iFlags:%d"), aInfo.iFlags);
    __PRINT(_L("-----"));
#endif
}
/**
Implementation of pure virtual function.
@see    MWTCacheInterface::PosCached()
*/
TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart)
    {
    const TInt64 pageStartMedPos = CalcPageStartPos(aPos);

    // only search the page in lookup table
    // NOTE: we don't count the active page into acount here,
    // this is to avoid pulling next pages recursively
    TDynamicDirCachePage* pPage = LookupTblFind(pageStartMedPos);

    // then check if page is still valid if page is on Unlocked Page Queue
    if (pPage && pPage->PageType() == TDynamicDirCachePage::EUnlocked)
        {
        if (LockPage(pPage) != NULL)
            {
//          __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos);
            // have to unlock it before returning, otherwise there will be memory leak
            UnlockPage(pPage);
            aCachedPosStart = pPage->StartPos();
            return pPage->PageSizeInBytes();
            }
        else    // if the unlocked page is not valid anymore, remove it
            {
            DeQueue(pPage);
            LookupTblRemove(pPage->StartPos());
            DecommitPage(pPage);
            delete pPage;
            pPage = NULL;
            }
        }
    // otherwise if page is already locked or valid active page
    else if (pPage)
        {
        __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos);
        aCachedPosStart = pPage->StartPos();
        return pPage->PageSizeInBytes();
        }

    // page is not found or not valid anymore
    return 0;
    }
Exemple #22
0
/**
Set or reset "VolumeClean" (ClnShutBitmask) flag.

@param  aClean if ETrue, marks the volume as clean, otherwise as dirty.
@leave  if write error occured.        
*/
void CFatMountCB::SetVolumeCleanL(TBool aClean) 
    {

	//-- The volume can't be set clean if there are disk access objects opened on it. This precondition must be checked before calling this function
    if(aClean && Locked())
        {
        __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
        ASSERT(0);
        User::Leave(KErrInUse);
        return;
        }
    
    if(FatType() == EFat12)
        {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);
        return;
        }

    //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. 
    //-- this is because CFatTable doesn't allow access to FAT[0] & FAT[1]
    //-- We also need to write data through CProxyDrive, because TDriveInterface has a call back that can call this method

    if(Is32BitFat())
        {//-- Fat32
		__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT32"),DriveNumber(), aClean);
		
        TFat32Entry fatEntry;
        const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
        TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
        User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT32[1] entry

        const TFat32Entry tmp = fatEntry;
        
        if(aClean)
            fatEntry |= KFat32CleanShutDownMask;  //-- set ClnShutBit flag
        else
            fatEntry &= ~KFat32CleanShutDownMask; //-- reset ClnShutBit flag

        if(tmp != fatEntry)
            {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                {
                const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT32[1] entry
                }
            }

        __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);
        }
    else 
    if(Is16BitFat())
        {//-- Fat16. 
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16"),DriveNumber(), aClean);

            if(FatConfig().FAT16_UseCleanShutDownBit())
                {
            TFat16Entry fatEntry;
            const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
            TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
            User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry

            const TFat16Entry tmp = fatEntry;
        
            if(aClean)
                fatEntry |= KFat16CleanShutDownMask;  //-- set ClnShutBit flag
            else
                fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag

            if(tmp != fatEntry)
                {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                    {
                    const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                    User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
                    }
                }
		    
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);    
            }
            else
            {
            __PRINT(_L("#- changing FAT16[1] is disabled in config!"));    
            }
        }
    else
        {//-- must never get here
        ASSERT(0);
        }
    
		//-- Notify the underlying media that the mount is consistent  (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);


    }
/**
    Open the device and do some initalisation work.
    
    @param  aParams device parameters
    @return Epoc error code, KErrNone if everything is OK
*/
TInt CWinVolumeDevice::Connect(const TMediaDeviceParams& aParams)
{
    
    __PRINT(_L("#-- CWinVolumeDevice::Connect()"));    
    
    if(!aParams.ipDevName)
    {
        __LOG(_L("#-- CWinVolumeDevice::Connect() device name is not set!"));    
        return KErrBadName;
    }

    __PRINTF(aParams.ipDevName);
    
    ASSERT(!HandleValid() && ipScratchBuf);

    //-- open the device
    DWORD dwAccess = GENERIC_READ;
    
    if(!aParams.iReadOnly)
        dwAccess |= GENERIC_WRITE;  
    
    iDevHandle = CreateFileA(aParams.ipDevName,
                             dwAccess, 
                             FILE_SHARE_READ,
                             (LPSECURITY_ATTRIBUTES)NULL,
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);

    if(!HandleValid())
    {
        __LOG1(_L("#-- CWinVolumeDevice::Connect() Error creating device handle! WinErr:%d"), GetLastError());
        return KErrGeneral;
    }     
    
    //-- find out device geometry
    iMediaType = Unknown;
    iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

    DWORD junk; 

    //-- 1. try to query disk geometry, but it can produce wrong results for partitioned media
    BOOL bResult = DeviceIoControl(Handle(),
                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                   NULL, 0,
                                   ipScratchBuf, KScratchBufSz,
                                   &junk, (LPOVERLAPPED)NULL);

    if(bResult)
    {
        const DISK_GEOMETRY& dg = (const DISK_GEOMETRY&)*ipScratchBuf;
        
        iDrvGeometry.iBytesPerSector = dg.BytesPerSector;
        iMediaType = dg.MediaType;

        __PRINT3(_L("#-- dev geometry: Cyl:%d Heads:%d Sectors:%d"), dg.Cylinders.LowPart, dg.TracksPerCylinder, dg.SectorsPerTrack);    
        __PRINT2(_L("#-- dev geometry: MediaType:%d, bps:%d"), dg.MediaType, dg.BytesPerSector);    

    }
    else
    {
        iMediaType = Unknown;
        iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_DRIVE_GEOMETRY WinError:%d !"), GetLastError());
    }

    //-- 1.1 check "bytes per sector" value and how it corresponds to the request from parameters
    if(aParams.iDrvGeometry.iBytesPerSector == 0)
    {//-- do nothing, this parameter is not set in config file, use media's
    } 
    else if(aParams.iDrvGeometry.iBytesPerSector != iDrvGeometry.iBytesPerSector)
    {//-- we can't set "SectorSize" value for the physical media
        __LOG1(_L("#-- CWinVolumeDevice::Connect() can not use 'Sec. Size' value from config:%d !"), aParams.iDrvGeometry.iBytesPerSector);
        Disconnect();
        return KErrArgument;
    }


    ASSERT(IsPowerOf2(BytesPerSector()) && BytesPerSector() >= KDefaultSectorSz && BytesPerSector() < 4096);

    //-- find out partition information in order to determine volume size. 
    bResult = DeviceIoControl(Handle(),
                              IOCTL_DISK_GET_PARTITION_INFO,
                              NULL, 0,
                              ipScratchBuf, KScratchBufSz,
                              &junk, (LPOVERLAPPED)NULL);

    if(!bResult)
    {//-- this is a fatal error
        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_PARTITION_INFO WinError:%d !"), GetLastError());
        Disconnect();
        return KErrBadHandle;    
    }

    //-- get partition informaton
    const PARTITION_INFORMATION& pi = (const PARTITION_INFORMATION&)*ipScratchBuf;
    TInt64 volSz = MAKE_TINT64(pi.PartitionLength.HighPart, pi.PartitionLength.LowPart);
    iDrvGeometry.iSizeInSectors = (TUint32)(volSz / iDrvGeometry.iBytesPerSector);
            
    __LOG3(_L("#-- partition size, bytes:%LU (%uMB), sectors:%u"), volSz, (TUint32)(volSz>>20), iDrvGeometry.iSizeInSectors);
   
    //-- check if the media size is set in coonfig and if we can use this setting.
    if(aParams.iDrvGeometry.iSizeInSectors == 0)
    {//-- do nothing, the media size is not set in the ini file, use existing media parameters
    }
    else if(aParams.iDrvGeometry.iSizeInSectors > iDrvGeometry.iSizeInSectors)
    {//-- requested media size in ini file is bigger than physical media, error.
     //-- we can't increase physical media size
    __LOG2(_L("#-- CWinVolumeDevice::Connect() 'MediaSizeSectors' value from config:%d > than physical:%d !"), aParams.iDrvGeometry.iSizeInSectors, iDrvGeometry.iSizeInSectors);
    Disconnect();
    return KErrArgument;
    }
    else if(aParams.iDrvGeometry.iSizeInSectors < iDrvGeometry.iSizeInSectors)
    {//-- settings specify smaller media than physical one, adjust the size
    __PRINT1(_L("#-- reducing media size to %d sectors"), aParams.iDrvGeometry.iSizeInSectors);
    iDrvGeometry.iSizeInSectors = aParams.iDrvGeometry.iSizeInSectors;
    }


    ASSERT(iDrvGeometry.iSizeInSectors > KMinMediaSizeInSectors);
    return KErrNone;
}
/**
Format a disk section, called iteratively to erase whole of media, on last iteration
creates an empty volume. If called with quick formatonly erases the Fat leaving the
rest of the volume intact.

@leave System wide error code
*/
void CFatFormatCB::DoFormatStepL()
	{
	if (iFormatInfo.iFormatIsCurrent==EFalse)
		{ // Only done first time through
		if (iMode & EForceErase)
			{
			TInt r = FatMount().ErasePassword();
			User::LeaveIfError(r);
			// CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(),
			// so need to stop a remount from occurring in next call to :
			// TFsFormatNext::DoRequestL((), TDrive::CheckMount().
			FatMount().Drive().SetChanged(EFalse);
			}

        RecordOldInfoL();
		InitializeFormatDataL();
		FatMount().DoDismount();
		if (iVariableSize)
			FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
		}
    //
    // Blank disk if not EQuickFormat
    //
	if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
		{
		if (iFormatInfo.iFormatIsCurrent == EFalse)
			{//-- firstly invalidate sectors 0-6 inclusive, they may contain main boot sector, backup boot sector and FSInfo sector.
	        DoZeroFillMediaL(0, (KBkBootSectorNum+1)*iBytesPerSector);
            }
		TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
		if (ret!=KErrNone && ret!=KErrEof) // Handle format error
            ret = HandleCorrupt(ret);

        if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
		    User::Leave(ret);

		if (ret==KErrNone)
			{
			iCurrentStep = I64LOW( 100 - (100 * TInt64(iFormatInfo.i512ByteSectorsFormatted)) / iMaxDiskSectors );
			if (iCurrentStep<=0)
				iCurrentStep=1;
			return;
			}
		}

	// ReMount since MBR may have been rewritten and partition may have moved / changed size
	TInt ret = LocalDrive()->ForceRemount(0);
	if (ret != KErrNone && ret != KErrNotSupported)
		User::Leave(ret);

	// MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
	InitializeFormatDataL();

    // Translate bad sector number to cluster number which contains that sector
    // This only happens in full format, in quick format they are already cluster numbers
    if (!iVariableSize && !(iMode & EQuickFormat))
        User::LeaveIfError(BadSectorToCluster());

	//Check if root cluster is bad and update as required
	if(Is32BitFat() && !iVariableSize && (iMode & EQuickFormat))
		{
		if(iBadClusters.Find(iRootClusterNum) !=  KErrNotFound)
			{
			iRootClusterNum++;
            while(iBadClusters.Find(iRootClusterNum) != KErrNotFound)
				{
				iRootClusterNum++;
				}
			}
		}

    //
    // Do the rest of the disk in one lump
    //
	iCurrentStep=0;

    //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
    const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
	
    if (iVariableSize)
		FatMount().EnlargeL(posFatEnd); 

    DoZeroFillMediaL(0, posFatEnd);
    
    if(Is32BitFat())
		{//create an empty root directory entry here
		
        const TUint KFat32EntrySz = 4; //-- FAT32 entry size, bytes
        const TInt  startFAT1   = iReservedSectors;              //-- FAT1 start sector
        const TInt  entryOffset = iRootClusterNum*KFat32EntrySz; //-- Root dir entry offset in the FAT, bytes

		TBuf8<KFat32EntrySz> EOF(KFat32EntrySz);
		EOF[0]=0xFF;		
		EOF[1]=0xFF;
		EOF[2]=0xFF;
		EOF[3]=0x0F;

        //-- write EOF mark to the every FAT copy
    	for(TInt i=0; i<iNumberOfFats; i++)
            {
		    const TInt rootDirEntryPos = iBytesPerSector*(startFAT1 + i*iSectorsPerFat) + entryOffset;
            User::LeaveIfError(LocalDrive()->Write(rootDirEntryPos, EOF));
            }

        //-- zero-fill FAT32 root directory (just 1 cluster)
		const TInt firstDataSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); //+RootDirSectors (not required for fat32)
        const TInt firstSectorOfCluster = ((iRootClusterNum - KFatFirstSearchCluster) * iSectorsPerCluster) + firstDataSector;
	
        const TUint32 posRootDirStart = firstSectorOfCluster * iBytesPerSector;
        const TUint32 posRootDirEnd = posRootDirStart + iSectorsPerCluster*iBytesPerSector;

        DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
        }
	else
		{//-- FAT12/16
		    //-- Zero fill root directory
            const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
            const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
            
            const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
            const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;

            const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
		    if (iVariableSize)
			    FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);

            DoZeroFillMediaL(posRootDirStart, posRootDirEnd);

		// Enlarge ram drive to take into account rounding of
		// data start to cluster boundary
		if(iVariableSize && iSectorsPerCluster!=1)
			{
			const TInt firstFreeSector=rootDirSector+numOfRootSectors;
			const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
			const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
			if(alignedSector!=firstFreeSector)
				FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
			}
		}

    //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
	TBuf8<8> startFat(8);
    startFat.Fill(0xFF);
   
    if(Is32BitFat()) //-- FAT32
        {//-- FAT32 uses only low 28 bits in FAT entry. 
        startFat[3] = 0x0F;
        startFat[7] = 0x0F;
        } 
    else if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
        {
        startFat.SetLength(4);
        }
    else //-- FAT12
        {
        startFat.SetLength(3);
        }

    startFat[0]=KBootSectorMediaDescriptor;

    //-- write FAT[0] and FAT[1] entries to all copies of FAT
	for(TInt i=0;i<iNumberOfFats;i++)
        {
		User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
        }

	//-- create boot sectors
    CreateBootSectorL();

    //-- create FSInfo sectors
    if (Is32BitFat())
		{
		CreateReservedBootSectorL();
        CreateFSInfoSectorL();
		}

    //-- here we have bad clusters numbers saved by the quick format
    //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
    if (!iVariableSize && iBadClusters.Count()>0)
        {
 	
        //-- Here we need fully mounted volume, so mount it normally.
	    FatMount().MountL(EFalse);

        iBadClusters.Sort();
        TranslateL();
        const TInt mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
        
        for (TInt i=0; i<iBadClusters.Count(); ++i)
            FatMount().FAT().WriteL(iBadClusters[i], mark);
        
        FatMount().FAT().FlushL();
        
        //-- indicate that the volume is "dirty" in order to the next Mount evend not to use FSInfo, which
        //-- contains incorrect value of free clusters because we already have bad ones saved.  
        //-- This is a very rare condition.
        FatMount().SetVolumeCleanL(EFalse); 

#if defined(_DEBUG)
	TInt r=FatMount().CheckDisk();
	__PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
#endif
        }
        else
        {
        //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
        //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
        FatMount().MountL(ETrue); //-- force mount
        }

    __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
	}
/**
Create the boot sector on media for the volume. For FAT32 also creates a backup copy of the boot sector.

@leave System wide error codes
*/
void CFatFormatCB::CreateBootSectorL()
	{
	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());

    _LIT8(KName_Fat12,"FAT12   ");    ///< Name in BPB given to a Fat12 volume
    _LIT8(KName_Fat16,"FAT16   ");    ///< Name in BPB given to a Fat16 volume
    _LIT8(KName_Fat32,"FAT32   ");    ///< Name in BPB given to a Fat32 volume
    _LIT8(KDefaultVendorID, "EPOC");  ///< Vendor Name for BPB for any volume formated using a Symbian OS device

    const TBool bFat32 = Is32BitFat();
    
    TFatBootSector bootSector;

	bootSector.SetVendorID(KDefaultVendorID);
	bootSector.SetBytesPerSector(iBytesPerSector);
	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
	bootSector.SetReservedSectors(iReservedSectors);
	bootSector.SetNumberOfFats(iNumberOfFats);
	iCountOfClusters=iMaxDiskSectors/iSectorsPerCluster;
	if (!bFat32)
		{
		if (iCountOfClusters>(TInt)KMaxTUint16)
			User::Leave(KErrTooBig);
		}

	bootSector.SetReservedByte(0);
	TTime timeID;
	timeID.HomeTime();
	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate Volume UniqueID from time
	bootSector.SetVolumeLabel(_L8(""));
	
    //-- set a text string in BPB that corresponds to the FS type
    switch(FatType())
        {
        case EFat12:
            bootSector.SetFileSysType(KName_Fat12);
        break;
        
        case EFat16:
            bootSector.SetFileSysType(KName_Fat16);
        break;
        
        case EFat32:
            bootSector.SetFileSysType(KName_Fat32);
        break;

        default:
            ASSERT(0);
            User::Leave(KErrArgument);
        };



	bootSector.SetJumpInstruction();
	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
	bootSector.SetNumberOfHeads(iNumberOfHeads);
	bootSector.SetHiddenSectors(iHiddenSectors);
	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
	bootSector.SetPhysicalDriveNumber(128);
	bootSector.SetExtendedBootSignature(0x29);

	if(bFat32)
		{
		bootSector.SetFatSectors(0);
		bootSector.SetFatSectors32(iSectorsPerFat);
		bootSector.SetRootDirEntries(0);
		bootSector.SetTotalSectors(0);
		bootSector.SetHugeSectors(iMaxDiskSectors);
		bootSector.SetFATFlags(0);			
		bootSector.SetVersionNumber(0x00);	
		bootSector.SetRootClusterNum(iRootClusterNum);
		bootSector.SetFSInfoSectorNum(KFSInfoSectorNum);	
        bootSector.SetBkBootRecSector(KBkBootSectorNum);
		}
	else//fat12 and 16
		{
		bootSector.SetFatSectors32(0);
		bootSector.SetFatSectors(iSectorsPerFat);
		bootSector.SetRootDirEntries(iRootDirEntries);

		if (iMaxDiskSectors<=KMaxTUint16)
			{
			bootSector.SetTotalSectors(iMaxDiskSectors);
			bootSector.SetHugeSectors(0);
			}
		else
			{
			bootSector.SetTotalSectors(0);
			bootSector.SetHugeSectors(iMaxDiskSectors);
			}
		}

	//-- write main boot sector to the first sector on media
    User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
	
    //-- for FAT32 write backup copy of the boot sector
    if(bFat32)
        {
        User::LeaveIfError(FatMount().DoWriteBootSector(KBkBootSectorNum*bootSector.BytesPerSector(), bootSector));    
        }

    }
Exemple #26
0
CFatFileCB::CFatFileCB()
{

    __PRINT1(_L("CFatFileCB created 0x%x"),this);
}
/**
Dump cache information, only enabled in debug mode.
@see CDynamicDirCache::Control()
*/
void CDynamicDirCache::Info() const
    {
    __PRINT(_L("======== CDynamicDirCache::Info ========="));
    const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
    // page size
    __PRINT1(_L("=== Pages size:               [%d Bytes]"), iPageSizeInBytes);
    __PRINT1(_L("=== Segment size:             [%d Bytes]"), 1 << SegmentSizeInBytesLog2);

    // data size:
    __PRINT1(_L("=== Min data size:            [%d Bytes]"), iMinSizeInPages << iPageSizeLog2);
    __PRINT1(_L("=== Max data size:            [%d Bytes]"), iMaxSizeInPages << iPageSizeLog2);

    // memory size:
    const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
    __PRINT1(_L("=== Min memory size:          [%d Bytes]"), iMinSizeInPages << pageMemSizeLog2);
    __PRINT1(_L("=== Max memory size:          [%d Bytes]"), iMaxSizeInPages << pageMemSizeLog2);

    // reserved pages
    __PRINT1(_L("=== Number of pages reserved: [%d]"), iMinSizeInPages);
    __PRINT1(_L("=== Reserved memory:          [%d Bytes]"), (iMinSizeInPages * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    // locked page num
    __PRINT1(_L("=== Number of pages locked:   [%d]"), iLockedQCount);
    __PRINT1(_L("=== Locked memory:            [%d Bytes]"), (iLockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    // unlocked page num
    __PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
    __PRINT1(_L("=== Unlocked memory:          [%d Bytes]"), (iUnlockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    }
Exemple #28
0
/**
    Open a drive for formatting.
*/
TInt FsFormatOpen(CFsRequest* aRequest)
	{
    TDrive& drive = *aRequest->Drive();

	__PRINT1(_L("FsFormatOpen() drv:%d"), drive.DriveNumber());
    
    TInt nMountRes = drive.CheckMount();
    //-- KErrNotReady means that there is no file system mounted on this drive
    //-- KErrInUse means that there are some "disk access" objects, like RFormat or RRawDisk opened on the mount.
    if(nMountRes == KErrNotReady || nMountRes == KErrInUse) 
        {
        __PRINT1(_L("FsFormatOpen() ChkMount:%d"), nMountRes);
        return nMountRes;
        }
    
    const TFormatMode fmtMode = (TFormatMode)aRequest->Message().Int1();
    TName buf;
    TUint32 currFsNameHash = 0; //-- current file system name hash, 0 means "not set"; used during forced FS dismounting

    if((nMountRes == KErrNone) && drive.CurrentMount().LockStatus() < 0)
        {//-- the mount is locked, it has normal objects (files, directories) opened on it. 
        
        //-- if someone is interested in the list of opened files and number of opened directories, compile this code in.
        #ifdef DUMP_OPENED_OBJECTS
            DumpOpenedObjects(drive);
        #endif //DUMP_OPENED_OBJECTS


        if(!(fmtMode & EForceFormat))
            {
            __PRINT(_L("FsFormatOpen() The mount is in use"));
            return KErrInUse;
            }    

        //-- there is a special flag that tells to force media dismounting even if it has files or dirs opened.
        __PRINT(_L("FsFormatOpen() The mount is in use, forcing dismounting!"));

        //-- record currently mounted FS name hash, it may be used after forced dismounting
        drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
        currFsNameHash = TVolFormatParam::CalcFSNameHash(buf);

        //-- kill the current mount
        FsThreadManager::LockDrive(drive.DriveNumber());
        TInt nRes = drive.ForceUnmountFileSystemForFormatting();
        FsThreadManager::UnlockDrive(drive.DriveNumber());

        
        switch(nRes)
            {
            case KErrInUse: 
            __PRINT(_L("FsFormatOpen() The mount has clamps! Can't force dismount"));    
            return KErrInUse; //-- there are clamps on this drive - can't dismount

            case KErrNone:
            break;

            default:
            ASSERT(0); //-- unexpected error code
            return nRes;

            };

        if(fmtMode & EQuickFormat)
            {//-- quick format may require the normally mounted FS, make the best effrot to mount it
            nMountRes = drive.CheckMount();
            }
        else
            {//-- this will make the FS mounted by force; for full format it will be quicker
            nMountRes = KErrCorrupt;
            }

        }

	//-- if True, we will need mount (probably specific) file system by force because normal mounting has failed
    TBool bNeedForceMount = (nMountRes != KErrNone); 

    //-- find out if we have optional data structure that describes format parameter
    TUint32 newFsNameHash = 0; //-- file system name hash, may be used for selecting which file system to put onto the volume. 0 means "not specified"

    const TLDFormatInfo*    pLDFormatInfo   = NULL;
    const TVolFormatParam*  pVolFormatParam = NULL;

    __ASSERT_COMPILE(sizeof(TVolFormatParam) >= sizeof(TLDFormatInfo));
    TBuf8<sizeof(TVolFormatParam)> paramBuf;
   
    
    if(fmtMode & ESpecialFormat)  
        {   
        //-- the user has provided format parameters structure.
        //-- IPC argument #2 contains a structure: <TUint32>[optional package descriptor]
        //-- where 1st mandatory TUint32 is a pointer to format counter and the optional additional package is a data structure passed to the filesystem by the client of RFormat
        const TInt desLen = aRequest->GetDesLength(KMsgPtr2);
        ASSERT((TUint32)desLen >= sizeof(TUint32));
    
        const TInt dataPckgLen = desLen - sizeof(TUint32);

        if((TUint32)dataPckgLen > sizeof(TUint32))
            {
            aRequest->ReadL(KMsgPtr2, paramBuf); 
            }
        
        if(dataPckgLen == sizeof(TLDFormatInfo))
            {//-- the user has provided formatting parameters via TLDFormatInfo structure.
            pLDFormatInfo = (const TLDFormatInfo*)(paramBuf.Ptr() + sizeof(TUint32));
            }
        else if(dataPckgLen == sizeof(TVolFormatParam))
            {//-- it's likely to be TVolFormatParam, need to check UId to be sure.
            pVolFormatParam = (const TVolFormatParam*)(const TVolFormatParam*)(paramBuf.Ptr() + sizeof(TUint32));

            if(pVolFormatParam->iUId == TVolFormatParam::KUId)  //-- check the class UID
                {//-- this is the real TVolFormatParam object passed
                newFsNameHash = pVolFormatParam->FSNameHash();
                }
            }
        else if(dataPckgLen >0)
            {//-- parameters data structure has strange length
            return KErrArgument;
            }
    
        }

    //-------------------
    if(!newFsNameHash && currFsNameHash)
        {//-- new file system name isn't specified (default formatting), but the volume had been forcedly dismounted.
         //-- restore the original file system   
        newFsNameHash = currFsNameHash;
        }
    
    if(newFsNameHash)
        {//-- check if the specified FS is already mounted on the volume
        if(!bNeedForceMount)
            {
            drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
            }
        else
            { //-- the iCurrentMount can be NULL, use the iFsys - the real file system associated with this drive
            buf = drive.GetFSys()->Name();
            }

        const TUint32 currFSNameHash = TVolFormatParam::CalcFSNameHash(buf);
        if(currFSNameHash == newFsNameHash)
            {//-- no need to do anything, the required FS is already mounted
            newFsNameHash = 0; 
            } 
        }

    if(newFsNameHash) 
        {
        //-- the user has specified some filesystem to be mounted on the volume. Check if this FS is supported at all.
        //-- if it is supported, but some other FS is currently mounted, it will be dismounted and the new one will be forced.
        TInt nRes;
            
        for(TInt cntFS=0; ;++cntFS)
            {
            nRes = drive.FSys().GetSupportedFileSystemName(cntFS, buf); //-- enumerate possible child file systems
            
            if(nRes != KErrNone)
                return KErrNotSupported; //-- the filesystem with the given name (fsNameHash) is not supported.

            if(newFsNameHash == TVolFormatParam::CalcFSNameHash(buf))
                {//-- the filesystem with the given name (fsNameHash) is supported, but some other filesystem can be already mounted
                drive.Dismount();
                bNeedForceMount = ETrue; //-- this will force the desired FS to be mounted
                break;
                }
            }
    
        }//if(fsNameHash) 


    //-- try force mounting the desired file system if it is required
    if(bNeedForceMount)
        {
        const TInt KMaxRetries = 3;
        for(TInt cnt=0; ; ++cnt)
            {
            drive.MountFileSystem(ETrue, newFsNameHash);

            nMountRes = drive.GetReason();
            if(nMountRes == KErrNone || nMountRes == KErrLocked)
                break;
            
            drive.Dismount(); //-- will reset mount retries counter
            
            if(cnt >= KMaxRetries)
                {
                __PRINT1(_L("FsFormatOpen() can't mount FS! res:%d"), nMountRes);    
                return nMountRes;
                }
            }
        }

    ASSERT(nMountRes == KErrNone || nMountRes == KErrLocked);
    
    __ASSERT_DEBUG(drive.CurrentMount().LockStatus()==0, Fault(ESvrFormatOpenFailed));


	TDriveInfo dInfo;
	drive.DriveInfo(dInfo);
	const TInt mediaAtt = dInfo.iMediaAtt;

#if defined(_LOCKABLE_MEDIA)
	if (!(fmtMode & EForceErase) && (mediaAtt & KMediaAttLocked))
		{
		// if attempting to format a locked drive, dismount otherwise subsequent 
		// requests will operate on a mount that has been forcibly mounted (a few lines above)
		CMountCB* pM = &drive.CurrentMount();
		
        if(pM)
			pM->Close();

		drive.MountFileSystem(EFalse);	// clear iCurrentMount
		return KErrLocked;
		}
#endif

	if (!(mediaAtt & KMediaAttFormattable) || (mediaAtt & KMediaAttWriteProtected))
		{
		CMountCB* pM = &drive.CurrentMount();
		
        if(pM)
			pM->Close();

		drive.MountFileSystem(EFalse);
        return KErrAccessDenied;
		}

	//-- instantinate and open CFormatCB object for this drive
    CFormatCB* formatCB=NULL;
	TInt fmtHandle;
    
    TRAPD(ret, formatCB = drive.FormatOpenL(aRequest, fmtHandle, fmtMode, pLDFormatInfo, pVolFormatParam ));

	if (ret!=KErrNone)
		{
		if(formatCB)
			formatCB->Close();

		return ret;
		}

	TPtrC8 pH((TUint8*)&fmtHandle,sizeof(TInt));
	aRequest->WriteL(KMsgPtr3,pH);
	TInt count=100;

	TPtrC8 pCount((TUint8*)&count,sizeof(TInt));
	aRequest->WriteL(KMsgPtr2,pCount);
	aRequest->Session()->IncResourceCount();
	
    return KErrNone;
	}
/**
Implementation of pure virtual function.
@see    MWTCacheInterface::MakePageMRU()
*/
void CDynamicDirCache::MakePageMRU(TInt64 aPos)
    {
    __PRINT1(_L("MakePageMRU (%lx)"), aPos);
//  __PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
    // check the MRU page first, if it is already the MRU page, we can return immediately
    TInt64 pageStartMedPos = CalcPageStartPos(aPos);
    if (!iLockedQ.IsEmpty())
        {
        if (iLockedQ.First()->StartPos() == pageStartMedPos)
            {
            return;
            }
        }

    TDynamicDirCachePage* pPage = FindPageByPos(aPos);
    if (pPage)
        {
        ASSERT(pPage->IsValid());
        // lock page before make it MRU
        if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
            {
            ASSERT(!pPage->IsLocked());
            if (LockPage(pPage) == NULL)
                {
                DeQueue(pPage);
                LookupTblRemove(pPage->StartPos());
                DecommitPage(pPage);
                delete pPage;
                pPage = NULL;
                }
            }
        else
            {
            // error checking: page should either be locked or active
            ASSERT(LockPage(pPage) != NULL);
            }
        }

    // if page not found or page data not valid anymore, use active page to read data
    if (!pPage)
        {
        TRAPD(err, pPage = UpdateActivePageL(aPos));
        if (err != KErrNone)
            {
            // problem occurred reading active page, return immediately.
            return;
            }
        }

    // by now, the page is either locked or active page
    ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());

    switch (pPage->PageType())
        {
        // if the page is the active page, we will need to find a new active page for replacement
        case TDynamicDirCachePage::EActivePage:
            {
            TDynamicDirCachePage* newAP = NULL;
            // if there is more cache room available, try to create a new page first
            if (!CacheIsFull())
                {
                // allocate and lock a new page
                TRAPD(err, newAP = AllocateAndLockNewPageL(0));
                // if any error ocurrs, return immediately
                if (err != KErrNone)
                    {
                    // unlock the page that was originally unlocked before leave
                    if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
                        {
                        UnlockPage(pPage);
                        }
                    return;
                    }

                if (newAP)
                    {
                    // replace the active page with the new page
                    newAP->SetPageType(TDynamicDirCachePage::EActivePage);
                    iActivePage = newAP;
                    }
                }

            // if cache has grown to its max size, or new page allocation failed
            if (!newAP)
                {
                // try to lock the LRU page on the unlocked page queque first
                if (!iUnlockedQ.IsEmpty())
                    {
                    newAP = iUnlockedQ.Last();
                    ASSERT(newAP->IsValid());
                    if (LockPage(newAP) != NULL)
                        {
                        // deque, reset pos, set new type
                        DeQueue(newAP);
                        LookupTblRemove(newAP->StartPos());
                        ResetPagePos(newAP);
                        newAP->SetPageType(TDynamicDirCachePage::EActivePage);
                        // replace active page
                        iActivePage = newAP;
                        }
                    // if falied locking the LRU page from unclocked queque,
                    // delete it
                    else
                        {
                        DeQueue(newAP);
                        LookupTblRemove(newAP->StartPos());
                        DecommitPage(newAP);
                        delete newAP;
                        newAP = NULL;
                        }
                    }
                }

            // if still have not found new active page
            // grab the LRU page from Locked Page Queue for active page
            if (!newAP)
                {
                ASSERT(!iLockedQ.IsEmpty());
                newAP = iLockedQ.Last();
                // deque, reset pos, set new type
                DeQueue(newAP);
                LookupTblRemove(newAP->StartPos());
                ResetPagePos(newAP);
                newAP->SetPageType(TDynamicDirCachePage::EActivePage);
                // replace active page
                iActivePage = newAP;
                }

            // we should always be able to find a locked page for active page
            ASSERT(newAP != NULL);

            // make original page (i.e. former active page) MRU
            // add onto locked queue
            AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
            // add onto lookuptbl, as active page is not on lookup tbl originally
            LookupTblAdd(pPage);
            // check cache limit
            CheckThresholds();
            return;
            }
        case TDynamicDirCachePage::EUnlocked:
            {
            // if page was originally on Unlocked Page Queque, remove it from Unlocked Page Queue, add it
            // to the Locked Page Queue and make it MRU
            DeQueue(pPage);
            AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
            // check cache limit
            CheckThresholds();
            return;
            }
        case TDynamicDirCachePage::ELocked:
            {
            // otherwise the page was on Locked Page Queue, make it MRU
            // no need to check cache limit
            if (pPage != iLockedQ.First())
                {
                DeQueue(pPage);
                AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
                return;
                }
            break;
            }
        default:
            ASSERT(0);
        }
    }