--- /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 <f32fsys.h>
+
+#include <emulator.h>
+
+#include <windows.h>
+
+#define WIN32_LEAN_AND_MEAN
+#pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
+
+#include <winioctl.h>
+
+// 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<TUint8*>(aBuffer.Ptr());
+
+ TBuf<KCharsPerLine> 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<TUint16*>(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());
+ }
+}
+