バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-external-storage-backnumber/
はじめに
FatFsのファイル上シミュレーションの話。
diskio.cを改造する。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
FatFs Win32のdiskio.cを改造してディスクイメージをファイル化
太郎くん
diskio.cを改造するって前回言ってたけど、
どうだった?
フクさん
まぁ結果としてはそれほど面倒なところも無かったかな。
太郎くん
ほう。相変わらずすごいね。
フクさん
とりあえず、ざっと改造してみた。
変更差分としてはこんな感じだ。
FatFs Win32のdiskio.c 変更差分
--- ffsample/win32/diskio.c
+++ ffsample_file_sim/win32/diskio.c
@@ -14,8 +14,8 @@
#define SZ_RAMDISK 135 /* Size of drive 0 (RAM disk) [MiB] */
#define SS_RAMDISK 512 /* Initial sector size of drive 0 (RAM disk) [byte] */
-#define MIN_READ_ONLY 1 /* Read-only drive from */
-#define MAX_READ_ONLY 1 /* Read-only drive to */
+#define MIN_READ_ONLY 5 /* Read-only drive from */
+#define MAX_READ_ONLY 5 /* Read-only drive to */
@@ -50,6 +50,7 @@
/*-----------------------------------------------------------------------*/
+#if 0
DWORD WINAPI tmr_thread (LPVOID parms)
{
DWORD dw;
@@ -70,6 +70,7 @@
}
}
}
+#endif
@@ -92,6 +93,12 @@
return 1;
}
+ if (pdrv > 0) {
+ stat->n_sectors = 1024 * 1024;
+ stat->sz_sector = 512;
+ stat->status = 0;
+ }
+
/* Get drive size */
if (!DeviceIoControl(h, IOCTL_STORAGE_CHECK_VERIFY, 0, 0, 0, 0, &rb, 0)) return 0;
if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 0, 0, &parms_ex, sizeof parms_ex, &rb, 0)) {
@@ -130,7 +137,7 @@
BYTE pdrv, ndrv;
WCHAR str[50];
HANDLE h;
- OSVERSIONINFO vinfo = { sizeof (OSVERSIONINFO) };
+ //OSVERSIONINFO vinfo = { sizeof (OSVERSIONINFO) };
hMutex = CreateMutex(0, 0, 0);
@@ -143,17 +150,19 @@
if (!RamDisk) return 0;
Stat[0].sz_sector = SS_RAMDISK;
- if (GetVersionEx(&vinfo) == FALSE) return 0;
- ndrv = vinfo.dwMajorVersion > 5 ? 1 : MAX_DRIVES;
+ ndrv = MAX_DRIVES;
for (pdrv = 0; pdrv < ndrv; pdrv++) {
if (pdrv == 0) { /* \\.\PhysicalDrive0 is never mapped to disk function, but RAM disk is mapped to pd#0 instead. */
swprintf(str, 50, L"RAM Disk");
- } else { /* \\.\PhysicalDrive<n> (n=1..) are mapped to disk funtion pd#<n>. */
- swprintf(str, 50, L"\\\\.\\PhysicalDrive%u", pdrv);
- h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
- if (h == INVALID_HANDLE_VALUE) break;
- Stat[pdrv].h_drive = h;
+ }else {
+ swprintf(str, 50, L"PhysicalDrive%u", pdrv);
+ if (Stat[pdrv].h_drive != 0) {
+ CloseHandle(Stat[pdrv].h_drive);
+ }
+ h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
+ if (h != INVALID_HANDLE_VALUE)
+ Stat[pdrv].h_drive = h;
}
wprintf(L"PD#%u <== %s", pdrv, str);
if (get_status(pdrv)) {
@@ -163,7 +172,7 @@
}
}
- hTmrThread = CreateThread(0, 0, tmr_thread, 0, 0, &TmrThreadID);
+ //hTmrThread = CreateThread(0, 0, tmr_thread, 0, 0, &TmrThreadID);
if (hTmrThread == INVALID_HANDLE_VALUE) pdrv = 0;
if (ndrv > 1) {
@@ -321,9 +330,31 @@
res = RES_ERROR;
} else {
memcpy(Buffer, buff, nc);
- if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
- res = RES_ERROR;
+ {
+ int i;
+ for (i = 0; i < 10; i++) {
+ if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
+ LPVOID lpMsgBuf;
+ res = RES_ERROR;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER // テキストのメモリ割り当てを要求する
+ | FORMAT_MESSAGE_FROM_SYSTEM // エラーメッセージはWindowsが用意しているものを使用
+ | FORMAT_MESSAGE_IGNORE_INSERTS,// 次の引数を無視してエラーコードに対するエラーメッセージを作成する
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),// 言語を指定
+ (LPTSTR)&lpMsgBuf, // メッセージテキストが保存されるバッファへのポインタ
+ 0,
+ NULL);
+ printf((char*)lpMsgBuf);
+
+ }
+ else {
+ res = RES_OK;
+ break;
+ }
+ }
}
+ FlushFileBuffers(Stat[pdrv].h_drive);
}
}
} else { /* RAM disk */
改造部分解説
太郎くん
確かに思ったよりも改造した箇所は少なそうだね。
フクさん
簡単に解説すると以下になる。
- 物理ドライブの走査をMAX_DRIVEにすることで、認識できる物理ドライブが増える。
- 物理ドライブ0は従来通りのRAM Disk。
- 物理ドライブ1以上を指定されたらCreateFileWでディスクイメージをオープン
太郎くん
確かにそんな感じの改造だね。
フクさん
次回は実際に動作させてみよう。
まとめ
フクさん
まとめだよ。
- FatFs Win32のdiskio.cを改造。
- 修正差分確認。
- 改造の概要説明。
- 物理ドライブ走査数をMAX_DRIVE分に修正して認識できる物理ドライブの数を増加。
- 物理ドライブ1以上を指定されたらディスクイメージファイルをオープン。
バックナンバーはこちら。
コメント