2004-04-07 01:18:11 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "MemoryCardDriverThreaded_Windows.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "RageLog.h"
|
2004-04-23 04:17:02 +00:00
|
|
|
|
2004-04-07 01:18:11 +00:00
|
|
|
MemoryCardDriverThreaded_Windows::MemoryCardDriverThreaded_Windows()
|
|
|
|
|
{
|
2004-06-06 02:41:16 +00:00
|
|
|
m_dwLastLogicalDrives = 0;
|
2004-04-07 01:18:11 +00:00
|
|
|
}
|
|
|
|
|
|
2004-07-17 20:38:59 +00:00
|
|
|
MemoryCardDriverThreaded_Windows::~MemoryCardDriverThreaded_Windows()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-10 01:11:12 +00:00
|
|
|
static bool TestReady( const CString &sDrive, CString &sVolumeLabelOut )
|
2004-04-07 01:18:11 +00:00
|
|
|
{
|
|
|
|
|
TCHAR szVolumeNameBuffer[MAX_PATH];
|
|
|
|
|
DWORD dwVolumeSerialNumber;
|
|
|
|
|
DWORD dwMaximumComponentLength;
|
|
|
|
|
DWORD lpFileSystemFlags;
|
|
|
|
|
TCHAR szFileSystemNameBuffer[MAX_PATH];
|
2004-05-01 01:26:38 +00:00
|
|
|
|
2005-11-27 01:50:10 +00:00
|
|
|
bool bRet = !!GetVolumeInformation(
|
2004-04-07 01:18:11 +00:00
|
|
|
sDrive,
|
|
|
|
|
szVolumeNameBuffer,
|
|
|
|
|
sizeof(szVolumeNameBuffer),
|
|
|
|
|
&dwVolumeSerialNumber,
|
|
|
|
|
&dwMaximumComponentLength,
|
|
|
|
|
&lpFileSystemFlags,
|
|
|
|
|
szFileSystemNameBuffer,
|
|
|
|
|
sizeof(szFileSystemNameBuffer) );
|
2005-12-10 01:11:12 +00:00
|
|
|
sVolumeLabelOut = szVolumeNameBuffer;
|
2005-11-27 01:50:10 +00:00
|
|
|
return bRet;
|
2004-05-01 01:26:38 +00:00
|
|
|
}
|
2004-04-07 01:18:11 +00:00
|
|
|
|
2005-12-10 02:07:30 +00:00
|
|
|
bool MemoryCardDriverThreaded_Windows::TestWrite( UsbStorageDevice* pDevice )
|
2004-05-01 01:26:38 +00:00
|
|
|
{
|
2005-12-24 03:09:33 +00:00
|
|
|
/* Try to write a file, to check if the device is writable and that we have write permission.
|
|
|
|
|
* Use FILE_ATTRIBUTE_TEMPORARY to try to avoid actually writing to the device. This reduces
|
|
|
|
|
* the chance of corruption if the user removes the device immediately, without doing anything. */
|
|
|
|
|
for( int i = 0; i < 10; ++i )
|
2005-12-10 02:07:30 +00:00
|
|
|
{
|
2005-12-24 03:09:33 +00:00
|
|
|
HANDLE hFile = CreateFile( ssprintf( "%stmp%i", pDevice->sOsMountDir.c_str(), rand() % 100000),
|
|
|
|
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
|
NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL );
|
2004-04-07 01:18:11 +00:00
|
|
|
|
2005-12-24 03:09:33 +00:00
|
|
|
if( hFile == INVALID_HANDLE_VALUE )
|
|
|
|
|
{
|
|
|
|
|
DWORD iError = GetLastError();
|
|
|
|
|
if( iError == ERROR_ALREADY_EXISTS )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
LOG->Warn( werr_ssprintf(iError, "Couldn't write to %s", pDevice->sOsMountDir.c_str()) );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle( hFile );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pDevice->SetError( "TestFailed" );
|
|
|
|
|
return false;
|
2004-04-07 01:18:11 +00:00
|
|
|
}
|
|
|
|
|
|
2005-12-24 02:32:55 +00:00
|
|
|
static bool IsFloppyDrive( const CString &sDrive )
|
2005-12-10 00:36:34 +00:00
|
|
|
{
|
|
|
|
|
char szBuf[1024];
|
|
|
|
|
|
2005-12-24 02:37:06 +00:00
|
|
|
int iRet = QueryDosDevice( sDrive, szBuf, 1024 );
|
|
|
|
|
if( iRet == 0 )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( werr_ssprintf(GetLastError(), "QueryDosDevice(%s)", sDrive.c_str()) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2005-12-10 00:36:34 +00:00
|
|
|
|
2005-12-24 02:37:06 +00:00
|
|
|
// Make sure szBuf is terminated with two nulls. This only may be needed if the buffer filled.
|
|
|
|
|
szBuf[iRet-2] = 0;
|
|
|
|
|
szBuf[iRet-1] = 0;
|
|
|
|
|
|
|
|
|
|
const char *p = szBuf;
|
2005-12-10 00:36:34 +00:00
|
|
|
while( *p )
|
|
|
|
|
{
|
|
|
|
|
if( BeginsWith(p, "\\Device\\Floppy") )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
p += strlen(p)+1;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-10 01:24:11 +00:00
|
|
|
void MemoryCardDriverThreaded_Windows::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
|
|
|
|
|
{
|
2005-12-10 02:11:34 +00:00
|
|
|
DWORD dwLogicalDrives = ::GetLogicalDrives();
|
|
|
|
|
m_dwLastLogicalDrives = dwLogicalDrives;
|
|
|
|
|
|
2005-12-10 01:24:11 +00:00
|
|
|
const int MAX_DRIVES = 26;
|
|
|
|
|
for( int i=0; i<MAX_DRIVES; ++i )
|
|
|
|
|
{
|
|
|
|
|
DWORD mask = (1 << i);
|
|
|
|
|
if( !(m_dwLastLogicalDrives & mask) )
|
|
|
|
|
continue; // drive letter is invalid
|
|
|
|
|
|
2005-12-24 02:08:17 +00:00
|
|
|
CString sDrive = ssprintf( "%c:", 'a'+i%26 );
|
2005-12-24 02:32:55 +00:00
|
|
|
if( IsFloppyDrive(sDrive) )
|
|
|
|
|
continue;
|
|
|
|
|
|
2005-12-24 02:08:17 +00:00
|
|
|
if( GetDriveType(sDrive + "\\") != DRIVE_REMOVABLE ) // is a removable drive
|
2005-12-10 01:24:11 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
CString sVolumeLabel;
|
2005-12-24 02:08:17 +00:00
|
|
|
if( !TestReady(sDrive + "\\", sVolumeLabel) )
|
2005-12-10 01:24:11 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
vDevicesOut.push_back( UsbStorageDevice() );
|
|
|
|
|
UsbStorageDevice &usbd = vDevicesOut.back();
|
2005-12-24 02:08:17 +00:00
|
|
|
usbd.SetOsMountDir( sDrive + "\\" );
|
2005-12-10 01:36:15 +00:00
|
|
|
usbd.sDevice = sDrive;
|
2005-12-10 01:24:11 +00:00
|
|
|
usbd.sVolumeLabel = sVolumeLabel;
|
|
|
|
|
|
2005-12-18 07:13:13 +00:00
|
|
|
// TODO: fill in bus/level/port with this:
|
|
|
|
|
// http://www.codeproject.com/system/EnumDeviceProperties.asp
|
|
|
|
|
|
2005-12-10 01:24:11 +00:00
|
|
|
// find volume size
|
|
|
|
|
DWORD dwSectorsPerCluster;
|
|
|
|
|
DWORD dwBytesPerSector;
|
|
|
|
|
DWORD dwNumberOfFreeClusters;
|
|
|
|
|
DWORD dwTotalNumberOfClusters;
|
|
|
|
|
if( GetDiskFreeSpace(
|
|
|
|
|
sDrive,
|
|
|
|
|
&dwSectorsPerCluster,
|
|
|
|
|
&dwBytesPerSector,
|
|
|
|
|
&dwNumberOfFreeClusters,
|
|
|
|
|
&dwTotalNumberOfClusters ) )
|
|
|
|
|
{
|
|
|
|
|
usbd.iVolumeSizeMB = (int)roundf( dwTotalNumberOfClusters * (float)dwSectorsPerCluster * dwBytesPerSector / (1024*1024) );
|
|
|
|
|
}
|
2005-12-10 01:36:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-12-10 01:24:11 +00:00
|
|
|
|
2005-12-10 02:07:30 +00:00
|
|
|
bool MemoryCardDriverThreaded_Windows::USBStorageDevicesChanged()
|
2005-12-10 01:36:15 +00:00
|
|
|
{
|
2005-12-10 02:11:34 +00:00
|
|
|
return ::GetLogicalDrives() != m_dwLastLogicalDrives;
|
2005-12-10 01:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-05 19:02:25 +00:00
|
|
|
bool MemoryCardDriverThreaded_Windows::Mount( UsbStorageDevice* pDevice )
|
2004-04-07 01:18:11 +00:00
|
|
|
{
|
2005-01-27 04:39:10 +00:00
|
|
|
// nothing to do here...
|
2005-02-05 19:02:25 +00:00
|
|
|
return true;
|
2004-04-07 01:18:11 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-27 19:23:54 +00:00
|
|
|
void MemoryCardDriverThreaded_Windows::Unmount( UsbStorageDevice* pDevice )
|
2004-04-07 01:18:11 +00:00
|
|
|
{
|
2005-12-24 02:08:17 +00:00
|
|
|
/* Try to flush the device before returning. This requires administrator priviliges. */
|
|
|
|
|
HANDLE hDevice = CreateFile( "\\\\.\\" + pDevice->sDevice, GENERIC_WRITE,
|
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
|
|
|
|
|
|
|
|
|
if( hDevice == INVALID_HANDLE_VALUE )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( werr_ssprintf(GetLastError(), "Couldn't open memory card device to flush: CreateFile") );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !FlushFileBuffers(hDevice) )
|
|
|
|
|
LOG->Warn( werr_ssprintf(GetLastError(), "Couldn't flush memory card device: FlushFileBuffers") );
|
|
|
|
|
CloseHandle( hDevice );
|
2004-04-07 01:18:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2004-05-15 22:30:30 +00:00
|
|
|
* (c) 2003-2004 Chris Danford
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
|
|
|
* whom the Software is furnished to do so, provided that the above
|
|
|
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
|
|
|
* the Software and that both the above copyright notice(s) and this
|
|
|
|
|
* permission notice appear in supporting documentation.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
|
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
|
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
2004-04-07 01:18:11 +00:00
|
|
|
*/
|