The beast of halfpace

日々のメモ

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  107  : 記事  0  : コメント  396  : トラックバック  31

ニュース

Mozilla Firefox ブラウザ無料ダウンロード

記事カテゴリ

書庫

日記カテゴリ

最初に言い訳。

C#ではコンソールにHello, World!を出したことがある程度の知識です。間違ってたら指摘してください。

とある掲示板でC#でHDDのセクタリードをするとは?という質問が出ていたのを見たので気になってやってみた。

ほぼここでやったことのC#版。ただし、MBRを読んでパーティションテーブルを取得した後パーティション1の先頭セクタを読んでいる。


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace SectorReadSample
{
    class SectorRead
    {
        [DllImport("Kernel32.dll")]
        public static extern System.IntPtr CreateFile(System.Text.StringBuilder lpFileName,
                                                      uint dwDesiredAccess,
                                                      uint dwSharedMode,
                                                      System.IntPtr lpSecuriteAttributes,
                                                      uint dwCreationDisposition,
                                                      uint dwFlagsAndAttributes,
                                                      System.IntPtr hTemplateFile);
        [DllImport("Kernel32.dll")]
        unsafe public static extern bool ReadFile(System.IntPtr hFile,
                                                  byte* lpBuffer,
                                                  uint nNumberOfBytesToRead,
                                                  uint* lpNumberOfBytesRead,
                                                  System.IntPtr lpOverlapped);
        [DllImport("Kernel32.dll")]
        unsafe public static extern uint SetFilePointer(System.IntPtr hFile,
                                                        uint lDistanceToMove,
                                                        uint* lpDistanceToMoveHigh,
                                                        uint dwMoveMethod);

        [DllImport("Kernel32.dll")]
        public static extern bool CloseHandle(System.IntPtr hFile);

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        unsafe public struct PartitionTable
        {
            public byte boot_flag;          // ブートフラグ
            public fixed byte start_chs[3]; // 開始CHS
            public byte type;               // パーティションの種類
            public fixed byte end_chs[3];   // 終了CHS
            public uint start_lba;          // 開始LBA
            public uint total_sector;       // セクタ数       
        }

        /* SetFilePointer用 */
        public const uint FileBegin = 0;
        public const uint FileCurrent = 1;
        public const uint FileEnd = 2;

        /* デバイス名 */
        private System.Text.StringBuilder deviceName;
        /* ハンドル */
        private System.IntPtr hFile;

        /* コンストラクタ */
        public SectorRead(string dn)
        {
            deviceName = new System.Text.StringBuilder(dn);
            hFile = CreateFile(deviceName,
                               0x80000000,              // GENERIC_READ
                               0x00000001 | 0x00000002, // FILE_SHARE_READ | FILE_SHARE_WRITE
                               System.IntPtr.Zero,      // NULL
                               3,                       // OPEN_EXISTING
                               0x00000080,              // FILE_ATTRIBUTE_NORMAL
                               System.IntPtr.Zero);     // NULL
        }

        /* デストラクタ */
        ~SectorRead()
        {
            CloseHandle(hFile);
        }

        /* セクタリード */
        unsafe public void ReadSector(uint sector, byte[] buff)
        {
            uint len = 0;
            fixed(byte* p = &buff[0])
            {
                SetFilePointer(hFile, sector * 0x200, &len, FileBegin);
                ReadFile(hFile, p, 0x200, &len, IntPtr.Zero);
            }
        }

        /* パーティションテーブル情報取得 MBR(セクタ0)を渡す */
        unsafe public PartitionTable ReadPartitionTable(byte[] buff, int part)
        {
            PartitionTable result = new PartitionTable();
            fixed(byte* p = &buff[446]) {
                result = ((PartitionTable*)p)[part];
            }

            return result;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            byte[] buff = new byte[512];    // 1セクタ分のバッファ
            // Cドライブをオープン
            SectorRead sr = new SectorRead("\\\\.\\PHYSICALDRIVE0");
            // 先頭セクタ(MBR)を読み出す。
            sr.ReadSector(0, buff);
            // パーティション1の情報を取得
            SectorRead.PartitionTable p1 = sr.ReadPartitionTable(buff, 0);
            // パーティション1の先頭1セクタを読み出す
            sr.ReadSector(p1.start_lba, buff);

            /* パーティション1セクタ情報 */
            Console.WriteLine("Partition Type:{0}", p1.type);
            Console.WriteLine("Start LBA:{0}", p1.start_lba);
            Console.WriteLine("Total Sector:{0}", p1.total_sector);
            Console.WriteLine("Partition1: {0:X2} {1:X2} {2:X2} {3:X2} {4:X2} {5:X2} {6:X2}",
                                        buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6]);
        }
    }
}


実行結果

Partition Type:7 (NTFSは7)
Start LBA:2048 (先頭セクタ)
Total Sector:625137664(総セクタ数 ・1K=1000換算で約320GB)
Partition1: EB 52 90 4E 54 46 53 (文字にすると.R.NTFS)

どうやら正しくパーティションが読めているようです。

C#ならC++より簡単に作れると思ったけど、この手のことをするにはC++の方が楽みたい。

投稿日時 : 2008年8月8日 0:03

コメント

# re: C#でセクタリード 2008/08/08 9:32 st.lain
# 未確認で書いてますので間違っていたらゴメンナサイっ m(_"_)m

MSDNのFileStreamを見ると、IntPtr handleを引数に持つコンストラクタが
存在するので、CreateFileのハンドルを直接渡せそうなニオひを
かもし出しているような気がしました。

FileStreamが使えるのであればReadFile, SetFilePointer, CloseHandleを
省くことができるのカナー、って書き込む前に自分でヤレってこと
ですね orz

# 私もC#ほとんど使ってない orz



# re: C#でセクタリード 2008/08/08 10:08 st.lain
Σ(*ノノ) やっぱり間違ってました・・・。

> IntPtr handleを引数に持つコンストラクタが
MSDN VS2003用見てたので2008では通らない状態でした。
IntPtr→SafeFileHandleを使え~と怒られちゃいました。

512Byte確認した限りでは大丈夫っぽいのですけど・・・。(汗
(MBRとかわかってないし)

こんな感じに書いてみました。
| using (FileStream fs = new FileStream(hFile, FileAccess.Read))
| {
| fs.Read(buff, 0, buff.Length);
| }



# re: C#でセクタリード 2008/08/09 11:46 あんどちん
おを、FileStreamを使えばよいのですね。
結局Win32API呼び出しばっかりで気に入らないと思っていたので、この方法は良いですね。
# PHYSICALDEVICE0が普通にオープンできればそれでいいんだけどねぇ




# Javaでセクタリード 2008/08/12 22:25 The beast of halfpace
Javaでセクタリード

# Javaでセクタリード 2008/08/12 22:34 The beast of halfpace
Javaでセクタリード

Post Feedback

タイトル
名前
Url:
コメント: