ISOイメージを作成することなく、CD-ROMから直接データを読み込んでMD5ハッシュ値を計算するための方法。
MD5.ComputeHashメソッドでMD5を計算する際、CD-ROMのデータを一度バイト配列に落としてからComputeHashメソッドに渡すのはムダが多いので、なんらかの方法でStreamから直接読み込ませる方法を考える。
CdromIsoStreamクラス
まずは、FileStreamクラスを継承してCD-ROMのデータを直接読み込むためのクラスを作る。
注意: この実装を使った場合だとCD-ROMの最終セクタの途中までしか読み込まないようなので、ISOイメージ作成ツールを使ってダンプした場合とは異なるチェックサムとなる。 あくまで参考として掲載する。 なお、以下のコードを使用して作成したISOイメージは問題なくマウントできる模様。
CdromIsoStream
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public class CdromIsoStream : FileStream {
public CdromIsoStream(DriveInfo drive)
: base(Open(drive), FileAccess.Read)
{
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(string lpFIleName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private static SafeFileHandle Open(DriveInfo drive)
{
if (drive == null)
throw new ArgumentNullException("drive");
var handle = CreateFile(string.Format(@"\\.\{0}:", drive.Name[0]),
GENERIC_READ,
FILE_SHARE_READ,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if (handle == INVALID_HANDLE_VALUE)
throw new Win32Exception(Marshal.GetLastWin32Error());
return new SafeFileHandle(handle, true);
}
}
MD5の計算
前述のクラスを使うことでCD-ROMのデータをStreamとして読み込めるようになったので、早速ComputeHashメソッドにこのインスタンスを渡してMD5を計算させる。
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
class Sample {
static void Main()
{
// 光学ドライブのDriveInfoを取得
var drive = DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.CDRom).First();
Console.WriteLine(drive);
using (var cdromStream = new CdromIsoStream(drive)) {
using (var md5 = MD5.Create()) {
// StreamのMD5ハッシュ値を計算
var md5hash = md5.ComputeHash(cdromStream);
// 文字列形式に変換して表示
var md5sum = BitConverter.ToString(md5hash).Replace("-", string.Empty).ToLowerInvariant();
Console.WriteLine(md5sum);
}
}
}
}
ISOイメージの作成
MD5の計算以だけでなく、読み込んだデータをそのままFileStreamに書きだせばISOイメージを作成することができる。
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
class Sample {
static void Main()
{
// 光学ドライブのDriveInfoを取得
var drive = DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.CDRom).First();
Console.WriteLine(drive);
using (var cdromStream = new CdromIsoStream(drive)) {
using (var fileStream = File.Create("test.iso")) {
cdromStream.CopyTo(fileStream);
}
}
}
}