diff -r 000000000000 -r 96e5fb8b040d userlibandfileserver/fileserver/swins/elocal.cpp --- /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 +#include + +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) 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 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=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)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* gRomMap = new CArrayFixSeg(64); + for (TInt ii=0; iiCount(); 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)> 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)> 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 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 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; + } + + + + + + + + + + + + + + +