Improve CVolumeStream to allow reading from physical drives again.

This commit is contained in:
Jean-Philip Desjardins 2019-10-02 13:07:03 -04:00
parent e9078ce3f0
commit e5580af607
3 changed files with 32 additions and 33 deletions

View file

@ -79,7 +79,7 @@ DiskUtils::OpticalMediaPtr DiskUtils::CreateOpticalMediaFromPath(const boost::fi
#ifdef _WIN32 #ifdef _WIN32
else if(imagePath.string()[0] == '\\') else if(imagePath.string()[0] == '\\')
{ {
stream = std::make_shared<Framework::Win32::CVolumeStream>(imagePath.string()[4]); stream = std::make_shared<Framework::Win32::CVolumeStream>(imagePath.native().c_str());
} }
#elif !defined(__ANDROID__) && !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR #elif !defined(__ANDROID__) && !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
else if(imagePath.string().find("/dev/") == 0) else if(imagePath.string().find("/dev/") == 0)

View file

@ -1,23 +1,26 @@
#include <exception> #include <exception>
#include "tcharx.h"
#include "VolumeStream.h" #include "VolumeStream.h"
using namespace Framework; using namespace Framework;
using namespace Framework::Win32; using namespace Framework::Win32;
using namespace std;
CVolumeStream::CVolumeStream(char nDriveLetter) CVolumeStream::CVolumeStream(const TCHAR* volumePath)
{ {
char sPath[7] = //We need to remove any trailing slashes to open volumes
{ auto fixedVolumePath = std::tstring(volumePath);
'\\', if(!fixedVolumePath.empty() && (*fixedVolumePath.rbegin() == '\\'))
'\\', {
'.', fixedVolumePath = std::tstring(fixedVolumePath.begin(), fixedVolumePath.end() - 1);
'\\', }
nDriveLetter,
':', m_nVolume = CreateFile(fixedVolumePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
'\0'}; assert(m_nVolume != INVALID_HANDLE_VALUE);
if(m_nVolume == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Failed to open volume.");
}
m_nVolume = CreateFileA(sPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
m_nPosition = 0; m_nPosition = 0;
m_nSectorSize = 0x800; m_nSectorSize = 0x800;
@ -42,7 +45,7 @@ void CVolumeStream::Seek(int64 nDistance, STREAM_SEEK_DIRECTION nFrom)
m_nPosition += nDistance; m_nPosition += nDistance;
break; break;
case STREAM_SEEK_END: case STREAM_SEEK_END:
throw exception("Operation not supported."); throw std::exception("Operation not supported.");
break; break;
} }
} }
@ -54,13 +57,9 @@ uint64 CVolumeStream::Tell()
uint64 CVolumeStream::Read(void* pBuffer, uint64 nSize) uint64 CVolumeStream::Read(void* pBuffer, uint64 nSize)
{ {
uint8* pDst; auto pSrc = reinterpret_cast<uint8*>(m_pCache);
uint8* pSrc; auto pDst = reinterpret_cast<uint8*>(pBuffer);
uint64 nRetSize; uint64 nRetSize = nSize;
pSrc = (uint8*)m_pCache;
pDst = (uint8*)pBuffer;
nRetSize = nSize;
while(nSize != 0) while(nSize != 0)
{ {
@ -84,7 +83,7 @@ uint64 CVolumeStream::Read(void* pBuffer, uint64 nSize)
uint64 CVolumeStream::Write(const void* pBuffer, uint64 nSize) uint64 CVolumeStream::Write(const void* pBuffer, uint64 nSize)
{ {
throw exception("Operation not-supported."); throw std::exception("Operation not-supported.");
} }
bool CVolumeStream::IsEOF() bool CVolumeStream::IsEOF()
@ -94,14 +93,13 @@ bool CVolumeStream::IsEOF()
void CVolumeStream::SyncCache() void CVolumeStream::SyncCache()
{ {
uint64 nSectorPosition; uint64 nSectorPosition = m_nPosition & ~(m_nSectorSize - 1);
DWORD nRead;
nSectorPosition = m_nPosition & ~(m_nSectorSize - 1);
if(nSectorPosition == m_nCacheSector) return; if(nSectorPosition == m_nCacheSector) return;
m_nCacheSector = nSectorPosition; m_nCacheSector = nSectorPosition;
SetFilePointer(m_nVolume, (uint32)nSectorPosition, (PLONG)((uint32*)&nSectorPosition) + 1, FILE_BEGIN); SetFilePointer(m_nVolume, (uint32)nSectorPosition, (PLONG)((uint32*)&nSectorPosition) + 1, FILE_BEGIN);
ReadFile(m_nVolume, m_pCache, (DWORD)m_nSectorSize, &nRead, NULL); DWORD nRead = 0;
BOOL success = ReadFile(m_nVolume, m_pCache, (DWORD)m_nSectorSize, &nRead, NULL);
assert(success);
} }

View file

@ -11,13 +11,14 @@ namespace Framework
class CVolumeStream : public CStream class CVolumeStream : public CStream
{ {
public: public:
CVolumeStream(char); CVolumeStream(const TCHAR*);
virtual ~CVolumeStream(); virtual ~CVolumeStream();
virtual void Seek(int64, STREAM_SEEK_DIRECTION);
virtual uint64 Tell(); void Seek(int64, STREAM_SEEK_DIRECTION);
virtual uint64 Read(void*, uint64); uint64 Tell() override;
virtual uint64 Write(const void*, uint64); uint64 Read(void*, uint64) override;
virtual bool IsEOF(); uint64 Write(const void*, uint64) override;
bool IsEOF() override;
private: private:
void SyncCache(); void SyncCache();