diff -r 000000000000 -r a41df078684a kerneltest/f32test/ext/t_rawext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/ext/t_rawext.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,771 @@ +/* +* Copyright (c) 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: +* +*/ +// +// RAWEXT.CPP +// +// This file system extension provides a way to access a drive on the local windows system in "raw format". +// It can be used to test large files / drives +// +// NB This should be used WITH CARE to avoid unintentionally overwriting or formatting a windows disk +// + +#include + +#include + +#include + +#define WIN32_LEAN_AND_MEAN +#pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union + +#include + +// Enable this macro to find the last REMOVABLE drive (e.g. a card reader drive) +// (to minimise the chance of doing any damage ! +// Doesn't even try any drive letters below E (again for safety): +#define __LOOK_FOR_DRIVE__ + +// Otherwise the windows drive letter can be hard-coded here: +#ifndef __LOOK_FOR_DRIVE__ + char diskName[] = "\\\\.\\Y:"; +#endif + + +const TInt KSectorSize = 512; + +class CRawWinDiskExtProxyDrive : public CBaseExtProxyDrive + { +public: + static CRawWinDiskExtProxyDrive* NewL(CProxyDrive* aProxyDrive, CMountCB* aMount); + ~CRawWinDiskExtProxyDrive(); +public: + virtual TInt Initialise(); + virtual TInt Dismounted(); + virtual TInt Enlarge(TInt aLength); + virtual TInt ReduceSize(TInt aPos, TInt aLength); + virtual TInt Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aThreadHandle,TInt anOffset); + virtual TInt Read(TInt64 aPos,TInt aLength,TDes8& aTrg); + virtual TInt Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aThreadHandle,TInt anOffset); + virtual TInt Write(TInt64 aPos,const TDesC8& aSrc); + virtual TInt Caps(TDes8& anInfo); + virtual TInt Format(TFormatInfo& anInfo); +private: + CRawWinDiskExtProxyDrive(CProxyDrive* aProxyDrive, CMountCB* aMount); +private: + HANDLE iDeviceHandle; + }; + +class CRawWinDiskProxyDriveFactory : public CProxyDriveFactory + { +public: + CRawWinDiskProxyDriveFactory(); + virtual TInt Install(); + virtual CProxyDrive* NewProxyDriveL(CProxyDrive* aProxy,CMountCB* aMount); + }; + + + +CRawWinDiskExtProxyDrive* CRawWinDiskExtProxyDrive::NewL(CProxyDrive* aProxyDrive, CMountCB* aMount) +// +// +// + { + CRawWinDiskExtProxyDrive* temp=new(ELeave) CRawWinDiskExtProxyDrive(aProxyDrive,aMount); + return(temp); + } + + +CRawWinDiskExtProxyDrive::CRawWinDiskExtProxyDrive(CProxyDrive* aProxyDrive, CMountCB* aMount):CBaseExtProxyDrive(aProxyDrive,aMount) + { + RDebug::Print(_L("CRawWinDiskExtProxyDrive::CRawWinDiskExtProxyDrive")); + } + +CRawWinDiskExtProxyDrive::~CRawWinDiskExtProxyDrive() +// +// +// + { + CloseHandle(iDeviceHandle); + } + +TInt CRawWinDiskExtProxyDrive::Initialise() +// +// +// + { + RDebug::Print(_L("CRawWinDiskExtProxyDrive::Initialise()")); + + +#ifdef __LOOK_FOR_DRIVE__ + // Find the last REMOVABLE drive (to minimise the chance of doing any damage ! + // Don't even try any drive letters below E (agai for safety): + char diskName[] = "\\\\.\\?:"; + char driveLetter; + for (driveLetter = 'Z'; driveLetter > 'D'; driveLetter--) + { + diskName[4] = driveLetter; + + DISK_GEOMETRY geometry; + DWORD dummy; + + iDeviceHandle = CreateFileA(diskName, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + + if (iDeviceHandle == INVALID_HANDLE_VALUE) + { + continue; + } + + if(DeviceIoControl(iDeviceHandle, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &geometry, + sizeof(geometry), + &dummy, + (LPOVERLAPPED)NULL)) + { + RDebug::Print(_L("Drive %c MediaType %d removable %s"), + driveLetter, + geometry.MediaType, + geometry.MediaType==RemovableMedia ? _S16("True") : _S16("False")); + + } + + CloseHandle(iDeviceHandle); + if (geometry.MediaType==RemovableMedia) + break; + } + if (driveLetter == 'D') + return KErrNotFound; +#endif + + // Creating a handle to drive a: using CreateFile () function .. + TPtrC8 diskName8((const TUint8*) diskName); + TBuf16<16> diskName16; + diskName16.Copy(diskName8); + RDebug::Print(_L("RAWEXT: Opening drive %S"), &diskName16); + + iDeviceHandle = CreateFileA( +// "\\\\.\\H:", + diskName, + GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + + if (iDeviceHandle == INVALID_HANDLE_VALUE) + { + return Emulator::LastError(); + } + + return KErrNone; + } + +TInt CRawWinDiskExtProxyDrive::Dismounted() +// +// +// + { + RDebug::Print(_L("CRawWinDiskExtProxyDrive::Dismounted()")); + return(KErrNone); + } + +TInt CRawWinDiskExtProxyDrive::Enlarge(TInt /*aLength*/) +// +// +// + { + return(KErrNotSupported); + } + + +TInt CRawWinDiskExtProxyDrive::ReduceSize(TInt /*aPos*/, TInt /*aLength*/) +// +// +// + { + return(KErrNotSupported); + } + +LOCAL_C TInt ParameterNum(const TInt aMessageHandle, const TAny* aAddress) + { + RMessage2 tmpMessage(*(RMessagePtr2 *) &aMessageHandle); + + if (tmpMessage.Ptr0() == aAddress) + { + return 0; + } + if (tmpMessage.Ptr1() == aAddress) + { + return 1; + } + if (tmpMessage.Ptr2() == aAddress) + { + return 2; + } + if (tmpMessage.Ptr3() == aAddress) + { + return 3; + } + User::Panic(_L("RAWEXT"),KErrBadHandle); + return -1; + } + + + +TInt CRawWinDiskExtProxyDrive::Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aThreadHandle,TInt aOffset) +// +// +// + { + + // + // Set file position to where we want to read... + // + LARGE_INTEGER li; + li.QuadPart = aPos; + + long posH = I64HIGH(aPos); + long posL = I64LOW(aPos); + + TInt off = posL & 0x1FF; + posL &= ~0x1FF; + + if(SetFilePointer (iDeviceHandle, posL, &posH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + const TInt KLocalBufferSize = 256*1024; + char buffer[KLocalBufferSize]; + + const TInt param = ParameterNum(aThreadHandle, aTrg); + + TInt totalBytesRead = 0; + + // + // Read first sector if start of data is offset from 512 bytes... + // + if(off) + { + // read 1st sector if offset + DWORD bytesRead; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesRead, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesRead != KSectorSize) + { + return KErrNotReady; + } + + bytesRead-= off; + TInt copyLen = Min(aLength, bytesRead);; + + totalBytesRead += copyLen; + aLength -= copyLen; + + TPtrC8 des((TUint8*) buffer+off, copyLen); + ((RMessagePtr2 *) &aThreadHandle)->Write(param, des, aOffset); + } + + // + // Read the remainder of the data, accounting for partial last sector... + // + while(aLength > 0) + { + TUint32 bytesThisTime = min(KLocalBufferSize, (TUint32)aLength); + + bytesThisTime = (bytesThisTime + KSectorSize-1) & ~(KSectorSize-1); + + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, bytesThisTime, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != (TUint32)bytesThisTime) + { + return KErrNotReady; + } + + TPtrC8 des((TUint8*)buffer, min((TUint32)aLength, bytesThisTime)); + ((RMessagePtr2 *) &aThreadHandle)->Write(param, des, aOffset + totalBytesRead); + totalBytesRead += bytesThisTime; + aLength -= bytesThisTime; + } + + return KErrNone; + } + +////// + +GLDEF_C void DumpBuffer( const TDesC8& aBuffer ) + /** + * Dump the content of aBuffer in hex + */ + { + static const TText hextab[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' }; + const TInt KBytesPerLine = 32; + const TInt KCharsPerLine = KBytesPerLine * 2; + + TInt remaining = aBuffer.Length(); + TUint8* pSrc = const_cast(aBuffer.Ptr()); + + TBuf line; + line.SetLength( KCharsPerLine ); // don't need to print trailing space + TInt bytesPerLine = KBytesPerLine; + TInt lineOffs = 0; + while( remaining ) + { + if( remaining < KBytesPerLine ) + { + bytesPerLine = remaining; + line.SetLength( (bytesPerLine*2) ); + } + TUint16* pDest = const_cast(line.Ptr()); + remaining -= bytesPerLine; + for( TInt i = bytesPerLine; i > 0; --i ) + { + TUint8 c = *pSrc++; + *pDest++ = hextab[c >> 4]; + *pDest++ = hextab[c & 0xF]; + } + _LIT( KFmt, "%06x: %S\n\r" ); + RDebug::Print( KFmt, lineOffs, &line ); + lineOffs += bytesPerLine; + } + } + + + +TInt CRawWinDiskExtProxyDrive::Read(TInt64 aPos,TInt aLength,TDes8& aTrg) +// +// +// + { + + // + // Set file position to where we want to read... + // + LARGE_INTEGER li; + li.QuadPart = aPos; + + long posH = I64HIGH(aPos); + long posL = I64LOW(aPos); + + TInt off = posL & 0x1FF; + posL &= ~0x1FF; + + if(SetFilePointer (iDeviceHandle, posL, &posH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + const TInt KLocalBufferSize = 256*1024; + char buffer[KLocalBufferSize]; + + TInt totalBytesRead = 0; + + aTrg.SetLength(aLength); + + // + // Read first sector if start of data is offset from 512 bytes... + // + if(off) + { + // read 1st sector if offset + DWORD bytesRead; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesRead, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesRead != KSectorSize) + { + return KErrNotReady; + } + + bytesRead-= off; + TInt copyLen = Min(aLength, bytesRead);; + + totalBytesRead += copyLen; + aLength -= copyLen; + + memcpy(&aTrg[0], &buffer[off], copyLen); + } + + // + // Read the remainder of the data, accounting for partial last sector... + // + while(aLength > 0) + { + TInt bytesThisTime = (aLength > KLocalBufferSize) ? KLocalBufferSize : aLength; + + bytesThisTime = (bytesThisTime + KSectorSize-1) & ~(KSectorSize-1); + + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, bytesThisTime, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != (TUint32)bytesThisTime) + return KErrNotReady; + + TInt copyLen = aLength < bytesThisTime ? aLength : bytesThisTime; + + memcpy(&aTrg[totalBytesRead], buffer, copyLen); + + totalBytesRead += bytesThisTime; + aLength -= bytesThisTime; + } + +// DumpBuffer(aTrg); + + return KErrNone; + } + +TInt CRawWinDiskExtProxyDrive::Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aThreadHandle,TInt aOffset) +// +// +// + { + // + // Set file position to where we want to write... + // + long posStartH = I64HIGH(aPos); + long posStartL = I64LOW(aPos); + + TInt offStart = posStartL & 0x1FF; + posStartL &= ~0x1FF; + + if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + const TInt KLocalBufferSize = 256*1024; + char buffer[KLocalBufferSize]; + + const TInt param = ParameterNum(aThreadHandle, aSrc); + + TInt totalBytesRead = 0; + + // + // Read-Modify-Write on first sector if start of data is offset from 512 bytes + // or if this is a partial write... + // + if(offStart || aLength < KSectorSize) + { + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != KSectorSize) + { + return KErrNotReady; + } + + totalBytesRead = min(KSectorSize-offStart, aLength); + aLength -= totalBytesRead; + + TPtr8 des((TUint8*)&buffer[offStart], totalBytesRead); + ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset); + + if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + } + + // + // Write the remainder of the aligned data + // + while(aLength >= KSectorSize) + { + TInt alignedLength = aLength & ~0x1FF; + + TInt bytesThisTime = (alignedLength > KLocalBufferSize) ? KLocalBufferSize : alignedLength; + + TPtr8 des((TUint8*)buffer, bytesThisTime); + ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset + totalBytesRead); + + DWORD bytesWritten; + if (!WriteFile (iDeviceHandle, buffer, bytesThisTime, &bytesWritten, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesWritten != (TUint32)bytesThisTime) + { + return KErrNotReady; + } + + totalBytesRead += bytesThisTime; + aLength -= bytesThisTime; + } + + // + // Read-Modify-Write on the last block if a partial write... + // + if(aLength > 0) + { + DWORD curPos = SetFilePointer(iDeviceHandle, 0, NULL, FILE_CURRENT); + + // RMW last sector if offset + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != KSectorSize) + return KErrNotReady; + + TPtr8 des((TUint8*)buffer, aLength); + ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset + totalBytesRead); + + if(SetFilePointer (iDeviceHandle, curPos, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + } + + return KErrNone; + } + +TInt CRawWinDiskExtProxyDrive::Write(TInt64 aPos,const TDesC8& aSrc) +// +// +// + { + // + // Set file position to where we want to write... + // + TInt length = aSrc.Length(); + + long posStartH = I64HIGH(aPos); + long posStartL = I64LOW(aPos); + + TInt offStart = posStartL & 0x1FF; + posStartL &= ~0x1FF; + + if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + const TInt KLocalBufferSize = 256*1024; + char buffer[KLocalBufferSize]; + + TInt totalBytesRead = 0; + + // + // Read-Modify-Write on first sector if start of data is offset from 512 bytes + // or if this is a partial write... + // + if(offStart || length < KSectorSize) + { + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != KSectorSize) + { + return KErrNotReady; + } + + totalBytesRead = min(KSectorSize-offStart, length); + length -= totalBytesRead; + + memcpy(&buffer[offStart], &aSrc[0], totalBytesRead); + + if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + } + + // + // Write the remainder of the aligned data + // + while(length >= KSectorSize) + { + TInt alignedLength = length & ~0x1FF; + + TInt bytesThisTime = (alignedLength > KLocalBufferSize) ? KLocalBufferSize : alignedLength; + + memcpy(buffer, &aSrc[totalBytesRead], bytesThisTime); + + DWORD bytesWritten; + if (!WriteFile (iDeviceHandle, buffer, bytesThisTime, &bytesWritten, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesWritten != (TUint32)bytesThisTime) + { + return KErrNotReady; + } + + totalBytesRead += bytesThisTime; + length -= bytesThisTime; + } + + // + // Read-Modify-Write on the last block if a partial write... + // + if(length > 0) + { + DWORD curPos = SetFilePointer(iDeviceHandle, 0, NULL, FILE_CURRENT); + + // RMW last sector if offset + DWORD bytesread; + if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + + if(bytesread != KSectorSize) + return KErrNotReady; + + memcpy(&buffer[0], &aSrc[totalBytesRead], length); + + if(SetFilePointer (iDeviceHandle, curPos, &posStartH, FILE_BEGIN) == 0xFFFFFFFF) + { + return Emulator::LastError(); + } + + if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) ) + { + return Emulator::LastError(); + } + } + + + return KErrNone; + } + +TInt CRawWinDiskExtProxyDrive::Caps(TDes8& anInfo) +// +// +// + { + TLocalDriveCapsV3Buf caps; + TInt err = CBaseExtProxyDrive::Caps(caps); + if(err == KErrNone) + { + DISK_GEOMETRY geometry; + DWORD dummy; + + if(!DeviceIoControl(iDeviceHandle, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &geometry, + sizeof(geometry), + &dummy, + (LPOVERLAPPED)NULL)) + { + return KErrNotReady; + } + + caps().iExtraInfo = EFalse; + + // NB This seems to be incorrect:If the disk is formatted by Windows, then the + // number of sectors reported in the Boot Sector is slightly greater than + // the number of sectors calculated here ... resulting in CheckDisk failures. + // One solution is to ensure the disk is formatted by the emulator. + caps().iSize = MAKE_TINT64(geometry.Cylinders.HighPart, geometry.Cylinders.LowPart) * + geometry.TracksPerCylinder * + geometry.SectorsPerTrack * + geometry.BytesPerSector; + + anInfo = caps.Left(Min(caps.Length(),anInfo.MaxLength())); + } + + return(err); + } + +TInt CRawWinDiskExtProxyDrive::Format(TFormatInfo& /*anInfo*/) +// +// +// + { + return(KErrEof); + } + + +CRawWinDiskProxyDriveFactory::CRawWinDiskProxyDriveFactory() +// +// +// + { + RDebug::Print(_L("CRawWinDiskProxyDriveFactory::CRawWinDiskProxyDriveFactory")); + } + +TInt CRawWinDiskProxyDriveFactory::Install() +// +// +// + { + _LIT(KLoggerName,"RAWEXT"); + return(SetName(&KLoggerName)); + } + + +CProxyDrive* CRawWinDiskProxyDriveFactory::NewProxyDriveL(CProxyDrive* aProxy,CMountCB* aMount) +// +// +// + { + return(CRawWinDiskExtProxyDrive::NewL(aProxy,aMount)); + } + +extern "C" { + +EXPORT_C CProxyDriveFactory* CreateFileSystem() +// +// Create a new file system +// + { + return(new CRawWinDiskProxyDriveFactory()); + } +} +