2012年4月8日 星期日

[Win32] Disk raw data read/write

會特別寫這篇就是因為, raw data 讀寫在 linux 下是很簡單的工作, 在 windows 下我卻找了很久才找到方法.

讀寫方法要用 CreateFile/ReadFile/WriteFile/DeviceIoControl 的方法下去操作, 而 CreateFile 要用
\\PhysicalDriveN
這個名字, N 從 0 開始, 而哪一個數字代表哪一個磁碟機, 可以在 windows 管理裡看的到:
理想上 PhysicalDrive 號碼是連續的, 但實際上通常不是, 所以最好還是依號去掃描看看哪一個是可以用的.
抓出 PhysicalDrive 後, 就可以用 ReadFile 跟 WriteFile 讀寫每一顆硬碟的 MBR 跟實體磁區資料, 但這樣做太危險了, 所以這裡只對可熱插拔 removable 的下手. 而要知道哪一個 physicaldrive 是 removable disk, 就要用 DeviceIoControl 搭 IOCTL_DISK_GET_DRIVE_GEOMETRY 去查, 如這一頁寫的 code:
DISK_GEOMETRY 裡的成員 MediaType 值如果是 11(dec), 就是可移除的.

至於怎麼抓出被 mount 到哪一個 label, 重改 MBR 時怎麼 unmount, 那就再研究....


[後記 2012/04/26]
直接去找 PhysicalDrive 有好有壞, 好處是即使不被 OS mount 起來也可以找的到 (例如檔案系統如果是 ExtFS 或 linux swap 時), 壞處是無法直接推得它被 OS mount 到哪一個 driver letter 去. 在後者, 比較好的做法, 是從已被 mount 上 OS 後的 driver letter 去回推它是哪一個 physical driver. 如果要知道目前有哪些 driver letter 是有效的, 可以用:
DWORD GetLogicalDrives(void);
的回傳值取得, 因為 windows 只能 A: ~ Z: 共 26 個代號, 所以分別是 bit 0 ~ bit 25, 該 bit 為 1, 就表示這個 driver letter 存在.
然後再用
DeviceIoControl 的
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
命令取得有多少 physical driver 被 mount 到這個 driver letter 來 (因為在 NTFS 裡可以這樣做),
VOLUME_DISK_EXTENTS[0].DiskNumber 就是被找出的第一個 PhysicalDrive 數字代號.


嗯, 然後回到原來的文章, 這樣就可以從指定 driver letter 去做實體層磁區的讀寫動作.

[後記 2012/11/18]
如果是對 SD 卡讀寫, 而且 SD 卡要被用在非 windows 族 OS 上讀寫的話, 可能要注意一下 SD 卡對應 c/h/s 參數的問題, 因為在 windows 下會被統一設定成 255 heads, 63 sectors by track. 但 linux 或 BSD 底下看到的就不一定是這樣的數字...
解決方法嘛... 個人會建議把整張卡 geometric 重做, 當然, 重做之前要記得備份...
重設 geometric 的方法:
http://processors.wiki.ti.com/index.php/SD/MMC_format_for_OMAP3_boot