ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Window I/O 제어
    Window Programming/MFC 2008. 3. 21. 21:52
    728x90

    00 Window I/O 관련

    원문 : http://kkamagui.springnote.com/pages/340860


    들어가기 전에...

    시작하기 전에!!
    먼저 WinXP SP2용 Platform SDK를 먼저 설치하세요~(By rajent)

    1.윈도우에서 Physical Drive 직접 읽고 쓰기

    • 드라이브 열기
    1. HANDLE OpenDrive( int iPhysicalDriveNumber )
      {
          HANDLE hDevice;
          char vcDriveName[ 30 ];


    2.     // HDD를 실수로 지우는걸 방지하기 위함

          if( iPhysicalDriveNumber == 0 )
          {
              return INVALID_HANDLE_VALUE;
          }

    3.     // 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;
      }


    • 드라이브 읽기
    1. BOOL ReadSector( HANDLE hDevice, DWORD dwSectorOffset, BYTE* pbBuffer,
                       int iSectorCount )
      {
          DWORD dwLow;
          DWORD dwHigh;
          DWORD dwRet;
          DWORD dwRead;
          DWORD dwErrorCode;
    2.     // 움직일 위치는 byte 단위로 되어야 한다.
          // 결국 dwSectorOffset에 512를 곱해줘야 한다.
          dwLow = ( dwSectorOffset << 9 );
          dwHigh = ( dwSectorOffset >> 23 );
    3.     // File Pointer를 이동한다.
          dwRet = SetFilePointer( hDevice, dwLow, &dwHigh, FILE_BEGIN );
          if( dwRet == INVALID_SET_FILE_POINTER )
          {
              return FALSE;
          }
    4.     // Sector를 읽는다.
          if( ReadFile( hDevice, pbBuffer, iSectorCount * SECTORSIZE, &dwRead,
              NULL ) == FALSE )
          {
              dwErrorCode = GetLastError();
              return FALSE;
          }
    5.     return TRUE;
      }

    • 드라이브 쓰기
    1. BOOL WriteSector( HANDLE hDevice, DWORD dwSectorOffset, BYTE* pbBuffer,
                       int iSectorCount )
      {
          DWORD dwLow;
          DWORD dwHigh;
          DWORD dwRet;
          DWORD dwWrite;
          DWORD dwErrorCode;
    2.     // 움직일 위치는 byte 단위로 되어야 한다.
          // 결국 dwSectorOffset에 512를 곱해줘야 한다.
          dwLow = ( dwSectorOffset << 9 );
          dwHigh = ( dwSectorOffset >> 23 );
    3.     // File Pointer를 이동한다.
          dwRet = SetFilePointer( hDevice, dwLow, &dwHigh, FILE_BEGIN );
          if( dwRet == INVALID_SET_FILE_POINTER )
          {
              return FALSE;
          }
    4.     // Sector를 쓴다.
          if( WriteFile( hDevice, pbBuffer, iSectorCount * SECTORSIZE, &dwWrite,
              NULL ) == FALSE )
          {
              dwErrorCode = GetLastError();
              return FALSE;
          }
    5.     gs_dwTotalWriteSectorCount += iSectorCount;
          return TRUE;
      }

    • 드라이브 닫기
    1. void CloseDrive( HANDLE hDevice )
      {
          CloseHandle( hDevice );
      }

    2.Drive의 Geometry 읽기

    Geometry정보에는 CHS 값이 들어있기 때문에 유용하게 쓸 수 있다.

    1. BOOL GetDriveGeometry( int iPhysicalDriveNumber, GEOMETRY* pstGeometry )
      {
          HANDLE hDevice;
          BOOL bRet;
          DWORD dwOutBytes;
          char vcDriveName[ 30 ];
          DISK_GEOMETRY stWindowGeometry;
    2.     // Physical Drive Number를 저장한다.
          sprintf( vcDriveName, "\\\\.\\PhysicalDrive%d", iPhysicalDriveNumber );
    3.     hDevice = CreateFile( vcDriveName, 0, FILE_SHARE_READ |
              FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
    4.     if( hDevice == INVALID_HANDLE_VALUE )
          {
              return FALSE;
          }
    5.     bRet = DeviceIoControl( hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY,
              NULL, 0, &stWindowGeometry, sizeof( DISK_GEOMETRY ), &dwOutBytes,
              NULL );
    6.     CloseHandle( hDevice );
    7.     // 지금은 윈도우 Geometry와 같은 Geometry를 사용한다.
          memcpy( pstGeometry, &stWindowGeometry, sizeof( DISK_GEOMETRY ) );
    8.     return bRet;
      }

    3.Drive Descriptor 얻기

    Descriptor에 보면 해당 드라이브의 제품명과 리비전 번호 같은 걸 알 수 있다.

    1. BOOL GetDeviceDescriptor( char* pcDevice, PSTORAGE_DEVICE_DESCRIPTOR pstDesc )
      {
          HANDLE hDevice;
          STORAGE_PROPERTY_QUERY  stQuery;
          DWORD dwOut;
          BOOL bRet;
    2.     memset( pstDesc, 0, sizeof(STORAGE_DEVICE_DESCRIPTOR) );
    3.     // 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;
          }
    4.     pstDesc->Size = sizeof( STORAGE_DEVICE_DESCRIPTOR );
    5.     // Device Io Control을 호출한다.
          stQuery.PropertyId = StorageDeviceProperty;
          stQuery.QueryType = PropertyStandardQuery;
    6.     bRet = DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
                  &stQuery, sizeof( STORAGE_PROPERTY_QUERY ),
                  pstDesc, pstDesc->Size, &dwOut, NULL);                
          if( bRet == FALSE )
          {
              return FALSE;
          }
    7.     CloseHandle( hDevice );
          return TRUE;
      }

    4.Drive 문자로 Physical Index 얻기

    드라이브 문자로 Physical Index를 얻는 방법은 VOLUME 정보를 이용하면 된다.

    1. int GetPhysicalDriveNumber( char cDriveName )
      {
          HANDLE hDevice;
          DWORD dwOut;
          BOOL bRet;
          char vcDriveName[ 40 ];
          VOLUME_DISK_EXTENTS* pstVolumeData;
          int iDiskNumber;
    2.     // 메모리를 할당한다.
          pstVolumeData = ( VOLUME_DISK_EXTENTS* ) malloc( VOLUMEDISKSIZE );
          if( pstVolumeData == NULL )
          {
              return -1;
          }
    3.     // 해당 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;
          }
    4.     // 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 );
    5.     // Disk 정보가 1보다 작으면 실패
          if( pstVolumeData->NumberOfDiskExtents < 1 )
          {
              free( pstVolumeData );
              return -1;
          }
    6.     iDiskNumber = pstVolumeData->Extents[ 0 ].DiskNumber;
          free( pstVolumeData );
    7.     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

    댓글

Designed by black7375.