Update contrib.
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
20 // This file system extension provides a way to access a drive on the local windows system in "raw format".
21 // It can be used to test large files / drives
23 // NB This should be used WITH CARE to avoid unintentionally overwriting or formatting a windows disk
32 #define WIN32_LEAN_AND_MEAN
33 #pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
37 // Enable this macro to find the last REMOVABLE drive (e.g. a card reader drive)
38 // (to minimise the chance of doing any damage !
39 // Doesn't even try any drive letters below E (again for safety):
40 #define __LOOK_FOR_DRIVE__
42 // Otherwise the windows drive letter can be hard-coded here:
43 #ifndef __LOOK_FOR_DRIVE__
44 char diskName[] = "\\\\.\\Y:";
48 const TInt KSectorSize = 512;
50 class CRawWinDiskExtProxyDrive : public CBaseExtProxyDrive
53 static CRawWinDiskExtProxyDrive* NewL(CProxyDrive* aProxyDrive, CMountCB* aMount);
54 ~CRawWinDiskExtProxyDrive();
56 virtual TInt Initialise();
57 virtual TInt Dismounted();
58 virtual TInt Enlarge(TInt aLength);
59 virtual TInt ReduceSize(TInt aPos, TInt aLength);
60 virtual TInt Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aThreadHandle,TInt anOffset);
61 virtual TInt Read(TInt64 aPos,TInt aLength,TDes8& aTrg);
62 virtual TInt Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aThreadHandle,TInt anOffset);
63 virtual TInt Write(TInt64 aPos,const TDesC8& aSrc);
64 virtual TInt Caps(TDes8& anInfo);
65 virtual TInt Format(TFormatInfo& anInfo);
67 CRawWinDiskExtProxyDrive(CProxyDrive* aProxyDrive, CMountCB* aMount);
72 class CRawWinDiskProxyDriveFactory : public CProxyDriveFactory
75 CRawWinDiskProxyDriveFactory();
76 virtual TInt Install();
77 virtual CProxyDrive* NewProxyDriveL(CProxyDrive* aProxy,CMountCB* aMount);
82 CRawWinDiskExtProxyDrive* CRawWinDiskExtProxyDrive::NewL(CProxyDrive* aProxyDrive, CMountCB* aMount)
87 CRawWinDiskExtProxyDrive* temp=new(ELeave) CRawWinDiskExtProxyDrive(aProxyDrive,aMount);
92 CRawWinDiskExtProxyDrive::CRawWinDiskExtProxyDrive(CProxyDrive* aProxyDrive, CMountCB* aMount):CBaseExtProxyDrive(aProxyDrive,aMount)
94 RDebug::Print(_L("CRawWinDiskExtProxyDrive::CRawWinDiskExtProxyDrive"));
97 CRawWinDiskExtProxyDrive::~CRawWinDiskExtProxyDrive()
102 CloseHandle(iDeviceHandle);
105 TInt CRawWinDiskExtProxyDrive::Initialise()
110 RDebug::Print(_L("CRawWinDiskExtProxyDrive::Initialise()"));
113 #ifdef __LOOK_FOR_DRIVE__
114 // Find the last REMOVABLE drive (to minimise the chance of doing any damage !
115 // Don't even try any drive letters below E (agai for safety):
116 char diskName[] = "\\\\.\\?:";
118 for (driveLetter = 'Z'; driveLetter > 'D'; driveLetter--)
120 diskName[4] = driveLetter;
122 DISK_GEOMETRY geometry;
125 iDeviceHandle = CreateFileA(diskName,
126 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
127 NULL, OPEN_EXISTING, 0, NULL);
129 if (iDeviceHandle == INVALID_HANDLE_VALUE)
134 if(DeviceIoControl(iDeviceHandle,
135 IOCTL_DISK_GET_DRIVE_GEOMETRY,
143 RDebug::Print(_L("Drive %c MediaType %d removable %s"),
146 geometry.MediaType==RemovableMedia ? _S16("True") : _S16("False"));
150 CloseHandle(iDeviceHandle);
151 if (geometry.MediaType==RemovableMedia)
154 if (driveLetter == 'D')
158 // Creating a handle to drive a: using CreateFile () function ..
159 TPtrC8 diskName8((const TUint8*) diskName);
160 TBuf16<16> diskName16;
161 diskName16.Copy(diskName8);
162 RDebug::Print(_L("RAWEXT: Opening drive %S"), &diskName16);
164 iDeviceHandle = CreateFileA(
167 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
168 NULL, OPEN_EXISTING, 0, NULL);
170 if (iDeviceHandle == INVALID_HANDLE_VALUE)
172 return Emulator::LastError();
178 TInt CRawWinDiskExtProxyDrive::Dismounted()
183 RDebug::Print(_L("CRawWinDiskExtProxyDrive::Dismounted()"));
187 TInt CRawWinDiskExtProxyDrive::Enlarge(TInt /*aLength*/)
192 return(KErrNotSupported);
196 TInt CRawWinDiskExtProxyDrive::ReduceSize(TInt /*aPos*/, TInt /*aLength*/)
201 return(KErrNotSupported);
204 LOCAL_C TInt ParameterNum(const TInt aMessageHandle, const TAny* aAddress)
206 RMessage2 tmpMessage(*(RMessagePtr2 *) &aMessageHandle);
208 if (tmpMessage.Ptr0() == aAddress)
212 if (tmpMessage.Ptr1() == aAddress)
216 if (tmpMessage.Ptr2() == aAddress)
220 if (tmpMessage.Ptr3() == aAddress)
224 User::Panic(_L("RAWEXT"),KErrBadHandle);
230 TInt CRawWinDiskExtProxyDrive::Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aThreadHandle,TInt aOffset)
237 // Set file position to where we want to read...
242 long posH = I64HIGH(aPos);
243 long posL = I64LOW(aPos);
245 TInt off = posL & 0x1FF;
248 if(SetFilePointer (iDeviceHandle, posL, &posH, FILE_BEGIN) == 0xFFFFFFFF)
250 return Emulator::LastError();
253 const TInt KLocalBufferSize = 256*1024;
254 char buffer[KLocalBufferSize];
256 const TInt param = ParameterNum(aThreadHandle, aTrg);
258 TInt totalBytesRead = 0;
261 // Read first sector if start of data is offset from 512 bytes...
265 // read 1st sector if offset
267 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesRead, NULL) )
269 return Emulator::LastError();
272 if(bytesRead != KSectorSize)
278 TInt copyLen = Min(aLength, bytesRead);;
280 totalBytesRead += copyLen;
283 TPtrC8 des((TUint8*) buffer+off, copyLen);
284 ((RMessagePtr2 *) &aThreadHandle)->Write(param, des, aOffset);
288 // Read the remainder of the data, accounting for partial last sector...
292 TUint32 bytesThisTime = min(KLocalBufferSize, (TUint32)aLength);
294 bytesThisTime = (bytesThisTime + KSectorSize-1) & ~(KSectorSize-1);
297 if (!ReadFile (iDeviceHandle, buffer, bytesThisTime, &bytesread, NULL) )
299 return Emulator::LastError();
302 if(bytesread != (TUint32)bytesThisTime)
307 TPtrC8 des((TUint8*)buffer, min((TUint32)aLength, bytesThisTime));
308 ((RMessagePtr2 *) &aThreadHandle)->Write(param, des, aOffset + totalBytesRead);
309 totalBytesRead += bytesThisTime;
310 aLength -= bytesThisTime;
318 GLDEF_C void DumpBuffer( const TDesC8& aBuffer )
320 * Dump the content of aBuffer in hex
323 static const TText hextab[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
324 'A', 'B', 'C', 'D', 'E', 'F' };
325 const TInt KBytesPerLine = 32;
326 const TInt KCharsPerLine = KBytesPerLine * 2;
328 TInt remaining = aBuffer.Length();
329 TUint8* pSrc = const_cast<TUint8*>(aBuffer.Ptr());
331 TBuf<KCharsPerLine> line;
332 line.SetLength( KCharsPerLine ); // don't need to print trailing space
333 TInt bytesPerLine = KBytesPerLine;
337 if( remaining < KBytesPerLine )
339 bytesPerLine = remaining;
340 line.SetLength( (bytesPerLine*2) );
342 TUint16* pDest = const_cast<TUint16*>(line.Ptr());
343 remaining -= bytesPerLine;
344 for( TInt i = bytesPerLine; i > 0; --i )
347 *pDest++ = hextab[c >> 4];
348 *pDest++ = hextab[c & 0xF];
350 _LIT( KFmt, "%06x: %S\n\r" );
351 RDebug::Print( KFmt, lineOffs, &line );
352 lineOffs += bytesPerLine;
358 TInt CRawWinDiskExtProxyDrive::Read(TInt64 aPos,TInt aLength,TDes8& aTrg)
365 // Set file position to where we want to read...
370 long posH = I64HIGH(aPos);
371 long posL = I64LOW(aPos);
373 TInt off = posL & 0x1FF;
376 if(SetFilePointer (iDeviceHandle, posL, &posH, FILE_BEGIN) == 0xFFFFFFFF)
378 return Emulator::LastError();
381 const TInt KLocalBufferSize = 256*1024;
382 char buffer[KLocalBufferSize];
384 TInt totalBytesRead = 0;
386 aTrg.SetLength(aLength);
389 // Read first sector if start of data is offset from 512 bytes...
393 // read 1st sector if offset
395 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesRead, NULL) )
397 return Emulator::LastError();
400 if(bytesRead != KSectorSize)
406 TInt copyLen = Min(aLength, bytesRead);;
408 totalBytesRead += copyLen;
411 memcpy(&aTrg[0], &buffer[off], copyLen);
415 // Read the remainder of the data, accounting for partial last sector...
419 TInt bytesThisTime = (aLength > KLocalBufferSize) ? KLocalBufferSize : aLength;
421 bytesThisTime = (bytesThisTime + KSectorSize-1) & ~(KSectorSize-1);
424 if (!ReadFile (iDeviceHandle, buffer, bytesThisTime, &bytesread, NULL) )
426 return Emulator::LastError();
429 if(bytesread != (TUint32)bytesThisTime)
432 TInt copyLen = aLength < bytesThisTime ? aLength : bytesThisTime;
434 memcpy(&aTrg[totalBytesRead], buffer, copyLen);
436 totalBytesRead += bytesThisTime;
437 aLength -= bytesThisTime;
445 TInt CRawWinDiskExtProxyDrive::Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aThreadHandle,TInt aOffset)
451 // Set file position to where we want to write...
453 long posStartH = I64HIGH(aPos);
454 long posStartL = I64LOW(aPos);
456 TInt offStart = posStartL & 0x1FF;
459 if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
461 return Emulator::LastError();
464 const TInt KLocalBufferSize = 256*1024;
465 char buffer[KLocalBufferSize];
467 const TInt param = ParameterNum(aThreadHandle, aSrc);
469 TInt totalBytesRead = 0;
472 // Read-Modify-Write on first sector if start of data is offset from 512 bytes
473 // or if this is a partial write...
475 if(offStart || aLength < KSectorSize)
478 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
480 return Emulator::LastError();
483 if(bytesread != KSectorSize)
488 totalBytesRead = min(KSectorSize-offStart, aLength);
489 aLength -= totalBytesRead;
491 TPtr8 des((TUint8*)&buffer[offStart], totalBytesRead);
492 ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset);
494 if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
496 return Emulator::LastError();
499 if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
501 return Emulator::LastError();
506 // Write the remainder of the aligned data
508 while(aLength >= KSectorSize)
510 TInt alignedLength = aLength & ~0x1FF;
512 TInt bytesThisTime = (alignedLength > KLocalBufferSize) ? KLocalBufferSize : alignedLength;
514 TPtr8 des((TUint8*)buffer, bytesThisTime);
515 ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset + totalBytesRead);
518 if (!WriteFile (iDeviceHandle, buffer, bytesThisTime, &bytesWritten, NULL) )
520 return Emulator::LastError();
523 if(bytesWritten != (TUint32)bytesThisTime)
528 totalBytesRead += bytesThisTime;
529 aLength -= bytesThisTime;
533 // Read-Modify-Write on the last block if a partial write...
537 DWORD curPos = SetFilePointer(iDeviceHandle, 0, NULL, FILE_CURRENT);
539 // RMW last sector if offset
541 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
543 return Emulator::LastError();
546 if(bytesread != KSectorSize)
549 TPtr8 des((TUint8*)buffer, aLength);
550 ((RMessagePtr2 *) &aThreadHandle)->Read(param, des, aOffset + totalBytesRead);
552 if(SetFilePointer (iDeviceHandle, curPos, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
554 return Emulator::LastError();
557 if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
559 return Emulator::LastError();
566 TInt CRawWinDiskExtProxyDrive::Write(TInt64 aPos,const TDesC8& aSrc)
572 // Set file position to where we want to write...
574 TInt length = aSrc.Length();
576 long posStartH = I64HIGH(aPos);
577 long posStartL = I64LOW(aPos);
579 TInt offStart = posStartL & 0x1FF;
582 if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
584 return Emulator::LastError();
587 const TInt KLocalBufferSize = 256*1024;
588 char buffer[KLocalBufferSize];
590 TInt totalBytesRead = 0;
593 // Read-Modify-Write on first sector if start of data is offset from 512 bytes
594 // or if this is a partial write...
596 if(offStart || length < KSectorSize)
599 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
601 return Emulator::LastError();
604 if(bytesread != KSectorSize)
609 totalBytesRead = min(KSectorSize-offStart, length);
610 length -= totalBytesRead;
612 memcpy(&buffer[offStart], &aSrc[0], totalBytesRead);
614 if(SetFilePointer (iDeviceHandle, posStartL, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
616 return Emulator::LastError();
619 if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
621 return Emulator::LastError();
626 // Write the remainder of the aligned data
628 while(length >= KSectorSize)
630 TInt alignedLength = length & ~0x1FF;
632 TInt bytesThisTime = (alignedLength > KLocalBufferSize) ? KLocalBufferSize : alignedLength;
634 memcpy(buffer, &aSrc[totalBytesRead], bytesThisTime);
637 if (!WriteFile (iDeviceHandle, buffer, bytesThisTime, &bytesWritten, NULL) )
639 return Emulator::LastError();
642 if(bytesWritten != (TUint32)bytesThisTime)
647 totalBytesRead += bytesThisTime;
648 length -= bytesThisTime;
652 // Read-Modify-Write on the last block if a partial write...
656 DWORD curPos = SetFilePointer(iDeviceHandle, 0, NULL, FILE_CURRENT);
658 // RMW last sector if offset
660 if (!ReadFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
662 return Emulator::LastError();
665 if(bytesread != KSectorSize)
668 memcpy(&buffer[0], &aSrc[totalBytesRead], length);
670 if(SetFilePointer (iDeviceHandle, curPos, &posStartH, FILE_BEGIN) == 0xFFFFFFFF)
672 return Emulator::LastError();
675 if (!WriteFile (iDeviceHandle, buffer, KSectorSize, &bytesread, NULL) )
677 return Emulator::LastError();
685 TInt CRawWinDiskExtProxyDrive::Caps(TDes8& anInfo)
690 TLocalDriveCapsV3Buf caps;
691 TInt err = CBaseExtProxyDrive::Caps(caps);
694 DISK_GEOMETRY geometry;
697 if(!DeviceIoControl(iDeviceHandle,
698 IOCTL_DISK_GET_DRIVE_GEOMETRY,
709 caps().iExtraInfo = EFalse;
711 // NB This seems to be incorrect:If the disk is formatted by Windows, then the
712 // number of sectors reported in the Boot Sector is slightly greater than
713 // the number of sectors calculated here ... resulting in CheckDisk failures.
714 // One solution is to ensure the disk is formatted by the emulator.
715 caps().iSize = MAKE_TINT64(geometry.Cylinders.HighPart, geometry.Cylinders.LowPart) *
716 geometry.TracksPerCylinder *
717 geometry.SectorsPerTrack *
718 geometry.BytesPerSector;
720 anInfo = caps.Left(Min(caps.Length(),anInfo.MaxLength()));
726 TInt CRawWinDiskExtProxyDrive::Format(TFormatInfo& /*anInfo*/)
735 CRawWinDiskProxyDriveFactory::CRawWinDiskProxyDriveFactory()
740 RDebug::Print(_L("CRawWinDiskProxyDriveFactory::CRawWinDiskProxyDriveFactory"));
743 TInt CRawWinDiskProxyDriveFactory::Install()
748 _LIT(KLoggerName,"RAWEXT");
749 return(SetName(&KLoggerName));
753 CProxyDrive* CRawWinDiskProxyDriveFactory::NewProxyDriveL(CProxyDrive* aProxy,CMountCB* aMount)
758 return(CRawWinDiskExtProxyDrive::NewL(aProxy,aMount));
763 EXPORT_C CProxyDriveFactory* CreateFileSystem()
765 // Create a new file system
768 return(new CRawWinDiskProxyDriveFactory());