-
Window I/O 제어Window Programming/MFC 2008. 3. 21. 21:52728x90
00 Window I/O 관련
원문 : http://kkamagui.springnote.com/pages/340860
들어가기 전에...
- 이 글은 kkamagui에 의해 작성된 글입니다.
- 마음껏 인용하시거나 사용하셔도 됩니다. 단 출처(http://kkamagui.tistory.com, http://kkamagui.springnote.com)는 밝혀 주십시오.
- 기타 사항은 kkakkunghehe at daum.net 이나 http://kkamagui.tistory.com으로 보내주시면
반영하겠습니다.
먼저 WinXP SP2용 Platform SDK를 먼저 설치하세요~(By rajent)
1.윈도우에서 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 );
}
2.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;
}
3.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;
}
4.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;
}
5.Logical Drive와 Physical Drive 간의 매치방법1. 일단 Logical Drive를 검색한다.
-> GetDriveType() 함수를 이용
2. 해당 Drvie를 열어서 Volume 정보를 얻음
-> "\\?\c" 와 같은 형태로 CreateFile() 호출
-> IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS를 날려서 Physical Drive 정보를 얻음
-> 리더기에 데이터가 연결되어있지 않으면 DeviceIoControl에서 문제 발생'Window Programming > MFC' 카테고리의 다른 글
콤보박스리스트조절 (0) 2008.10.05 title name변경 (0) 2008.10.05 [MFC]ShellExecute 예제 (0) 2008.03.13 [MFC]ShellExecute Function (0) 2008.03.13 MFC tips (0) 2008.01.31