sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // Implementation for CEComCachedDriveInfo class
sl@0: // 
sl@0: //
sl@0: 
sl@0: /**
sl@0:  @file
sl@0:  @internalComponent
sl@0: */
sl@0: 
sl@0: #include <e32const.h>
sl@0: #include <f32file.h>
sl@0: #include <bsul/bsul.h>
sl@0: #include <ecom/ecomerrorcodes.h>
sl@0: #include "DriveInfo.h"
sl@0: #include "EComPatchDataConstantv2.h"
sl@0: #include "EComInternalErrorCodes.h"
sl@0: const TInt KInvalidIndex = -1;
sl@0: const TInt32 KInvalidDrvNumber = -1;
sl@0: 
sl@0: /** static member of CEComCachedDriveInfo */
sl@0: TFixedArray<TEComDrvFlags, KMaxDrives> CEComCachedDriveInfo::iDriveAttr;
sl@0: 
sl@0: /** static member of CEComCachedDriveInfo */
sl@0: TInt CEComCachedDriveInfo::iLastIndex = KInvalidIndex;
sl@0: 
sl@0: /** static member of CEComCachedDriveInfo */
sl@0: TBool CEComCachedDriveInfo::iInitialized = EFalse;
sl@0: 
sl@0: 
sl@0: /** Standard factory method to instantiate CEComCachedDriveInfo instances.
sl@0: */
sl@0: CEComCachedDriveInfo* CEComCachedDriveInfo::NewL(RFs& aFs)
sl@0: 	{
sl@0: 	CEComCachedDriveInfo* self = new (ELeave) CEComCachedDriveInfo;
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL(aFs, KDiscoveryDisabledDriveList);
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: /** Constructor of CEComCachedDriveInfo. Nothing to do. */
sl@0: CEComCachedDriveInfo::CEComCachedDriveInfo()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: /** Standard two-phase construction to complete construction
sl@0: of CEComCachedDriveInfo.
sl@0: 
sl@0: @param aFs reference to a connected RFs session.
sl@0: @param aDiscoveryDisabledMask bits set indicate the drives contain no plug-ins
sl@0: 	and need not be scanned. There is a mechanism to allow licensees to
sl@0: 	specify this mask at ROM build time.
sl@0: @leave KErrNoMemory if out of memory, or any of the other system wide errors.
sl@0: */
sl@0: void CEComCachedDriveInfo::ConstructL(RFs& aFs, TUint32 aDiscoveryDisabledMask)
sl@0: 	{
sl@0: 	if (iInitialized)
sl@0: 		{
sl@0: 		return;
sl@0: 		}
sl@0: 
sl@0: 	iLastIndex = KInvalidIndex;
sl@0: 
sl@0: 	// Get list of installed drives. This info is not available from
sl@0: 	// BSUL::CCachedDriveInfo API's.
sl@0: 	TDriveList drvList;
sl@0: 	User::LeaveIfError( aFs.DriveList(drvList) );
sl@0: 
sl@0: 	BSUL::CCachedDriveInfo* cachedDrvInfo = BSUL::CCachedDriveInfo::NewL(aFs);
sl@0: 	CleanupStack::PushL(cachedDrvInfo);
sl@0: 
sl@0: 	// determine attributes of valid drives
sl@0: 	for (TInt i = EDriveA; i <= EDriveZ; i++)
sl@0: 		{
sl@0: 		if (drvList[i])
sl@0: 			{
sl@0: 			// drive exist
sl@0: 			TInt j = ++iLastIndex;
sl@0: 
sl@0: 			iDriveAttr[j].iDrvNumber = i; 
sl@0: 
sl@0: 			TDriveUnit drvUnit(i);
sl@0: 			if (cachedDrvInfo->IsReadOnlyInternalL(drvUnit))
sl@0: 				{
sl@0: 				iDriveAttr[j].iFlags = EEComDrvAttrReadOnlyInternal;
sl@0: 				// RO internal drive does not have any other attributes
sl@0: 				continue;
sl@0: 				}
sl@0: 
sl@0: 			iDriveAttr[j].iFlags = 0; 
sl@0: 
sl@0: 			// Check if drive is removable
sl@0: 			if (cachedDrvInfo->IsFlagSetOnDriveL(drvUnit, KDriveAttRemovable))
sl@0: 				{
sl@0: 				iDriveAttr[j].iFlags |= EEComDrvAttrRemovable;
sl@0: 				}
sl@0: 
sl@0: 			// Check if drive is on ReadWrite drive
sl@0: 			if (! cachedDrvInfo->IsFlagSetOnDriveL(drvUnit, KDriveAttRom))
sl@0: 				{
sl@0: 				iDriveAttr[j].iFlags |= EEComDrvAttrWritable;
sl@0: 				}
sl@0: 
sl@0: 			TUint32 drvBitMask = 1;
sl@0: 			drvBitMask <<= i;
sl@0: 			// Three conditions for discovery disable: disabled by licensees,
sl@0: 			// remote drives and substituted drives
sl@0: 			if ( (drvBitMask & aDiscoveryDisabledMask) ||
sl@0: 				 cachedDrvInfo->IsFlagSetOnDriveL(drvUnit, KDriveAttSubsted) ||
sl@0: 				 cachedDrvInfo->IsFlagSetOnDriveL(drvUnit, KDriveAttRemote) )
sl@0: 				{
sl@0: 				iDriveAttr[j].iFlags |= EEComDrvAttrNoDiscovery;
sl@0: 				}
sl@0: 			} // if drvList[i]
sl@0: 		} // for
sl@0: 
sl@0: 	CleanupStack::PopAndDestroy(cachedDrvInfo);
sl@0: 	__ASSERT_DEBUG(iLastIndex >= 0, User::Invariant());
sl@0: 
sl@0: 	for (TInt i = iLastIndex + 1; i < KMaxDrives; i++)
sl@0: 		{
sl@0: 		iDriveAttr[i].iDrvNumber = KInvalidDrvNumber; 
sl@0: 		}
sl@0: 
sl@0: 	iInitialized = ETrue;
sl@0: 	}
sl@0: 
sl@0: /** Is EEComDrvAttrReadOnlyInternal attribute set on the given drive?
sl@0: @param aDrive the drive number
sl@0: @return ETrue if drive is RO internal. EFalse means either no such drive or
sl@0: 	not RO internal.
sl@0: @leave KEComErrDriveNotFound if aDrive is not supposed to be scanned,
sl@0: 	i.e. drive absent or disabled by licensees or subst or remote.
sl@0:     Use TEComCachedDriveInfoIterator::SetPos instead if want to test drive
sl@0: 	attribute.
sl@0: */
sl@0: TBool CEComCachedDriveInfo::DriveIsReadOnlyInternalL(const TInt aDrive) const
sl@0: 	{
sl@0: 	TEComCachedDriveInfoIterator iter(*this);
sl@0: 
sl@0: 	if (! iter.SetPos(aDrive))
sl@0: 		{
sl@0: 		// This method is intended to be used on drives that are known
sl@0: 		// to be valid, e.g. drive extracted from the path of a discovered
sl@0: 		// DLL.
sl@0: 		User::Leave(KEComErrDriveNotFound);
sl@0: 		}
sl@0: 	return iter.DriveIsReadOnlyInternal();
sl@0: 	}
sl@0: 
sl@0: /** Test if the EEComDrvAttrRemovable attribute for the given drive is set.
sl@0: @param aDrive the drive number
sl@0: @return ETrue if drive is removable. EFalse means either no such drive or
sl@0: 	not removable.
sl@0: @leave KEComErrDriveNotFound if aDrive is not supposed to be scanned,
sl@0: 	i.e. drive absent or disabled by licensees or subst or remote.
sl@0:     Use TEComCachedDriveInfoIterator::SetPos instead if want to test drive
sl@0: 	is removable.
sl@0: */
sl@0: TBool CEComCachedDriveInfo::DriveIsRemovableL(const TInt aDrive) const
sl@0: 	{
sl@0: 	TEComCachedDriveInfoIterator iter(*this);
sl@0: 
sl@0: 	if (! iter.SetPos(aDrive))
sl@0: 		{
sl@0: 		// This method is intended to be used on drives that are known
sl@0: 		// to be valid, e.g. drive extracted from the path of a discovered
sl@0: 		// DLL.
sl@0: 		User::Leave(KEComErrDriveNotFound);
sl@0: 		}
sl@0: 	return iter.DriveIsRemovable();
sl@0: 	}
sl@0: 
sl@0: /** Test if the EEComDrvAttrWritable attribute for the given drive is set.
sl@0: @param aDrive the drive number
sl@0: @return ETrue if drive is writable. EFalse means either no such drive or
sl@0: 	drive not writable.
sl@0: @leave KEComErrDriveNotFound if aDrive is not supposed to be scanned,
sl@0: 	i.e. drive absent or disabled by licensees or subst or remote.
sl@0:     Use TEComCachedDriveInfoIterator::SetPos instead if want to test drive
sl@0: 	is removable.
sl@0: */
sl@0: TBool CEComCachedDriveInfo::DriveIsWritableL(const TInt aDrive) const
sl@0: 	{
sl@0: 	TEComCachedDriveInfoIterator iter(*this);
sl@0: 
sl@0: 	if (! iter.SetPos(aDrive))
sl@0: 		{
sl@0: 		// This method is intended to be used on drives that are known
sl@0: 		// to be valid, e.g. drive extracted from the path of a discovered
sl@0: 		// DLL.
sl@0: 		User::Leave(KEComErrDriveNotFound);
sl@0: 		}
sl@0: 	return iter.DriveIsWritable();
sl@0: 	}
sl@0: 
sl@0: // Implementation for TEComCachedDriveInfoIterator class
sl@0: 
sl@0: /** TEComCachedDriveInfoIterator Constructor
sl@0: Note that the object is not yet in valid state. User must first call
sl@0: First() or Last().
sl@0: */
sl@0: TEComCachedDriveInfoIterator::TEComCachedDriveInfoIterator(const CEComCachedDriveInfo& aCachedDriveInfo)
sl@0: 	: iDriveAttr(aCachedDriveInfo.iDriveAttr)
sl@0: 	{
sl@0: 	iIndex = KInvalidIndex;
sl@0: 	}
sl@0: 
sl@0: /** Check if the drive is enabled for scanning and move index there if true.
sl@0: @param aDrive the drive number of the drive to check.
sl@0: @return ETrue the drive is enabled for scanning. Index is moved to that location.
sl@0: 	If drive not to be scanned, index is moved out of bound.
sl@0: */
sl@0: TBool TEComCachedDriveInfoIterator::SetPos(const TInt aDrive)
sl@0: 	{
sl@0: 	for (iIndex = CEComCachedDriveInfo::iLastIndex; iIndex >= 0; iIndex--)
sl@0: 		{
sl@0: 		if (iDriveAttr[iIndex].iDrvNumber == aDrive)
sl@0: 			{
sl@0: 		    if (0 == (iDriveAttr[iIndex].iFlags & EEComDrvAttrNoDiscovery))
sl@0: 				{
sl@0: 				return ETrue;
sl@0: 				}
sl@0: 			iIndex = KInvalidIndex;
sl@0: 			break;
sl@0: 			}
sl@0: 		}
sl@0: 	return EFalse;
sl@0: 	}
sl@0: 
sl@0: /** Position iterator at first valid drive so as to
sl@0: iterate the drive list in increasing drive number order. */
sl@0: void TEComCachedDriveInfoIterator::First(void)
sl@0: 	{
sl@0: 	for (iIndex = 0; iIndex <= CEComCachedDriveInfo::iLastIndex; iIndex++)
sl@0: 		{
sl@0: 		if (0 == (iDriveAttr[iIndex].iFlags & EEComDrvAttrNoDiscovery))
sl@0: 			{
sl@0: 			return;
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** Position iterator at last valid drive so as to
sl@0: iterate the drive list in decreasing drive number order. */
sl@0: void TEComCachedDriveInfoIterator::Last(void)
sl@0: 	{
sl@0: 	for (iIndex = CEComCachedDriveInfo::iLastIndex; iIndex >=0; iIndex--)
sl@0: 		{
sl@0: 		if (0 == (iDriveAttr[iIndex].iFlags & EEComDrvAttrNoDiscovery))
sl@0: 			{
sl@0: 			return;
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** To be used in for and while loops to check if iterator
sl@0: has stepped through all posible drives. */
sl@0: TBool TEComCachedDriveInfoIterator::InRange(void) const
sl@0: 	{
sl@0: 	return (iIndex >= 0 && iIndex <= CEComCachedDriveInfo::iLastIndex);
sl@0: 	}
sl@0: 
sl@0: /** Increment iterator to next valid drive. */
sl@0: void TEComCachedDriveInfoIterator::Next(void)
sl@0: 	{
sl@0: 	if (InRange())
sl@0: 		{
sl@0: 		for (++iIndex; iIndex <= CEComCachedDriveInfo::iLastIndex; iIndex++)
sl@0: 			{
sl@0: 			if (0 == (iDriveAttr[iIndex].iFlags & EEComDrvAttrNoDiscovery))
sl@0: 				{
sl@0: 				return;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** Decrement iterator to next valid drive. */
sl@0: void TEComCachedDriveInfoIterator::Prev(void)
sl@0: 	{
sl@0: 	if (InRange())
sl@0: 		{
sl@0: 		for (--iIndex; iIndex >= 0; iIndex--)
sl@0: 			{
sl@0: 			if (0 == (iDriveAttr[iIndex].iFlags & EEComDrvAttrNoDiscovery))
sl@0: 				{
sl@0: 				return;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @panic USER:133 from TFixedArray if iterator is out of bound.
sl@0: */
sl@0: TDriveNumber TEComCachedDriveInfoIterator::DriveNumber(void) const
sl@0: 	{
sl@0: 	return static_cast<TDriveNumber>( iDriveAttr.At(iIndex).iDrvNumber );
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @panic USER:133 from TFixedArray if iterator is out of bound.
sl@0: */
sl@0: TDriveUnit TEComCachedDriveInfoIterator::DriveUnit(void) const
sl@0: 	{
sl@0: 	return TDriveUnit( DriveNumber() );
sl@0: 	}
sl@0: 
sl@0: /** Test if the EEComDrvAttrReadOnlyInternal attribute for the current
sl@0: drive is set.
sl@0: @panic USER:133 from TFixedArray if iterator is out of bound.
sl@0: */
sl@0: TBool TEComCachedDriveInfoIterator::DriveIsReadOnlyInternal(void) const
sl@0: 	{
sl@0: 	if (EEComDrvAttrReadOnlyInternal & iDriveAttr.At(iIndex).iFlags)
sl@0: 		{
sl@0: 		return ETrue;
sl@0: 		}
sl@0: 	return EFalse;
sl@0: 	}
sl@0: 
sl@0: /** Test if the EEComDrvAttrRemovable attribute for the current
sl@0: drive is set.
sl@0: @panic USER:133 from TFixedArray if iterator is out of bound.
sl@0: */
sl@0: TBool TEComCachedDriveInfoIterator::DriveIsRemovable(void) const
sl@0: 	{
sl@0: 	if (EEComDrvAttrRemovable & iDriveAttr.At(iIndex).iFlags)
sl@0: 		{
sl@0: 		return ETrue;
sl@0: 		}
sl@0: 	return EFalse;
sl@0: 	}
sl@0: 
sl@0: /** Test if the EEComDrvAttrWritable attribute for the current drive is set.
sl@0: @return ETrue if drive is writable. EFalse means drive is not writable.
sl@0: @panic USER:133 from TFixedArray if iterator is out of bound.
sl@0: */
sl@0: TBool TEComCachedDriveInfoIterator::DriveIsWritable(void) const
sl@0: 	{
sl@0: 	if (EEComDrvAttrWritable & iDriveAttr.At(iIndex).iFlags)
sl@0: 		{
sl@0: 		return ETrue;
sl@0: 		}
sl@0: 	return EFalse;
sl@0: 	}