2008年5月13日 星期二

如何偵測 USB Flash 的實際磁碟機(Physical Drive)代號

USB Flash 的資料存取方式, 以邏輯上來看和硬碟是相同的, 也就是由一個個
磁區所組成, 因此當要存取 USB Flash 裏的任一個磁區的資料時, 就需要把
USB Flash 的實際磁碟機代號找出來, 再用 CreateFile 去打開, 就可以存取
任意的磁區了, 方法如下:
1.GetDriveType 判斷邏輯磁碟機是否為 Removable.
(這裏的邏輯磁碟機指的是使用者看到的代號, 如 "D:\", "E:\" 等)
2.GetVolumeNameForVolumeMountPoint 把這個邏輯磁碟機的 GUID 找出來
3.CreateFile, 第一個參數使用剛剛找到的 GUID, 產生一個 handle
4.DeviceIoControl, HANDLE 當然是用剛才產生的 handle, dwIoControlCode
使用 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 成功後, 傳回的結構
VOLUME_DISK_EXTENTS.NumberOfDiskExtents 就是實際磁碟代號了
實際上在使用這個 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 時, 有發現
OS 所回的結構和 MSDN 上講的不同, MSDN 的如下:
typedef struct _DISK_EXTENT
{
ULONG DiskNumber;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER ExtentLength;
} DISK_EXTENT, *PDISK_EXTENT;

typedef struct _VOLUME_DISK_EXTENTS
{
ULONG NumberOfDiskExtents;
DISK_EXTENT Extents[1];
} VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS;

但實際我測試結果如下:
typedef struct _my_DISK_EXTENT {
DWORD DiskNumber;
DWORD rr; // 多出來的
LARGE_INTEGER StartingOffset;
LARGE_INTEGER ExtentLength;
} my_DISK_EXTENT;

typedef struct _my_VOLUME_DISK_EXTENTS {
DWORD NumberOfDiskExtents;
DWORD r1; // 多出來的
my_DISK_EXTENT Extents[1];
} my_VOLUME_DISK_EXTENTS, *my_PVOLUME_DISK_EXTENTS;
不知是我對MSDN有誤解或看不懂, 試了 XP & Vista 後, 都需要用我修改過
的結構才能正確的得到回傳值, 不知是否有人能幫我解釋一下, 問題在那


程式碼:

char drv_name[64],guidbuf[512];
for(i=0; i<23;i++>
{
// format the drive name from "D"
sprintf_s(drv_name, sizeof drv_name, "%c:\\", i+0x44);
// if the drive is removable device?
if(GetDriveType(drv_name) == DRIVE_REMOVABLE)
{
if(GetVolumeNameForVolumeMountPoint(drv_name,
&guidbuf[0], sizeof guidbuf))
{
HANDLE hDrv,hDrv2;
DWORD dReturn;
my_VOLUME_DISK_EXTENTS my_vd_ex;
guidbuf[strlen(guidbuf)-1]=0; // mask last "\"
// create the volume's handle by specify GUID
hDrv = CreateFile(guidbuf, GENERIC_READ, FILE_READ_DATA FILE_WRITE_DATA, 0, OPEN_EXISTING, 0, 0 );
if(hDrv != INVALID_HANDLE_VALUE) // if open success?
{
// get the volume's extent information
if(DeviceIoControl(hDrv, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &my_vd_ex, sizeof my_vd_ex, &dReturn, 0))
{
...
...
}
}
}
}
}

2008年5月6日 星期二

墾丁4日遊

很久沒到墾丁了, 這次趁勞動節,多請了一天特休, 和 Tom 一家人到墾丁.
考量到開車的人會很累, 所以我們決定坐高鐵到高雄,再租車到墾丁.
高鐵通車後我們一家也還沒坐過, 剛好體驗一下, 真的很快, 不用2小時就到高雄了,
若是自己開車,2小時最多也才到雲林而已.
Day 1 : 我們是租小馬租車, 就在高鐵旁邊而已, 租到的是 Toyota Hiace 2.7, 坐 8 個大人都沒問題, 空間很大, 不過耗油是一定的, 中餐則到三輪車, 吃的是泰式料理, 入住凱撒飯店後, 馬上到小彎去挖沙了, 因為沒有太陽, 所以不會太熱, 小朋友也玩的很高興, 至於大人們除了看小孩外, 只借排球打了約30分鐘就休息, 晚餐則到冒煙的喬吃墨西哥菜, 味道還不錯, 不過貴了點就是. 來到墾丁當然要逛逛世界上唯一在國家公園裏的夜市啦, 其實都是看熱鬧比較多啦, 有二攤叫青蛙ㄋㄟㄋㄟ的奶茶, 真的好喝, 不過最熱門的那攤竟然賣完了, 只好去排另一攤, 也等了15分鐘才買到, 看來只好第二天再來一次看看.
Day 2 : 早上吃早餐時還遇到前公司PM部門的長官, 台灣真的蠻小的, 吃完早餐後, 去坐玻璃船, 看到幾隻海龜, 另外就是海底的珊瑚礁真的非常漂亮, 希望這些美景能永遠持續下去. 中午到遠近馳名的阿利海產, 因為去到時超過2點, 差一點就沒得吃了,飽餐一頓後, 就到民宿香蕉船 check in, 馬上本團的二位女王就進入夢鄉了, 至於4個小孩則聚在一起看電視, 晚餐後再去買青蛙ㄋㄟㄋㄟ, 沒想到排了有50人左右吧, 真誇張, 難怪第一天會賣完. Day 3 : 今天的太陽非常大, 不過為了滿足小孩們要挖沙的欲望, 一行人在等王建民拿下勝投後, 又向小彎出發, 玩了一小時就離開墾丁往高雄出發了, 中午原預計到東港吃海鮮, 但沒想到東港除了生的黑鮪魚之外, 就只有二家海鮮店, 其中一家老闆還在那摔盤子, 大夥只好匆忙買了雙糕潤就閃人啦, 傍晚先到中山大學看夕陽, 可惜夕陽在快掉下來時, 竟然被雲擋到了, 只能望雲興嘆. 晚上到高雄有名的六合夜市, 但令人非常失望, 東西貴又不好吃, 不過可能是我們沒作好功課, 沒先去打聽那家店是好吃的, 今天夜宿金典酒店, 不過只有住到 49 樓, 不像上次 70 樓那麼高, 再加上是面山的房間, 所以風景沒那麼好, 幸好天氣還不錯, 所以也不差就是.
Day 4 : 早餐吃完後, 配合小孩子的行程, 就待在飯店裏的兒童設施直到退房, 之後就直上高鐵回到溫暖的家, 因為沒吃中餐, 全家又立即到麥當勞飽一頓, 就這麼結束4天的假期.
後記 : 本次出遊可視為超懶散之旅, 一些原本預定要去的景點都沒有去, 如海生館, 動物園等,不過其實也沒這麼重要, 重點是大家都玩的開心就好囉. 另一個就是墾丁的名產, 比基尼美女, 因為天氣沒很熱, 各美女們都很客氣, 所以沒看到幾個, 下次要等天氣熱一點時再來, 相信必能滿載而歸.