○ハードディスクのMBR読み書き

ハードディスクと言っても、ハードディスクと同じように扱われるUSBメモリやSDカードなどのMBRも読み書きできます。


■HDDのMBRをファイルに保存

#include <stdio.h>
#include <windows.h>

#define BUFF_SIZE 512

int main(){
	//ハードディスクドライブ0番ドライブ たぶんCドライブ
	char*filename="\\\\.\\PHYSICALDRIVE0";
	char buff[BUFF_SIZE]="No Data\n";

	//先頭セクタから512バイト読み出す
	HANDLE hFile;
	hFile = CreateFile(filename, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

	if( hFile != INVALID_HANDLE_VALUE ){
		DWORD len;
		ReadFile( hFile, buff, BUFF_SIZE, &len, NULL );
	}else{
		unsigned int i=GetLastError();
		if(ERROR_ACCESS_DENIED==i){
			printf("アクセスが拒否されました。\n管理者として実行してる?\n");
		}else if(ERROR_FILE_NOT_FOUND==i){
			printf("ドライブの指定が間違ってない?\n");
		}else{
			printf("エラー GetLastError:0x%x\n",i);
		}
		getchar();
		return -1;
	}
	CloseHandle( hFile );

	//バッファの内容をファイルに保存
	FILE * fp;
	if((fp=fopen("test.txt","wb"))==NULL){
		//エラー処理
	}else{

		unsigned int WriteLen = BUFF_SIZE;//書き込むサイズを求める

		if(WriteLen!=fwrite(buff,sizeof(char),WriteLen,fp)){
			printf("書き込みエラー%dバイト書き込まれました",WriteLen);
		}

		fclose(fp);
	}
	return 0;
}


MBRが読めるといってもドライブによっては管理者として実行しないとエラーが出てしまいます。
あと、PHYSICALDRIVE0 の文字列によってドライブを区別します、一番後ろの数字が0なら大抵Cドライブだろうと思われ、 接続された順に1,2,3と増えていくんだろう思われます。
いまいちよくわからないから、なんか調べる方法がないのかと思い、DeviceIoControlでCドライブを開いてみました。


#include <stdio.h>
#include <windows.h>

int main(){
	int i;
	DWORD r = 0;
	HANDLE hFile = CreateFile("\\\\.\\c:"
		, GENERIC_READ | GENERIC_WRITE
		, FILE_SHARE_READ | FILE_SHARE_WRITE
		, NULL, OPEN_EXISTING
		, FILE_ATTRIBUTE_NORMAL, NULL);

	if (!hFile){
		printf("ドライブ名が間違ってない?\n");
		return	-1;
	}
	STORAGE_PROPERTY_QUERY spq;
	spq.PropertyId = StorageDeviceProperty;
	spq.QueryType = PropertyStandardQuery;

	STORAGE_DEVICE_DESCRIPTOR sdd;

	i = DeviceIoControl(
		hFile,
		IOCTL_STORAGE_QUERY_PROPERTY,
		&spq,
		sizeof(STORAGE_PROPERTY_QUERY),
		&sdd,
		sizeof(STORAGE_DEVICE_DESCRIPTOR),
		&r,
		NULL);
	if (!i){
		printf("エラー\n", i);
		printf("ドライブによっては管理者として実行しないとエラーが出るよ。\n", i);
	}else{
		//sddの中を見てみよう、目的のものが見つかるかも。
	}

	CloseHandle(hFile);
	getchar();
	return 0;
}


結果から言うとこの方法では調べられません。
STORAGE_DEVICE_DESCRIPTOR構造体の中を見てもそれらしいものは見つかりませんでした。
とりあえず書いたプログラムがもったいないから載せときます(笑

その後、いろいろ調べていくと、なんとレジストリにその情報があるということがわかりました。


HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Disk\Enum



なんと、番号のほかにデータを見ると、これはIDEのSSDだな、とかこれはUSBだな、とか判別がつきます。
この番号を元にアクセスしていけばうまくいきそうです。
USBメモリを抜き差しすると、メモリごとの番号がころころ入れ替わりますが、欠番は発生しないようです。
常に連番になってるみたいです。

Windows7のパソコンで
USBメモリを抜き差しすると即座に値が変わりますが、1番のUSBメモリを抜いて2番のUSBメモリが1番になった時、 変化した1番の番号でアクセスしてもうまくいかないです。
なんでだろ、なんか更新する方法があるんだろうな・・・・・誰か教えて。




■ファイルをHDDのMBRに書き込み


この操作は非常に危険です、ちょっとミスると接続されてるUSBメモリなどの記憶装置が読めなくなったり、使えなくなったりします。
フロッピーディスクのMBRをUSBメモリに書き込んだらエクスプローラでフォーマットできなくなったりとかします。
(まあ、フォーマットはコンピュータの管理のディスクの管理でなんとかなりましたが、起動しないのに起動しようとするのにはちょっと面倒でした Boot signature の0x55 0xAAを0にしただけですけどね。)

あと、当たり前ですけど、失敗するとパソコンが起動しなくなりますんでね。
USBメモリを壊す覚悟で、パソコンを壊す覚悟で試してみてください。
ちなみに私は2回パソコンをリカバリーしましたし、USBメモリのデータも飛ばしました(笑

プログラム中では2回MBRを書き込んでますが、環境によっては必要ないかもしれません。
Windows7の私のパソコンではUSBメモリのMBRへ即時に書き込むにはこの方法が一番簡単でした。
キャッシュを押し込むみたいなイメージかな?
ほかに方法があったら教えてください。

まあ、細かいことはソースを呼んでください。


#include <stdio.h>
#include <windows.h>

#define BUFF_SIZE 512

int main(){
	char buff[BUFF_SIZE]="";

	//ファイルを開いて内容を配列に入れる
	FILE * fp;
	if((fp=fopen("test","rb"))==NULL){
		//エラー処理
		printf("ファイルが開けません。終了します。\n");
		system("PAUSE"); 
		return -1;
	}else{
		printf("%d バイト ファイルから読み込み\n",fread(buff,sizeof(char),BUFF_SIZE,fp));
		fclose(fp);
	}

	char*filename="\\\\.\\PHYSICALDRIVE1";
	printf("%s に対して ",filename);

	DWORD len=0;
	//複数回書き込むことでキャッシュから最初の書き込みをディスクに書き込んでいる。
	for(int i=0;i<=1;i++){
		//先頭セクタに書き込み
		HANDLE hFile;
		hFile = CreateFile(filename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL );
		if( hFile != INVALID_HANDLE_VALUE ){
			WriteFile( hFile, buff,BUFF_SIZE, &len, NULL );
			FlushFileBuffers(hFile);
		}else{
			unsigned int i=GetLastError();
			if(ERROR_ACCESS_DENIED==i){
				printf("エラー アクセスが拒否されました。\n管理者として実行してる?\n");
			}else if(ERROR_FILE_NOT_FOUND==i){
				printf("エラー ドライブの指定が間違ってない?\n");
			}else{
				printf("エラー GetLastError:0x%x\n",i);
			}
			break;
		}
		CloseHandle( hFile );
	}
	printf("%d バイト MBRに書き込み\n",len);
	printf("プログラムを終了します。\n");
	system("PAUSE"); 
	return 0;
}




▲トップページ > プログラミングの実験