원본:요기
윈도우에서 Physical Drive 직접 읽고 쓰기
- 드라이브 열기
- HANDLE OpenDrive( int iPhysicalDriveNumber )
{
HANDLE hDevice;
char vcDriveName[ 30 ];// HDD를 실수로 지우는걸 방지하기 위함
if( iPhysicalDriveNumber == 0 )
{
return INVALID_HANDLE_VALUE;
}// Physical Drive를 연다.
sprintf( vcDriveName, "\\\\.\\PhysicalDrive%d", iPhysicalDriveNumber );
hDevice = CreateFile( vcDriveName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
return hDevice;
}
- 드라이브 읽기
- BOOL ReadSector( HANDLE hDevice, DWORD dwSectorOffset, BYTE* pbBuffer,
int iSectorCount )
{
DWORD dwLow;
DWORD dwHigh;
DWORD dwRet;
DWORD dwRead;
DWORD dwErrorCode;- // 움직일 위치는 byte 단위로 되어야 한다.
// 결국 dwSectorOffset에 512를 곱해줘야 한다.
dwLow = ( dwSectorOffset << 9 );
dwHigh = ( dwSectorOffset >> 23 );- // File Pointer를 이동한다.
dwRet = SetFilePointer( hDevice, dwLow, &dwHigh, FILE_BEGIN );
if( dwRet == INVALID_SET_FILE_POINTER )
{
return FALSE;
}- // Sector를 읽는다.
if( ReadFile( hDevice, pbBuffer, iSectorCount * SECTORSIZE, &dwRead,
NULL ) == FALSE )
{
dwErrorCode = GetLastError();
return FALSE;
}- return TRUE;
}
- 드라이브 쓰기
- BOOL WriteSector( HANDLE hDevice, DWORD dwSectorOffset, BYTE* pbBuffer,
int iSectorCount )
{
DWORD dwLow;
DWORD dwHigh;
DWORD dwRet;
DWORD dwWrite;
DWORD dwErrorCode;- // 움직일 위치는 byte 단위로 되어야 한다.
// 결국 dwSectorOffset에 512를 곱해줘야 한다.
dwLow = ( dwSectorOffset << 9 );
dwHigh = ( dwSectorOffset >> 23 );- // File Pointer를 이동한다.
dwRet = SetFilePointer( hDevice, dwLow, &dwHigh, FILE_BEGIN );
if( dwRet == INVALID_SET_FILE_POINTER )
{
return FALSE;
}- // Sector를 쓴다.
if( WriteFile( hDevice, pbBuffer, iSectorCount * SECTORSIZE, &dwWrite,
NULL ) == FALSE )
{
dwErrorCode = GetLastError();
return FALSE;
}- gs_dwTotalWriteSectorCount += iSectorCount;
return TRUE;
}
- 드라이브 닫기
- void CloseDrive( HANDLE hDevice )
{
CloseHandle( hDevice );
}Drive의 Geometry 읽기
Geometry정보에는 CHS 값이 들어있기 때문에 유용하게 쓸 수 있다.
- BOOL GetDriveGeometry( int iPhysicalDriveNumber, GEOMETRY* pstGeometry )
{
HANDLE hDevice;
BOOL bRet;
DWORD dwOutBytes;
char vcDriveName[ 30 ];
DISK_GEOMETRY stWindowGeometry;- // Physical Drive Number를 저장한다.
sprintf( vcDriveName, "\\\\.\\PhysicalDrive%d", iPhysicalDriveNumber );- hDevice = CreateFile( vcDriveName, 0, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );- if( hDevice == INVALID_HANDLE_VALUE )
{
return FALSE;
}- bRet = DeviceIoControl( hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, 0, &stWindowGeometry, sizeof( DISK_GEOMETRY ), &dwOutBytes,
NULL );- CloseHandle( hDevice );
- // 지금은 윈도우 Geometry와 같은 Geometry를 사용한다.
memcpy( pstGeometry, &stWindowGeometry, sizeof( DISK_GEOMETRY ) );- return bRet;
}Drive Descriptor 얻기
Descriptor에 보면 해당 드라이브의 제품명과 리비전 번호 같은 걸 알 수 있다.
- BOOL GetDeviceDescriptor( char* pcDevice, PSTORAGE_DEVICE_DESCRIPTOR pstDesc )
{
HANDLE hDevice;
STORAGE_PROPERTY_QUERY stQuery;
DWORD dwOut;
BOOL bRet;- memset( pstDesc, 0, sizeof(STORAGE_DEVICE_DESCRIPTOR) );
- // Device를 Open한다.
hDevice = CreateFile( pcDevice, GENERIC_READ, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if( hDevice == INVALID_HANDLE_VALUE )
{
return FALSE;
}- pstDesc->Size = sizeof( STORAGE_DEVICE_DESCRIPTOR );
- // Device Io Control을 호출한다.
stQuery.PropertyId = StorageDeviceProperty;
stQuery.QueryType = PropertyStandardQuery;- bRet = DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&stQuery, sizeof( STORAGE_PROPERTY_QUERY ),
pstDesc, pstDesc->Size, &dwOut, NULL);
if( bRet == FALSE )
{
return FALSE;
}- CloseHandle( hDevice );
return TRUE;
}Drive 문자로 Physical Index 얻기
드라이브 문자로 Physical Index를 얻는 방법은 VOLUME 정보를 이용하면 된다.
- int GetPhysicalDriveNumber( char cDriveName )
{
HANDLE hDevice;
DWORD dwOut;
BOOL bRet;
char vcDriveName[ 40 ];
VOLUME_DISK_EXTENTS* pstVolumeData;
int iDiskNumber;- // 메모리를 할당한다.
pstVolumeData = ( VOLUME_DISK_EXTENTS* ) malloc( VOLUMEDISKSIZE );
if( pstVolumeData == NULL )
{
return -1;
}- // 해당 Drive의 정보를 얻는다.
sprintf( vcDriveName, "\\\\?\\%c:", cDriveName );
// Device를 Open한다.
hDevice = CreateFile( vcDriveName, GENERIC_READ, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if( hDevice == INVALID_HANDLE_VALUE )
{
return -1;
}- // Device Io Control을 호출한다.
bRet = DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0, pstVolumeData, VOLUMEDISKSIZE, &dwOut, NULL );
if( bRet == FALSE )
{
free( pstVolumeData );
return -1;
}
CloseHandle( hDevice );- // Disk 정보가 1보다 작으면 실패
if( pstVolumeData->NumberOfDiskExtents < 1 )
{
free( pstVolumeData );
return -1;
}- iDiskNumber = pstVolumeData->Extents[ 0 ].DiskNumber;
free( pstVolumeData );- return iDiskNumber;
}
Logical Drive와 Physical Drive 간의 매치방법1. 일단 Logical Drive를 검색한다.
-> GetDriveType() 함수를 이용
2. 해당 Drvie를 열어서 Volume 정보를 얻음
-> "\\?\c" 와 같은 형태로 CreateFile() 호출
-> IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS를 날려서 Physical Drive 정보를 얻음
-> 리더기에 데이터가 연결되어있지 않으면 DeviceIoControl에서 문제 발생
'개발이야기' 카테고리의 다른 글
비주얼 스튜디오 마법사 에러 - Some VS2005 and VS2008 Wizards Pop Up Script Error. (0) | 2009.04.27 |
---|---|
HKCU/Software/ Microsoft/Home/Keys/ - Google 검색 (3) | 2008.03.15 |
블랙잭 레지스트리 만지기 (0) | 2007.10.24 |
정말 도움되는 Windows Mobile 팁 (0) | 2007.10.10 |
HTC UNIVERSAL HACK COLLECTION POOL! - xda-developers (0) | 2007.08.30 |
PPCSG -> How to disable GPRS and MMS (0) | 2007.08.30 |