--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/swins/elocal.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,1761 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "elocal.h"
+#include <emulator.h>
+#include <TCHAR.h>
+
+const TInt KMajorVersionNumber=1;
+const TInt KMinorVersionNumber=0;
+
+const TUint KInvalidSetFilePointer = 0xffffffff; // INVALID_SET_FILE_POINTER
+
+#pragma data_seg(".data2")
+#ifdef __VC32__
+#pragma bss_seg(".data2")
+#endif
+static TInt ReadSpeed;
+static TInt WriteSpeed;
+#pragma data_seg()
+#ifdef __VC32__
+#pragma bss_seg()
+#endif
+
+static void Panic(TPanic aPanic)
+ {
+ User::Panic(_L("LocalFSys"),aPanic);
+ }
+
+
+//
+// Map aDrive to a path given by environment variables
+//
+TBool MapDrive(TDes& aFileName, TInt aDrive)
+ {
+
+ TDriveName root(TDriveUnit(aDrive).Name());
+ TFileName path;
+ TBuf<3> rootWithSlash(root);
+ rootWithSlash.Append('\\');
+
+ if (MapEmulatedFileName(path, rootWithSlash) == KErrNone)
+ {
+ aFileName=path.Left(3); // drive letter, colon and backslash
+ return(ETrue);
+ }
+ aFileName=root; // no trailing backslash
+ return(EFalse);
+ }
+
+TInt MapFileName(TDes& aFileName, TInt aDrive, const TDesC& aName)
+ {
+ TFileName n(TDriveUnit(aDrive).Name());
+ n.Append(aName);
+ return MapEmulatedFileName(aFileName,n);
+ }
+
+void MapFileNameL(TDes& aFileName, TInt aDrive, const TDesC& aName)
+ {
+ User::LeaveIfError(MapFileName(aFileName,aDrive,aName));
+ }
+
+
+/**
+Check whether a descriptor has enough space for null-terminating and append a zero terminator if it does.
+Supposed to be used for Win32 file operations, taking C-like strings as parameters.
+The main purpose is to avoid panics caused by descriptors overflow.
+
+@param aDes descriptor to be null-terminated; a file(directory) name presumably.
+@return cast to LPCTSTR value of the descriptor, supposed to be the unicode string
+@leave KErrBadName if there is no room for trailing zero
+*/
+LPCTSTR StrPtrZL(TDes16& aDes)
+ {
+ if(aDes.MaxLength() - aDes.Length() < 1)
+ User::Leave(KErrBadName); //-- no room for terminating zero
+
+ return (LPCTSTR)aDes.PtrZ();
+ }
+
+
+
+//
+// Converts a TTime structure to a Windows/NT filetime. Assumes that aTime is a
+// UTC (system) time
+//
+static void timeToFileTimeL(const TTime& aTime,FILETIME* f)
+ {
+
+ TDateTime dateTime=aTime.DateTime();
+ SYSTEMTIME t;
+ #pragma warning( disable : 4244 ) // conversion from 'const int' to 'unsigned short', possible loss of data
+ t.wYear=dateTime.Year();
+ t.wMonth=dateTime.Month()+1;
+ t.wDay=dateTime.Day()+1;
+ t.wDayOfWeek=(aTime.DayNoInWeek()+1)%7;
+ t.wHour=dateTime.Hour();
+ t.wMinute=dateTime.Minute();
+ t.wSecond=dateTime.Second();
+ t.wMilliseconds=dateTime.MicroSecond()/1000;
+ #pragma warning( default : 4244 ) // conversion from 'const int' to 'unsigned short', possible loss of data
+ __ASSERT_ALWAYS(SystemTimeToFileTime(&t,f)==TRUE,User::Leave(KErrArgument));
+ }
+
+//
+// Convert Windows/NT file time to TTime
+// Assumes the NT file time is UTC
+//
+static void fileTimeToTime(FILETIME* f,TTime& aTime)
+ {
+ SYSTEMTIME t;
+ __ASSERT_ALWAYS(FileTimeToSystemTime(f,&t)==TRUE,Panic(EFileTimeToSystemTime));
+ aTime=TDateTime(t.wYear,TMonth(t.wMonth-1),t.wDay-1,t.wHour,t.wMinute,t.wSecond,t.wMilliseconds*1000);
+ }
+
+//
+// Return the size and free space on a drive.
+//
+static TInt GetMediaSize(TInt aDriveNumber,TInt64& aSize,TInt64& aFree)
+ {
+
+ TBuf<4> driveName;
+ MapDrive(driveName,aDriveNumber);
+ DWORD sectorsPerCluster;
+ DWORD bytesPerSector;
+ DWORD freeClusters;
+ DWORD sizeClusters;
+ // this function should be upgraded to GetDiskFreeSpaceEx
+ BOOL b=Emulator::GetDiskFreeSpace((LPCTSTR)driveName.PtrZ(),§orsPerCluster,&bytesPerSector,&freeClusters,&sizeClusters);
+ if (!b)
+ return Emulator::LastError();
+
+ TInt64 bytesPerCluster=(TInt)(sectorsPerCluster*bytesPerSector);
+ aSize=TInt64((TInt)sizeClusters)*bytesPerCluster;
+ aFree=TInt64((TInt)freeClusters)*bytesPerCluster;
+ return(KErrNone);
+ }
+
+//
+// Return the volume name and uniqueID.
+//
+static TInt GetVolumeId(TInt aDriveNumber,TUint& aUniqueID)
+ {
+
+ TBuf<4> driveName;
+ MapDrive(driveName,aDriveNumber);
+ DWORD uniqueID,componentLength,flags;
+ BOOL b=Emulator::GetVolumeInformation((LPCTSTR)driveName.PtrZ(),NULL,0,&uniqueID,&componentLength,&flags,NULL,0);
+ if (!b)
+ return Emulator::LastError();
+
+ aUniqueID=uniqueID;
+ return(KErrNone);
+ }
+
+//#########################################################################################################################
+//## CLocalMountCB class implementation
+//#########################################################################################################################
+
+
+CLocalMountCB::CLocalMountCB()
+ {
+ }
+
+CLocalMountCB::~CLocalMountCB()
+ {
+ }
+
+
+//
+// Returns ETrue if the drive == EDriveZ
+//
+TBool CLocalMountCB::IsRomDrive() const
+ {
+ // WINS emulated rom drive is Z:
+ return(Drive().DriveNumber()==EDriveZ);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+
+/**
+Mount a volume.
+
+@param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
+@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
+*/
+void CLocalMountCB::MountL(TBool /*aForceMount*/)
+ {
+ TInt64 s,f;
+ const TInt driveNum=Drive().DriveNumber();
+ User::LeaveIfError(GetMediaSize(driveNum,s,f));
+
+ iSize=s;
+ if (driveNum==EDriveZ)
+ iSize=4*1048576;
+
+ User::LeaveIfError(GetVolumeId(driveNum,iUniqueID));
+ SetVolumeName(HBufC::NewL(0)); // all Win32 volumes are unnamed
+
+ //-- assign default value, 4G-1
+ iMaxFileSizeSupported = ((TUint64)4 << 30)-1;
+
+ {
+ //-- find out the maximal supported file size. For this we need to query the name of the windows filesystem that is
+ //-- used for the emulated drive
+ TBuf<20> bufWinDrive;
+ MapDrive(bufWinDrive, Drive().DriveNumber());
+ ASSERT(bufWinDrive.Length() >= 3);
+
+ TCHAR rootName[10];
+ TCHAR volName[30];
+ TCHAR volFSFileName[30];
+ DWORD volSerNum;
+ DWORD volMaxCompLen;
+ DWORD volFsFlags;
+
+ memset(rootName, 0, sizeof(rootName));
+ wcsncpy(rootName, bufWinDrive.Ptr(), 3); //- something like "k:\\"
+
+ BOOL b = GetVolumeInformation(rootName, volName, sizeof(volName)/sizeof(TCHAR), &volSerNum, &volMaxCompLen, &volFsFlags, volFSFileName, sizeof(volFSFileName)/sizeof(TCHAR));
+ if(b)
+ {
+ if(_wcsicmp(volFSFileName, _TEXT("NTFS")) == 0)
+ {//-- this is NTFS
+ iMaxFileSizeSupported = 0xFFFFFFF0000; //-- max. file size for NTFS
+ }
+ else
+ {//-- theoretically other than FAT & NTFS filesystem are possible.. Figure yourself.
+ } }
+ }
+
+
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Try remount this volume. Checks if the volume parameters remained the same as on original MountL() call, and
+ if they are, re-initialises the mount.
+ @return KErrNone if the remount was OK
+ system-wide error code otherwise
+*/
+TInt CLocalMountCB::ReMount()
+ {
+
+ TInt d=Drive().DriveNumber();
+ TUint uniqueID;
+ TInt r=GetVolumeId(d,uniqueID);
+ if (r==KErrNone && uniqueID!=iUniqueID)
+ r=KErrGeneral;
+ return(r);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+void CLocalMountCB::Dismounted()
+ {
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Return the volume info.
+//
+void CLocalMountCB::VolumeL(TVolumeInfo& aVolume) const
+ {
+
+ TInt64 s,f;
+ TInt driveNum=Drive().DriveNumber();
+ User::LeaveIfError(GetMediaSize(driveNum,s,f));
+ if (driveNum==EDriveZ)
+ aVolume.iFree=0;
+ else
+ aVolume.iFree=f;
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Set the volume label. Not supported on Win32 volumes
+//
+void CLocalMountCB::SetVolumeL(TDes&)
+ {
+
+ User::Leave(IsRomDrive() ? KErrAccessDenied : KErrNotSupported);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Return the address of the file if it is in rom
+//
+void CLocalMountCB::IsFileInRom(const TDesC& aName,TUint8*& aFileStart)
+ {
+
+ aFileStart=NULL;
+ if (!IsRomDrive())
+ return;
+
+ TFileName n;
+ if (MapFileName(n,Drive().DriveNumber(),aName)!=KErrNone)
+ return;
+
+ DWORD access=GENERIC_READ;
+ DWORD share=FILE_SHARE_WRITE|FILE_SHARE_READ;
+ DWORD create=OPEN_EXISTING;
+ HANDLE h=Emulator::CreateFile((LPCTSTR)n.PtrZ(),access,share,NULL,create,FILE_FLAG_RANDOM_ACCESS,NULL);
+ if (h==INVALID_HANDLE_VALUE)
+ return;
+
+ CLocalFileCB::RomAddress(aName, h, aFileStart);
+ CloseHandle(h);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Make a directory.
+ @param aName full path to the directory to create. Name validity is checked by file server.
+*/
+void CLocalMountCB::MkDirL(const TDesC& aName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ BOOL b=Emulator::CreateDirectory(StrPtrZL(n),NULL);
+
+ if (b)
+ return;
+ TInt r=Emulator::LastError();
+ if (r!=KErrAlreadyExists)
+ User::Leave(r);
+ TEntry e;
+ EntryL(aName,e);
+
+ if (e.IsDir())
+ User::Leave(KErrAlreadyExists);
+ else
+ User::Leave(KErrAccessDenied);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Remove a directory.
+ @param aName directory name
+*/
+void CLocalMountCB::RmDirL(const TDesC& aName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ BOOL b=Emulator::RemoveDirectory(StrPtrZL(n));
+
+ if (!b)
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Delete a file.
+//
+void CLocalMountCB::DeleteL(const TDesC& aName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ BOOL b=Emulator::DeleteFile(StrPtrZL(n));
+
+ if (!b)
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Rename a file or directory.
+//
+void CLocalMountCB::RenameL(const TDesC& aOldName,const TDesC& aNewName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TEntry entry;
+ TRAPD(r,EntryL(aNewName,entry));
+ if (r!=KErrNone && r!=KErrNotFound)
+ User::Leave(r);
+ TFileName old;
+ MapFileNameL(old,Drive().DriveNumber(),aOldName);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aNewName);
+ BOOL b=Emulator::MoveFile(StrPtrZL(old),StrPtrZL(n));
+
+ if (!b)
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+void CLocalMountCB::ReplaceL(const TDesC& aOldName,const TDesC& aNewName)
+//
+// Delete aNewName if it exists and rename anOldName.
+//
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TEntry entry;
+ if(FileNamesIdentical(aOldName,aNewName))
+ {
+ return;
+ }
+ TRAPD(r,DeleteL(aNewName));
+ if (r!=KErrNotFound && r!=KErrNone)
+ User::Leave(r);
+ TFileName old;
+ MapFileNameL(old,Drive().DriveNumber(),aOldName);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aNewName);
+ BOOL b=Emulator::MoveFile(StrPtrZL(old),StrPtrZL(n));
+ if (!b)
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Set and get file pointer for windows files
+//
+static DWORD SetFilePointerL(HANDLE hFile,LONG lDistanceToMove,DWORD dwMoveMethod)
+
+ {
+ DWORD dwRet;
+
+ dwRet=SetFilePointer(hFile,lDistanceToMove,0,dwMoveMethod);
+ if (dwRet==KInvalidSetFilePointer) // INVALID_HANDLE_VALUE
+ User::Leave(Emulator::LastError());
+
+ return (dwRet);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Set and get file pointer for windows files
+//
+static DWORD SetFilePointer64L(HANDLE hFile, LARGE_INTEGER * lpDistanceToMove, DWORD dwMoveMethod)
+ {
+
+ DWORD dwRet;
+
+ dwRet=SetFilePointer(hFile, lpDistanceToMove->LowPart, &(lpDistanceToMove->HighPart), dwMoveMethod);
+
+ TInt r = Emulator::LastError();
+ if ((KInvalidSetFilePointer==dwRet) && (r != NO_ERROR))
+ User::Leave(r);
+
+ return (dwRet);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Read file section without opening this file on a file server side.
+
+ @param aName file name; all trailing dots from the name will be removed
+ @param aFilePos start read position within a file
+ @param aLength how many bytes to read; on return will be how many bytes actually read
+ @param aDes local buffer desctriptor
+ @param aMessage from file server, used to write data to the buffer in different address space.
+
+ @leave on media read error
+*/
+void CLocalMountCB::ReadSectionL(const TDesC& aName,TInt aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
+ {
+
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+
+ WIN32_FIND_DATA d;
+ HANDLE hFile=Emulator::FindFirstFile(StrPtrZL(n),&d);
+ if (hFile==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ FOREVER
+ {
+ TPtrC fileName((TText*)(&d.cFileName[0]));
+ if (fileName!=_L(".") && fileName!=_L(".."))
+ break;
+ if (!Emulator::FindNextFile(hFile,&d))
+ {
+ TInt r = Emulator::LastError();
+ User::Leave(r == KErrEof ? KErrNotFound : r);
+ }
+ }
+
+ FindClose(hFile);
+
+ hFile=Emulator::CreateFile(StrPtrZL(n),GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+ if (hFile==INVALID_HANDLE_VALUE)
+ return;
+
+ DWORD dwSizeLow, dwSizeHigh;
+ dwSizeLow=GetFileSize(hFile,&dwSizeHigh);
+ TInt r = Emulator::LastError();
+ if((NO_ERROR != r) && (INVALID_FILE_SIZE == dwSizeLow))
+ User::Leave(r);
+
+ // ReadSectionL can support only upto 2G as aPos is TInt!
+ const TInt64 fileSize = MAKE_TINT64(dwSizeHigh, dwSizeHigh);
+ if(fileSize > KMaxTInt)
+ {
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+
+ User::Leave(KErrTooBig);
+ }
+
+// Check that reading from aPos for aLength lies within the file
+// if aPos is within the file, and aLength is too long, read up to EOF
+// If aPos is beyond the file, return a zero length descriptor
+
+ if ((TInt)dwSizeLow>=(aPos+aLength)) // Can read entire length requested from aPos
+ SetFilePointerL(hFile,aPos,FILE_BEGIN);
+
+ else if ((TInt)dwSizeLow>aPos) // Can read from aPos but not entire length requested
+ {
+ SetFilePointerL(hFile,aPos,FILE_BEGIN);
+ aLength=dwSizeLow-aPos;
+ }
+ else // Cannot read from aPos because it lies outside file
+ { // Close file and leave with KErrEof
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+
+ User::Leave(KErrEof);
+ }
+
+ TBuf8<0x1000> buf;
+ TInt pos=0;
+
+ if (aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aTrg)->SetLength(0);
+
+ while (aLength)
+ {
+ TInt readTotal=Min(aLength,buf.MaxLength());
+ DWORD ret;
+ BOOL b=ReadFile(hFile,(TAny*)buf.Ptr(),readTotal,&ret,NULL);
+ if (!b || ((TInt)ret!=readTotal))
+ User::Leave(Emulator::LastError());
+ buf.SetLength(ret);
+
+ if(aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aTrg)->Append(buf);
+ else
+ aMessage.WriteL(0,buf,pos);
+
+ pos+=ret;
+ if (((TInt)ret)<readTotal)
+ break;
+ aLength-=readTotal;
+ }
+
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+ }
+
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Read the entry uid if present
+//
+void CLocalMountCB::ReadUidL(const TDesC& aName,TEntry& anEntry) const
+ {
+
+// First check to see if the first sixteen bytes form a valid UID
+ TBuf<KMaxFileName + 1> fileName=aName;
+ HANDLE hFile=Emulator::CreateFile(StrPtrZL(fileName),GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+ if (hFile==INVALID_HANDLE_VALUE)
+ return;
+ DWORD ret;
+ TBuf8<sizeof(TCheckedUid)> checkedUidBuf;
+ checkedUidBuf.SetLength(sizeof(TCheckedUid));
+ ReadFile(hFile,&checkedUidBuf[0],sizeof(TCheckedUid),&ret,NULL);
+ if (ret!=sizeof(TCheckedUid))
+ goto close;
+ {
+ TCheckedUid checkedUid(checkedUidBuf);
+ if(checkedUid.UidType()!=TUidType(TUid::Null(),TUid::Null(),TUid::Null()))
+ {
+ anEntry.iType=checkedUid.UidType();
+ goto close;
+ }
+ }
+
+//Look at PE file for UID section
+ {
+ const TInt KPeHeaderAddrAddr=0x3c;
+ const TInt KPeHeaderAddrSize=0x01;
+ const TInt KNumberOfSectionsOffset=0x06;
+ const TInt KNumberOfSectionsSize=0x02;
+ const TInt KSectionTableOffset=0xf8;
+ const TInt KSectionHeaderSize=0x28;
+ const TInt KSectionNameLength=0x08;
+ const TInt KPtrToRawDataOffset=0x14;
+ const TInt KPtrToRawDataSize=0x04;
+ const TText8 peText[4]={'P','E',0,0};
+ const TText8 uidText[8]={'.','S','Y','M','B','I','A','N'};
+
+ //Read address of start of PE header
+ if (SetFilePointer(hFile,KPeHeaderAddrAddr,0,FILE_BEGIN)==KInvalidSetFilePointer)
+ goto close;
+ TInt peAddr=0;
+ ReadFile(hFile,&peAddr,KPeHeaderAddrSize,&ret,NULL);
+ if (ret!=KPeHeaderAddrSize)
+ goto close;
+
+ //Check it really is the start of PE header
+ if (SetFilePointer(hFile,peAddr,0,FILE_BEGIN)==KInvalidSetFilePointer)
+ goto close;
+ TText8 text[4];
+ ReadFile(hFile,text,4,&ret,NULL);
+ if (*(TInt32*)text!=*(TInt32*)peText)
+ goto close;
+
+ //Read number of sections
+ if (SetFilePointer(hFile,peAddr+KNumberOfSectionsOffset,0,FILE_BEGIN)==KInvalidSetFilePointer)
+ goto close;
+ TInt sections=0;
+ ReadFile(hFile,§ions,KNumberOfSectionsSize,&ret,NULL);
+ if (ret!=KNumberOfSectionsSize)
+ goto close;
+
+ //Go through section headers looking for UID section
+ if (SetFilePointer(hFile,peAddr+KSectionTableOffset,0,FILE_BEGIN)==KInvalidSetFilePointer)
+ goto close;
+ TInt i=0;
+ for(;i<sections;i++)
+ {
+ TText8 name[KSectionNameLength];
+ ReadFile(hFile,name,KSectionNameLength,&ret,NULL);
+ if (ret!=KSectionNameLength)
+ goto close;
+ if (*(TInt64*)name==*(TInt64*)uidText)
+ break;
+ if (SetFilePointer(hFile,KSectionHeaderSize-KSectionNameLength,0,FILE_CURRENT)==KInvalidSetFilePointer)
+ goto close;
+ }
+ if (i==sections)
+ goto close;
+
+ //Read RVA/Offset
+ if (SetFilePointer(hFile,KPtrToRawDataOffset-KSectionNameLength,0,FILE_CURRENT)==KInvalidSetFilePointer)
+ goto close;
+ TInt uidOffset;
+ ReadFile(hFile,&uidOffset,KPtrToRawDataSize,&ret,NULL);
+ if (ret!=KPtrToRawDataSize)
+ goto close;
+
+ //Read UIDs!
+ if (SetFilePointer(hFile,uidOffset,0,FILE_BEGIN)==KInvalidSetFilePointer)
+ User::Leave(KErrGeneral);
+
+ TEmulatorImageHeader header;
+ ReadFile(hFile,&header,sizeof(header),&ret,NULL);
+ if (ret==sizeof(header))
+ anEntry.iType=*(TUidType*)&header;
+ }
+//Close file
+close:
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Try to find a directory entry by the given name and path.
+ This method _must_ leave if the entry is not found. See the caller.
+
+ @param aName path to the directory object. all trailing dots from the name will be removed.
+ @param anEntry on return will contain the entry data
+
+ @leave KErrPathNotFound if there is no path to the aName
+ KErrNotFound if the entry corresponding to the aName is not found
+ system-wide erorr code of media read failure.
+*/
+void CLocalMountCB::EntryL(const TDesC& aName,TEntry& anEntry) const
+ {
+
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ WIN32_FIND_DATA d;
+ HANDLE h=Emulator::FindFirstFile(StrPtrZL(n),&d);
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ FOREVER
+ {
+ TPtrC fileName((TText*)(&d.cFileName[0]));
+ if (fileName!=_L(".") && fileName!=_L(".."))
+ break;
+ if (!Emulator::FindNextFile(h,&d))
+ {
+ TInt r = Emulator::LastError();
+ User::Leave(r == KErrEof ? KErrNotFound : r);
+ }
+ }
+ FindClose(h);
+ anEntry.iName.Des()=(TText*)(&d.cFileName[0]);
+ anEntry.iAtt=d.dwFileAttributes&KEntryAttMaskSupported;
+ if (IsRomDrive())
+ anEntry.iAtt|=KEntryAttReadOnly;
+
+ anEntry.SetFileSize(MAKE_TINT64(d.nFileSizeHigh,d.nFileSizeLow));
+
+ fileTimeToTime(&d.ftLastWriteTime,anEntry.iModified);
+ ReadUidL(n,anEntry);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Set directory entry details.
+ @param aName entry name; all trailing dots from the name will be removed
+ @param aTime entry modification time (and last access as well)
+ @param aSetAttMask entry attributes OR mask
+ @param aClearAttMask entry attributes AND mask
+
+*/
+void CLocalMountCB::SetEntryL(const TDesC& aName,const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ TUint setAttMask=aSetAttMask&KEntryAttMaskSupported;
+ DWORD att=Emulator::GetFileAttributes(StrPtrZL(n));
+ if (att==0xffffffffu)
+ User::Leave(Emulator::LastError());
+
+ if (setAttMask|aClearAttMask)
+ {
+ att|=setAttMask;
+ att&=(~aClearAttMask);
+ if (!Emulator::SetFileAttributes((LPCTSTR)n.Ptr(),att))
+ User::Leave(Emulator::LastError());
+ }
+
+ if (aSetAttMask&KEntryAttModified)
+ {
+ FILETIME f;
+ timeToFileTimeL(aTime,&f);
+
+ if (att&KEntryAttReadOnly)
+ {
+ DWORD writeableAtt=att&(~KEntryAttReadOnly);
+ if (!Emulator::SetFileAttributes((LPCTSTR)n.Ptr(),writeableAtt))
+ User::Leave(Emulator::LastError());
+ }
+
+ HANDLE h;
+ if (att&KEntryAttDir)
+ {
+ h=Emulator::CreateFile((LPCTSTR)n.Ptr(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_DIRECTORY|FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ }
+ else
+ {
+ h=Emulator::CreateFile((LPCTSTR)n.Ptr(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ }
+
+ if (!SetFileTime(h,NULL,&f,&f))
+ {
+ TInt error = Emulator::LastError();
+ CloseHandle(h);
+ User::Leave(error);
+ }
+
+ if (!CloseHandle(h))
+ User::Leave(Emulator::LastError());
+
+ if ((att&KEntryAttReadOnly) && !Emulator::SetFileAttributes((LPCTSTR)n.Ptr(),att))
+ User::Leave(Emulator::LastError());
+ }
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Open/Create/Replace a file on the current mount.
+
+ @param aName file name; all trailing dots from the name will be removed
+ @param aMode File open mode, See TFileMode
+ @param anOpen specifies action: open, create or replace the file
+ @param aFile pointer to the CFileCB object to populate
+
+*/
+void CLocalMountCB::FileOpenL(const TDesC& aName,TUint aMode,TFileOpen anOpen,CFileCB* aFile)
+ {
+
+ if (IsRomDrive() && (anOpen!=EFileOpen || (aMode&EFileWrite)))
+ User::Leave(KErrAccessDenied);
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+
+ DWORD access=GENERIC_READ|GENERIC_WRITE;
+ DWORD share=FILE_SHARE_WRITE|FILE_SHARE_READ;
+ DWORD create=0;
+ switch (anOpen)
+ {
+ case EFileOpen: create=OPEN_EXISTING; break;
+ case EFileCreate: create=CREATE_NEW; break;
+ case EFileReplace: create=CREATE_ALWAYS; break;
+ }
+
+ HANDLE h=Emulator::CreateFile(StrPtrZL(n),access,share,NULL,create,FILE_FLAG_RANDOM_ACCESS,NULL);
+
+ if((h==INVALID_HANDLE_VALUE) && !(aMode&EFileWrite))
+ {
+ // If windows will not allow write access and it was not requested then open for read only
+ access=GENERIC_READ;
+ h=Emulator::CreateFile(StrPtrZL(n),access,share,NULL,create,FILE_FLAG_RANDOM_ACCESS,NULL);
+ }
+
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ CLocalFileCB& file=(*((CLocalFileCB*)aFile));
+ file.SetHandle(h);
+
+ BY_HANDLE_FILE_INFORMATION info;
+ if (!GetFileInformationByHandle(h,&info))
+ User::Leave(Emulator::LastError());
+
+ const TUint64 fileSize = MAKE_TUINT64(info.nFileSizeHigh, info.nFileSizeLow);
+
+ // Check on file size
+ if(MaxFileSizeSupported() < fileSize)
+ User::Leave(KErrTooBig);
+
+ file.SetMaxSupportedSize(MaxFileSizeSupported());
+ file.SetSize64(fileSize, EFalse);
+ file.SetAtt(info.dwFileAttributes&KEntryAttMaskSupported);
+
+// if (IsRomDrive())
+// file.iAtt|=KEntryAttReadOnly;
+ TTime tempTime=file.Modified();
+ fileTimeToTime(&info.ftLastWriteTime,tempTime);
+ file.SetModified(tempTime);
+ }
+
+void AppendAsteriskL(TDes& aDes)
+ {
+ if (aDes.Length()==aDes.MaxLength())
+ User::Leave(KErrBadName);
+ aDes.Append('*');
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Open a directory on the current mount.
+
+ @param aName path to the object in the directory we want to open; all trailing dots from the name will be removed
+ @param aDir dir. CB to be filled in.
+
+ If there is no such a path, this method must leave with KErrPathNotFound
+
+ @leave KErrPathNotFound if thereis no such path
+ @leave error code on media read fault
+*/
+void CLocalMountCB::DirOpenL(const TDesC& aName,CDirCB* aDir)
+ {
+
+ TFileName n;
+ TParse parse;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+ parse.Set(n,NULL,NULL);
+ n=parse.DriveAndPath();
+ AppendAsteriskL(n);
+ WIN32_FIND_DATA info;
+ HANDLE h=Emulator::FindFirstFile(StrPtrZL(n),&info);
+ if (h==INVALID_HANDLE_VALUE)
+ {
+ TInt error=Emulator::LastError();
+ TParse parser;
+ TInt r=parser.Set(n,NULL,NULL);
+ if (r!=KErrNone)
+ User::Leave(r);
+ if (!parser.IsRoot() || Drive().DriveNumber()!=0 || error!=KErrNotFound)
+ User::Leave(error);
+ h=NULL;
+ }
+ CLocalDirCB& dir=(*((CLocalDirCB*)aDir));
+ dir.SetHandle(h);
+ dir.SetPending(ETrue);
+ dir.iEntry.iName.Des()=(TText*)(&info.cFileName[0]);
+ dir.iEntry.iAtt=info.dwFileAttributes&KEntryAttMaskSupported;
+
+ const TInt64 fileSize = MAKE_TINT64(info.nFileSizeHigh,info.nFileSizeLow);
+ dir.iEntry.SetFileSize(fileSize);
+
+ n=parse.FullName();
+ if (parse.NameAndExt().Length()==0)
+ AppendAsteriskL(n);
+ dir.SetFullName(n);
+ fileTimeToTime(&info.ftLastWriteTime,dir.iEntry.iModified);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Read directly from disk
+//
+void CLocalMountCB::RawReadL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aDes*/,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/) const
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Write directly to disk
+//
+void CLocalMountCB::RawWriteL(TInt64 /*aPos*/,TInt /*aLength*/,const TAny* /*aDes*/ ,TInt /*anOffset*/,const RMessagePtr2& /*aMessage*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Get the short name associated with aLongName
+//
+void CLocalMountCB::GetShortNameL(const TDesC& aLongName,TDes& aShortName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrNotSupported);
+
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aLongName);
+ WIN32_FIND_DATA d;
+ HANDLE h=Emulator::FindFirstFile(StrPtrZL(n),&d);
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ FindClose(h);
+ if (d.cAlternateFileName[0]) // we have a dos name too
+ aShortName=(TText*)(&d.cAlternateFileName[0]);
+ else
+ aShortName=(TText*)(&d.cFileName[0]);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Get the short name associated with aLongName
+//
+void CLocalMountCB::GetLongNameL(const TDesC& aShortName,TDes& aLongName)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrNotSupported);
+
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aShortName);
+ WIN32_FIND_DATA d;
+ HANDLE h=Emulator::FindFirstFile(StrPtrZL(n),&d);
+ if (h==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+ FindClose(h);
+ aLongName=(TText*)(&d.cFileName[0]);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+Reports whether the specified interface is supported - if it is,
+the supplied interface object is modified to it
+
+@param aInterfaceId The interface of interest
+@param aInterface The interface object
+@return KErrNone if the interface is supported, otherwise KErrNotFound
+
+@see CMountCB::GetInterface()
+*/
+TInt CLocalMountCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
+ {
+ switch(aInterfaceId)
+ {
+ case EFileExtendedInterface:
+ ((CMountCB::MFileExtendedInterface*&) aInterface) = this;
+ return KErrNone;
+
+ case ELocalBufferSupport:
+ // CLocalMountCB doesn't ever use any extensions?
+ // - seems to not have any iProxyDrive or LocalDrive() or similar,
+ // so we'll just return KErrNone here.
+ return KErrNone;
+
+ default:
+ return CMountCB::GetInterface(aInterfaceId,aInterface,aInput);
+ }
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+TInt CLocalMountCB::LocalBufferSupport()
+ {
+ TAny* dummyInterface = NULL;
+ TAny* dummyInput = NULL;
+ return GetInterface(ELocalBufferSupport,dummyInterface,dummyInput);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Read file section without opening this file on a file server side.
+
+ @param aName file name; all trailing dots from the name will be removed
+ @param aFilePos start read position within a file
+ @param aLength how many bytes to read; on return will be how many bytes actually read
+ @param aDes local buffer desctriptor
+ @param aMessage from file server, used to write data to the buffer in different address space.
+
+ @leave on media read error
+*/
+void CLocalMountCB::ReadSection64L(const TDesC& aName, TInt64 aPos, TAny* aTrg, TInt aLength, const RMessagePtr2& aMessage)
+ {
+ TFileName n;
+ MapFileNameL(n,Drive().DriveNumber(),aName);
+
+ WIN32_FIND_DATA d;
+ HANDLE hFile=Emulator::FindFirstFile(StrPtrZL(n),&d);
+ if (hFile==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+
+ FOREVER
+ {
+ TPtrC fileName((TText*)(&d.cFileName[0]));
+ if (fileName!=_L(".") && fileName!=_L(".."))
+ break;
+ if (!Emulator::FindNextFile(hFile,&d))
+ {
+ TInt r = Emulator::LastError();
+ User::Leave(r == KErrEof ? KErrNotFound : r);
+ }
+ }
+
+ FindClose(hFile);
+
+ hFile=Emulator::CreateFile(StrPtrZL(n),GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+ if (hFile==INVALID_HANDLE_VALUE)
+ return;
+
+ DWORD dwSizeLow, dwSizeHigh;
+ dwSizeLow=GetFileSize(hFile,&dwSizeHigh);
+ TInt r = Emulator::LastError();
+ if((NO_ERROR != r) && (INVALID_FILE_SIZE == dwSizeLow))
+ User::Leave(r);
+
+ // Check on file size
+ const TInt64 fileSize = MAKE_TINT64(dwSizeHigh, dwSizeLow);
+ if(MaxFileSizeSupported() < (TUint64)fileSize)
+ {
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+
+ User::Leave(KErrTooBig);
+ }
+
+// Check that reading from aPos for aLength lies within the file
+// if aPos is within the file, and aLength is too long, read up to EOF
+// If aPos is beyond the file, return a zero length descriptor
+
+ if (fileSize>=aPos+aLength) // Can read entire length requested from aPos
+ SetFilePointer64L(hFile,(LARGE_INTEGER *)&aPos,FILE_BEGIN);
+
+ else if (fileSize>aPos) // Can read from aPos but not entire length requested
+ {
+ SetFilePointer64L(hFile,(LARGE_INTEGER *)&aPos,FILE_BEGIN);
+ aLength=(TInt)(fileSize-aPos);
+ }
+ else // Cannot read from aPos because it lies outside file
+ { // Close file and leave with KErrEof
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+
+ User::Leave(KErrEof);
+ }
+
+ TBuf8<0x1000> buf;
+ TInt pos=0;
+
+ if (aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aTrg)->SetLength(0);
+
+ while (aLength)
+ {
+ TInt readTotal=Min(aLength,buf.MaxLength());
+ DWORD ret;
+ BOOL b=ReadFile(hFile,(TAny*)buf.Ptr(),readTotal,&ret,NULL);
+ if (!b || ((TInt)ret!=readTotal))
+ User::Leave(Emulator::LastError());
+ buf.SetLength(ret);
+
+ if(aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aTrg)->Append(buf);
+ else
+ aMessage.WriteL(0,buf,pos);
+
+ pos+=ret;
+ if (((TInt)ret)<readTotal)
+ break;
+ aLength-=readTotal;
+ }
+
+ if (!CloseHandle(hFile))
+ User::Leave(Emulator::LastError());
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+
+/**
+ CLocalMountCB control method.
+ @param aLevel specifies the operation to perfrom on the mount
+ @param aOption specific option for the given operation
+ @param aParam pointer to generic parameter, its meaning depends on aLevel and aOption
+
+ @return standard error code.
+*/
+
+TInt CLocalMountCB::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
+ {
+ //-- File System - specific queries
+ if(aLevel == EMountFsParamQuery && aOption == ESQ_GetMaxSupportedFileSize)
+ {//-- this is a query to provide the max. supported file size; aParam is a pointer to TUint64 to return the value
+ *(TUint64*)aParam = MaxFileSizeSupported();
+ return KErrNone;
+ }
+
+ return KErrNotSupported;
+ }
+
+//#########################################################################################################################
+//## CLocalFileCB class implementation
+//#########################################################################################################################
+
+
+CLocalFileCB::CLocalFileCB()
+ {
+ }
+
+CLocalFileCB::~CLocalFileCB()
+ {
+
+ if (iAtt&KEntryAttModified)
+ {
+ TRAPD(ret,FlushDataL());
+// if (ret!=KErrNone) // Can fail if floppy disk is removed
+// Panic(EFileClose); // Ignore error
+ }
+ if (iWinHandle!=NULL && !CloseHandle(iWinHandle))
+ Panic(EFileClose);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Returns ETrue if the drive number == EDriveZ
+//
+TBool CLocalFileCB::IsRomDrive() const
+ {
+
+ // WINS emulated rom drive is Z:
+ return(((CLocalFileCB*)this)->Mount().Drive().DriveNumber()==EDriveZ);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Check that the file pointer iCurrentPos is positioned correctly
+// in relation to the Win32 file pointer
+//
+void CLocalFileCB::CheckPosL(TInt64 aPos)
+ {
+// Get the current Win32 file pointer position
+ LARGE_INTEGER pos;
+ pos.QuadPart = 0;
+ DWORD position=SetFilePointer(iWinHandle,pos.LowPart,&pos.HighPart,FILE_CURRENT);
+ TInt r = Emulator::LastError();
+ if ((KInvalidSetFilePointer == position) && (r != NO_ERROR))
+ User::Leave(r);
+// Set iCurrentPos and Win32 file pointers to aPos if they are different to each
+// other or different to aPos
+ if ((pos.QuadPart!=iCurrentPos) || (iCurrentPos!=aPos))
+ {
+ iCurrentPos=(-1);
+ pos.QuadPart = aPos;
+ position = SetFilePointer(iWinHandle,pos.LowPart,&pos.HighPart,FILE_BEGIN);
+ r = Emulator::LastError();
+ if ((KInvalidSetFilePointer == position) && (r != NO_ERROR))
+ User::Leave(r);
+ iCurrentPos=aPos;
+ }
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+void CLocalFileCB::ReadL(TInt aPos,TInt& aLength,const TAny* aDes,const RMessagePtr2& aMessage)
+ {
+ ReadL((TInt64)aPos, aLength, (TDes8*)aDes, aMessage, 0);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+void CLocalFileCB::WriteL(TInt aPos,TInt& aLength,const TAny* aDes,const RMessagePtr2& aMessage)
+ {
+ WriteL((TInt64)aPos, aLength, (TDesC8*)aDes, aMessage, 0);
+ }
+
+struct SRomMap
+ {
+ HBufC* iName;
+ TUint8* iAddr;
+ };
+//-------------------------------------------------------------------------------------------------------------------
+
+TInt CLocalFileCB::RomAddress(const TDesC& aName, HANDLE aFile, TUint8*& aAddr)
+ {
+ static CArrayFixSeg<SRomMap>* gRomMap = new CArrayFixSeg<SRomMap>(64);
+ for (TInt ii=0; ii<gRomMap->Count(); ii++)
+ {
+ if (*gRomMap->At(ii).iName == aName)
+ {
+ aAddr = gRomMap->At(ii).iAddr;
+ return KErrNone;
+ }
+ }
+
+ HANDLE fileMapping=CreateFileMappingA(aFile,NULL,PAGE_READONLY,0,0,NULL);
+ if (fileMapping==0)
+ return Emulator::LastError();
+ aAddr=(TUint8*)MapViewOfFile(fileMapping,FILE_MAP_READ,0,0,0);
+ SRomMap entry;
+ entry.iAddr = aAddr;
+ entry.iName = aName.Alloc();
+ if (entry.iName)
+ {
+ TRAPD(ignore, gRomMap->AppendL(entry));
+ }
+ return KErrNone;
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// If ROM file, do a memory map and return the address
+//
+TInt CLocalFileCB::Address(TInt& aPos) const
+ {
+
+ TBool isRomFile=IsRomDrive();
+ if (!isRomFile)
+ return(KErrNotSupported);
+
+ if (aPos>Size64())
+ return(KErrEof);
+ if (iFilePtr==NULL)
+ {
+ CLocalFileCB* This=(CLocalFileCB*)this;
+ TInt err = RomAddress(*iFileName, iWinHandle, This->iFilePtr);
+ if (err)
+ return err;
+ }
+ aPos=(TInt)((TUint8*)iFilePtr+aPos);
+ return(KErrNone);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Set the file size.
+//
+void CLocalFileCB::SetSizeL(TInt aSize)
+ {
+ SetSizeL(aSize);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Set the entry's attributes and modified time.
+//
+void CLocalFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
+ {
+
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+ TUint setAttMask=aSetAttMask&KEntryAttMaskSupported;
+ if (setAttMask|aClearAttMask)
+ {
+ iAtt|=setAttMask;
+ iAtt&=(~aClearAttMask);
+ iAtt|=KEntryAttModified;
+ }
+ if (aSetAttMask&KEntryAttModified)
+ iModified=aTime;
+ iAtt|=KEntryAttModified;
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Commit any buffered date to the media.
+//
+void CLocalFileCB::FlushAllL()
+ {
+ FlushDataL();
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Commit any buffered date to the media.
+//
+void CLocalFileCB::FlushDataL()
+ {
+
+ if (IsRomDrive())
+ return;
+
+ TFileName n;
+ TInt driveNumber=Mount().Drive().DriveNumber();
+ MapFileNameL(n,driveNumber,FileName());
+
+ if(!Emulator::SetFileAttributes(StrPtrZL(n),iAtt&KEntryAttMaskSupported))
+ User::Leave(Emulator::LastError()); // Panic(EFileCloseSetAttributes);
+ FILETIME f;
+ timeToFileTimeL(iModified,&f);
+ if (!SetFileTime(iWinHandle,&f,&f,&f))
+ User::Leave(Emulator::LastError());
+
+ iAtt&=(~KEntryAttModified);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+//
+// Rename the file while open
+//
+void CLocalFileCB::RenameL(const TDesC& aNewName)
+ {
+
+ TInt driveNumber=Mount().Drive().DriveNumber();
+
+ TFileName n1;
+ MapFileNameL(n1,driveNumber,FileName());
+ TFileName n2;
+ MapFileNameL(n2,driveNumber,aNewName);
+
+ CloseHandle(iWinHandle);
+ TInt ret=KErrNone;
+ if (!Emulator::MoveFile(StrPtrZL(n1),StrPtrZL(n2)))
+ {
+ ret=Emulator::LastError();
+ n2=n1;
+ }
+ DWORD access=GENERIC_READ|GENERIC_WRITE;
+ DWORD share=FILE_SHARE_WRITE|FILE_SHARE_READ;
+ DWORD create=OPEN_EXISTING;
+ iWinHandle=Emulator::CreateFile(StrPtrZL(n2),access,share,NULL,create,FILE_FLAG_RANDOM_ACCESS,NULL);
+ if (iWinHandle==INVALID_HANDLE_VALUE)
+ User::Leave(Emulator::LastError());
+
+ LARGE_INTEGER pos;
+ pos.QuadPart = iCurrentPos;
+ DWORD position = SetFilePointer(iWinHandle,pos.LowPart,&pos.HighPart,FILE_BEGIN);
+ TInt r = Emulator::LastError();
+ if ((KInvalidSetFilePointer == position) && (r != NO_ERROR))
+ User::Leave(r);
+
+ User::LeaveIfError(ret);
+ AllocBufferL(iFileName,aNewName);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+TInt CLocalFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
+ {
+ switch(aInterfaceId)
+ {
+ case EExtendedFileInterface:
+ ((CFileCB::MExtendedFileInterface*&) aInterface) = this;
+ return KErrNone;
+
+ default:
+ return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
+ }
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Read data from the file.
+
+ @param aFilePos start read position within a file
+ @param aLength how many bytes to read; on return will be how many bytes actually read
+ @param aDes local buffer desctriptor
+ @param aMessage from file server, used to write data to the buffer in different address space.
+ @param aDesOffset offset within data descriptor where the data will be copied
+
+ @leave on media read error
+
+*/
+void CLocalFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+ {
+
+ const TUint64 KMaxFilePosition = LocalMount().MaxFileSizeSupported()-1;
+
+
+ if(KMaxFilePosition < (TUint64)aPos)
+ User::Leave(KErrNotSupported);
+
+ CheckPosL(aPos);
+ TInt pos=0;
+ TInt len=aLength;
+ TBuf8<0x1000> buf;
+
+ if (aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aDes)->SetLength(0);
+
+ while (len)
+ {
+ TInt s=Min(len,buf.MaxLength());
+ DWORD res;
+ BOOL b=ReadFile(iWinHandle,(TAny*)buf.Ptr(),s,&res,NULL);
+ if(!b)
+ User::Leave(Emulator::LastError());
+
+ buf.SetLength(res);
+
+ if (aMessage.Handle() == KLocalMessageHandle)
+ ((TPtr8* )aDes)->Append(buf);
+ else
+ aMessage.WriteL(0,buf,pos + aOffset);
+
+ pos+=res;
+ if (((TInt)res)<s)
+ break;
+ len-=s;
+ }
+ TInt delay = (ReadSpeed * aLength) >> 10;
+ if (delay)
+ User::AfterHighRes(delay);
+ aLength=pos;
+ iCurrentPos=aPos+pos;
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Write data to the file.
+
+ @param aFilePos start write position within a file
+ @param aLength how many bytes to write; on return contain amount of data actually written
+ @param aDes local buffer desctriptor
+ @param aMessage from file server, used to write data to the media from different address space.
+ @param aDesOffset offset within data descriptor
+
+ @leave on media read error
+
+*/
+void CLocalFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
+ {
+ if (IsRomDrive())
+ User::Leave(KErrAccessDenied);
+
+
+ const TUint64 KMaxFileSize = LocalMount().MaxFileSizeSupported();
+ const TUint64 KMaxFilePosition = KMaxFileSize - 1;
+
+ if( KMaxFilePosition < (TUint64)aPos || KMaxFileSize < (TUint64)(aPos + aLength) )
+ User::Leave(KErrNotSupported);
+
+ CheckPosL(aPos);
+ TInt pos=0;
+ TInt len=aLength;
+ TBuf8<0x1000> buf;
+
+ while (len)
+ {
+ TInt s=Min(len,buf.MaxLength());
+
+ if (aMessage.Handle() == KLocalMessageHandle)
+ buf.Copy( ((TPtr8* )aDes)->MidTPtr(pos, s) );
+ else
+ aMessage.ReadL(0,buf,pos + aOffset);
+
+ DWORD res;
+ BOOL b=WriteFile(iWinHandle,buf.Ptr(),s,&res,NULL);
+
+ if (!b)
+ User::Leave(Emulator::LastError());
+
+ if (((TInt)res)<s)
+ User::Leave(KErrCorrupt);
+
+ len-=s;
+ pos+=s;
+ }
+ TInt delay = (WriteSpeed * aLength) >> 10;
+ if (delay)
+ User::AfterHighRes(delay);
+ aLength=pos;
+ iCurrentPos=aPos+pos;
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Set file size.
+ @param aSize new file size.
+*/
+void CLocalFileCB::SetSizeL(TInt64 aSize)
+ {
+ const TUint64 KMaxFileSize = LocalMount().MaxFileSizeSupported();
+
+ if(KMaxFileSize < (TUint64)aSize)
+ User::Leave(KErrNotSupported);
+
+ CheckPosL(aSize);
+ if(!SetEndOfFile(iWinHandle))
+ {
+ iCurrentPos= -1;
+ User::Leave(Emulator::LastError());
+ }
+
+ SetSize64(aSize, EFalse);
+ }
+
+//#########################################################################################################################
+//## CLocalDirCB class implementation
+//#########################################################################################################################
+
+CLocalDirCB::CLocalDirCB()
+ :iEntry()
+ {
+ }
+
+CLocalDirCB::~CLocalDirCB()
+ {
+
+ if (iWinHandle!=NULL && !FindClose(iWinHandle))
+ Panic(EDirClose);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+TBool CLocalDirCB::MatchUid()
+ {
+
+ if (iUidType[0]!=TUid::Null() || iUidType[1]!=TUid::Null() || iUidType[2]!=TUid::Null())
+ return(ETrue);
+
+ return(EFalse);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/** @return ETrue if the aUidTrg matches aUidSuitor */
+static TBool CompareUid(const TUidType& aUidTrg, const TUidType& aUidSuitor)
+ {
+
+ if (aUidTrg[0]!=TUid::Null() && aUidTrg[0]!=aUidSuitor[0])
+ return(EFalse);
+ if (aUidTrg[1]!=TUid::Null() && aUidTrg[1]!=aUidSuitor[1])
+ return(EFalse);
+ if (aUidTrg[2]!=TUid::Null() && aUidTrg[2]!=aUidSuitor[2])
+ return(EFalse);
+ return(ETrue);
+ }
+
+//-------------------------------------------------------------------------------------------------------------------
+/**
+ Read current entry from the directory and move to the next one.
+ This function must leave KErrEof when the end of directory is reached
+
+ @param anEntry extracted directory entry
+ @leave KErrEof when there are no more entries in the directory
+ system-wide error code on media read fault.
+
+*/
+void CLocalDirCB::ReadL(TEntry& anEntry)
+ {
+
+ if (iWinHandle==NULL)
+ User::Leave(KErrEof);
+
+ FOREVER
+ {
+ if (!iPending)
+ {
+ WIN32_FIND_DATA info;
+ if (!Emulator::FindNextFile(iWinHandle,&info))
+ User::Leave(Emulator::LastError());
+
+ iEntry.iName.Des()=(TText*)(&info.cFileName[0]);
+ iEntry.iAtt=info.dwFileAttributes&KEntryAttMaskSupported;
+ iEntry.SetFileSize(MAKE_TINT64(info.nFileSizeHigh,info.nFileSizeLow));
+ fileTimeToTime(&info.ftLastWriteTime,iEntry.iModified);
+ }
+ iPending=EFalse;
+ anEntry=iEntry;
+ if (anEntry.iName==_L(".") || anEntry.iName==_L(".."))
+ continue;
+ if ((iFullName.NameAndExt()==_L("*.*") || iFullName.NameAndExt()==_L("*") || anEntry.iName.MatchF(iFullName.NameAndExt())!=KErrNotFound) && Mount().MatchEntryAtt(anEntry.iAtt&KEntryAttMaskSupported,iAtt))
+ {
+ if (MatchUid())
+ {
+ TParse fileName;
+ TBuf<KMaxFileName> driveAndPath=iFullName.DriveAndPath();
+ fileName.Set(anEntry.iName,&driveAndPath,NULL);
+ (*(CLocalMountCB*)&Mount()).ReadUidL(fileName.FullName(),anEntry);
+ if (CompareUid(iUidType,anEntry.iType))
+ break;
+ }
+ else
+ break;
+ }
+ }
+ if ((iAtt&KEntryAttAllowUid)==0 || anEntry.iAtt&KEntryAttDir || MatchUid())
+ return;
+ TParse fileName;
+ TBuf<KMaxFileName> driveAndPath=iFullName.DriveAndPath();
+ fileName.Set(anEntry.iName,&driveAndPath,NULL);
+ (*(CLocalMountCB*)&Mount()).ReadUidL(fileName.FullName(),anEntry);
+ }
+
+//#########################################################################################################################
+//## CLocalFormatCB class implementation
+//#########################################################################################################################
+
+CLocalFormatCB::CLocalFormatCB()
+ {
+ }
+
+CLocalFormatCB::~CLocalFormatCB()
+ {
+ }
+
+void CLocalFormatCB::DoFormatStepL()
+ {
+ iCurrentStep=0;
+ User::Leave(KErrNotSupported);
+ }
+
+
+//#########################################################################################################################
+//## CLocal File System class implementation
+//#########################################################################################################################
+
+extern "C"
+{
+//
+// Create a new file system
+//
+EXPORT_C CFileSystem* CreateFileSystem()
+ {
+ return(new CLocal);
+ }
+}
+
+CLocal::CLocal()
+ {
+ }
+
+TInt CLocal::Install()
+ {
+
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+ EmulatorDiskSpeed(ReadSpeed, WriteSpeed);
+ iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KF32BuildVersionNumber);
+ _LIT(KWin32Name,"Win32");
+ return(SetName(&KWin32Name));
+ }
+
+CMountCB* CLocal::NewMountL() const
+//
+// Create a new mount control block.
+//
+ {
+
+ return(new(ELeave) CLocalMountCB);
+ }
+
+CFileCB* CLocal::NewFileL() const
+//
+// Create a new file.
+//
+ {
+
+ return(new(ELeave) CLocalFileCB);
+ }
+
+CDirCB* CLocal::NewDirL() const
+//
+// Create a new directory lister.
+//
+ {
+ return(new(ELeave) CLocalDirCB);
+ }
+
+CFormatCB* CLocal::NewFormatL() const
+//
+// Create a new media formatter.
+//
+ {
+ return(new(ELeave) CLocalFormatCB);
+ }
+
+TInt CLocal::DefaultPath(TDes& aPath) const
+//
+// Return the initial default path.
+//
+ {
+ aPath=_L("?:\\");
+ aPath[0] = (TUint8) RFs::GetSystemDriveChar();
+ return(KErrNone);
+ }
+
+void CLocal::DriveInfo(TDriveInfo& anInfo,TInt aDriveNumber) const
+//
+// Return the drive info. iBatteryState already set.
+//
+ {
+
+ anInfo.iMediaAtt=0;
+
+// Get Fake drive info.
+ if (aDriveNumber==EDriveZ)
+ {
+ anInfo.iType=EMediaRom;
+ anInfo.iMediaAtt=KMediaAttWriteProtected;
+ anInfo.iDriveAtt=KDriveAttRom|KDriveAttInternal;
+ return;
+ }
+ if (aDriveNumber==EDriveC)
+ {
+ anInfo.iType=EMediaHardDisk;
+ anInfo.iMediaAtt=KMediaAttVariableSize;
+ anInfo.iDriveAtt=KDriveAttLocal|KDriveAttInternal;
+ return;
+ }
+ TFileName envValue;
+ if (MapDrive(envValue,aDriveNumber))
+ {
+ anInfo.iType=EMediaHardDisk;
+ anInfo.iDriveAtt=KDriveAttLocal|KDriveAttInternal;
+ return;
+ }
+ anInfo.iType=EMediaNotPresent;
+ anInfo.iDriveAtt=0;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+