不同WINDOWS平臺(tái)下磁盤(pán)邏輯扇區(qū)的直接讀寫(xiě)
來(lái)源:程序員人生 發(fā)布時(shí)間:2015-06-11 08:29:43 閱讀次數(shù):2946次
不同WINDOWS平臺(tái)下磁盤(pán)邏輯扇區(qū)的直接讀寫(xiě) 關(guān)鍵字:VWIN32、中斷、DeviceIoControl 1、概述 在DOS操作系統(tǒng)下,通過(guò)BIOS的INT13、DOS的INT25(絕對(duì)讀)、INT26(絕對(duì)寫(xiě))等功能調(diào)用實(shí)現(xiàn)對(duì)磁盤(pán)邏輯扇區(qū)或物理扇區(qū)的讀寫(xiě)是很方便的,C語(yǔ)言中還有對(duì)應(yīng)上述功能調(diào)用的函數(shù):biosdisk、absread和abswrite等。但在WINDOWS操作系統(tǒng)下編寫(xiě)WIN32利用程序時(shí)卻不再能直接使用上述的中斷調(diào)用或函數(shù)了。那末,在WINDOWS操作系統(tǒng)下能不能實(shí)現(xiàn)磁盤(pán)扇區(qū)的直接讀寫(xiě)呢?如何實(shí)現(xiàn)磁盤(pán)扇區(qū)的讀寫(xiě)呢?為了解決這些問(wèn)題,筆者查閱了1些相干資料后發(fā)現(xiàn),WINDOWS操作系統(tǒng)也提供了讀寫(xiě)磁盤(pán)扇區(qū)的方法,只是在不同的版本中有著不同的方式和使用限制。最后,筆者編寫(xiě)了1個(gè)磁盤(pán)扇區(qū)直接讀寫(xiě)類(lèi),不敢獨(dú)專(zhuān),特提供出來(lái),希望能對(duì)大家有所幫助。 注:這里INT13表示INT 13H,其它類(lèi)同。 2、1個(gè)讀取軟盤(pán)扇區(qū)的例子 WINDOWS操作系統(tǒng)對(duì)所有的存儲(chǔ)裝備實(shí)行了統(tǒng)1管理,而且為了安全起見(jiàn),操作系統(tǒng)還不允許在WIN32利用程序(工作在Ring3級(jí))中直接調(diào)用中斷功能,如INT13、INT21、INT25、INT26等。但它同時(shí)也提供了1些服務(wù)來(lái)彌補(bǔ)這類(lèi)缺憾,在WIN95/98中,VWIN32服務(wù)就是其中1種。VWIN32服務(wù)是通過(guò)1個(gè)VXD來(lái)實(shí)現(xiàn)的,它提供了裝備IO功能,通過(guò)它,使用API函數(shù)DeviceIoControl即可以實(shí)現(xiàn)WIN32利用程序和磁盤(pán)裝備驅(qū)動(dòng)程序間的通訊,從而實(shí)現(xiàn)對(duì)磁盤(pán)的存取。VWIN32提供的服務(wù)是1系列的控制命令字,它們實(shí)現(xiàn)諸如DOS操作系統(tǒng)下的INT13、INT25、INT26和INT21等功能調(diào)用。下面是它定義的1些控制命令字: VWIN32_DIOC_DOS_IOCTL (1) 實(shí)現(xiàn)INT21 功能 VWIN32_DIOC_DOS_INT25 (2) 實(shí)現(xiàn)INT25 功能 VWIN32_DIOC_DOS_INT26 (3) 實(shí)現(xiàn)INT26 功能 VWIN32_DIOC_DOS_INT13 (4) 實(shí)現(xiàn)INT13 功能 VWIN32_DIOC_DOS_DRIVEINFO (6) 實(shí)現(xiàn)INT21 730x 功能 如果要對(duì)磁盤(pán)進(jìn)行讀寫(xiě),只要使用DeviceIoControl履行相應(yīng)命令便可,下面的例子用來(lái)讀取軟盤(pán)的1個(gè)扇區(qū)(使用INT13): 第1步:打開(kāi)VWIN32服務(wù),HANDLE hDev=CreateFile("\.VWIN32",0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,NULL); 第2步:填充中斷所用到的相干寄存器。這里將寄存器放在1個(gè)結(jié)構(gòu)中,結(jié)構(gòu)定義以下(有關(guān)INT13使用的寄存器情況,請(qǐng)參閱相干資料): typedef struct INT13Regs{ PVOID buffer; // ebx 寄存器 BYTE Drive; // 磁
盤(pán)號(hào) dl BYTE Head; //磁
頭號(hào) dh WORD EDX_High; // edx 寄存器 BYTE Sector; //起
始扇區(qū) cl BYTE Track; //磁
道號(hào) ch WORD ECX_High; //ecx
寄存器 BYTE Number; //要
讀寫(xiě)的扇取數(shù) al BYTE CMD; //命
令:2--讀,3--寫(xiě),5--格式化 ah WORD EAX_High; //eax
寄存器 DWORD EDI; // edi 寄存器 DWORD ESI; // esi DWORD EFLAG; // flags }INT13_REGISTERS; unsigned char Buffer[512];//定義緩沖區(qū),放置讀取扇區(qū)數(shù)據(jù) INT13_REGISTERS reg={0};//定義寄存器結(jié)構(gòu)變量 reg.buffer =(void *)Buffer; reg.Drive =0;//0-軟盤(pán)A 1-軟盤(pán)B 0x80-硬盤(pán)c reg.Head =0; reg.Track=0; reg.Sector=1; reg.Number=1; reg.CMD=2; //讀
取 第3步:調(diào)用裝備IO API函數(shù)DeviceIoControl履行4號(hào)命令(即VWIN32_DIOC_DOS_INT13), BOOL b_ret=DeviceIoControl(hDev,4,®,sizeof(INT13_REGISTERS),®,sizeof(INT13_REGISTERS),&lpRet,0); 如果其返回值不等于零,調(diào)用成功,進(jìn)1步處理....否則調(diào)用失敗。 第4步:關(guān)閉服務(wù),CloseHandle(hDev); 3、限制或局限 上面是使用INT13讀取軟盤(pán)扇區(qū)的完全步驟,在WIN95/98下它是可以工作的。那末,是不是將上面的寄存器結(jié)構(gòu)中的Drive置為0x80就能夠讀取邏輯硬盤(pán)C盤(pán)的扇區(qū)了呢?回答是不是定的。INT13用來(lái)存取硬盤(pán)的功能在WINDOWS中被疏忽了。另外,INT25、INT26雖然可以存取硬盤(pán),但是它們不能工作在FAT32格式的硬盤(pán)上。下面的列表將詳細(xì)羅列與磁盤(pán)操作相干的中斷調(diào)用的限制情況(不特殊說(shuō)明,指的是在WIN95/98操作系統(tǒng)下): 中斷功能 限制及使用情況 INT13 不可以讀寫(xiě)硬盤(pán),僅支持軟盤(pán) INT25/INT26 不可以讀/寫(xiě)FAT32硬盤(pán),支持FAT12、FAT16 INT21(440DH⑷1H/61H) 不可用(文檔資料中說(shuō)支持FAT12、FAT16、FAT32,實(shí)際上沒(méi)有實(shí)現(xiàn)) INT21(7305H) 可以讀寫(xiě)軟盤(pán)、硬盤(pán),支持FAT12、FAT16、FAT32,但要求WIN95OSR2及以后版本 值得1提的是上表中的INT21-⑺305H功能是專(zhuān)門(mén)提供用來(lái)支持FAT32的,并且用來(lái)替換INT25/INT26,對(duì)應(yīng)的控制命令字是6(即VWIN32_DIOC_DOS_DRIVEINFO),它和INT13、INT25、INT26等中斷功能的1個(gè)顯著區(qū)分是:它不使用寄存器來(lái)傳遞參數(shù)(INT21-⑷40DH⑷1H/61H類(lèi)同),而是使用1個(gè)稱(chēng)為DISKIO的結(jié)構(gòu),寄存器EBX用來(lái)保存指向該結(jié)構(gòu)的地址。DISKIO的定義以下: typedef struct _DISKIO { DWORD dwStartSector; // 要讀寫(xiě)的起始扇區(qū)號(hào) WORD wSectors; // 要讀寫(xiě)的扇區(qū)數(shù) DWORD dwBuffer; // 用來(lái)保存讀/寫(xiě)數(shù)據(jù)的緩沖區(qū) }DISKIO, * PDISKIO; 另外,在使用該功能時(shí)還需要特別設(shè)置1些寄存器,如ECX必須為⑴,用ESI來(lái)表示讀寫(xiě)。下面的例子是使用該功能來(lái)實(shí)現(xiàn)上面的例子功能,即讀軟盤(pán)A的1個(gè)扇區(qū)。首先定義1個(gè)新的寄存器結(jié)構(gòu)供本例使用: typedef struct _DIOC_REGISTERS{ DWORD EBX; DWORD EDX; DWORD ECX; DWORD EAX; DWORD EDI; DWORD ESI; DWORD Flags; }DIOC_REGISTERS; 其實(shí)該結(jié)構(gòu)和上面的INT13_REGISTERS是1樣的,只不過(guò)INT13_REGISTERS將寄存器細(xì)分開(kāi)了,可讀性更強(qiáng)些。本例從步驟上說(shuō)和上面的例子相同,只有寄存器設(shè)置1步在內(nèi)容上有差異。 第1步:打開(kāi)VWIN32服務(wù)。 第2步:設(shè)置寄存器。 DIOC_REGISTERS reg = {0}; DISKIO dio; unsigned char Buffer[512]; //設(shè)
置參數(shù)結(jié)構(gòu) dio.dwStartSector = 0;//注意:和上例不同,不是1,從0開(kāi)始編號(hào) dio.wSectors = 1; dio.dwBuffer = (DWORD)Buffer; //設(shè)
置寄存器 reg.EAX = 0x7305; //功
能上類(lèi)似于INT25,絕對(duì)讀 reg.EBX = (DWORD)&dio;//參數(shù)結(jié)構(gòu)的地址 reg.ECX = ⑴;//必須是⑴ reg.EDX = 1; //注
意:和上例不同,驅(qū)動(dòng)器編號(hào)變了,0--缺省 1--A、2--B、3--C reg.ESI = 0; //ESI
的bit0表示讀寫(xiě),0--讀、1--寫(xiě) 在寫(xiě)狀態(tài)時(shí)SI的bit1--bit12,bit15必須是0,bit13、bit14、bit15共同來(lái)表示所寫(xiě)數(shù)據(jù)的類(lèi)型,具體見(jiàn)下表: 15 14 13 類(lèi)型描寫(xiě) 0 0 0 其它或不知道. 0 0 1 FAT數(shù)據(jù) 0 1 0 目錄數(shù)據(jù) 0 1 1 1般數(shù)據(jù) 1 x x 保存。bit15必須是0 第3步:調(diào)用API。BOOL b_ret=DeviceIoControl(hDev,6,®, sizeof(DIOC_REGISTERS),®,sizeof(DIOC_REGISTERS),&cb,0); 第4步:關(guān)閉服務(wù)。 可以發(fā)現(xiàn),兩種方法讀到的數(shù)據(jù)完全1致。 4、WIN2000中的磁盤(pán)扇區(qū)讀寫(xiě) 在WINNT和WIN2000中磁盤(pán)被看作1種標(biāo)準(zhǔn)裝備,可使用CreateFile象打開(kāi)文件1樣打開(kāi)并存取。CreateFile支持兩種方式的磁盤(pán)裝備--邏輯磁盤(pán)(格式為".C:")和物理磁盤(pán)(格式為".PHYSICALDRIVEx",其中x為數(shù)字),例如打開(kāi)A:盤(pán)進(jìn)行讀取操作,只要這樣: HANDLE hDev=CreateFile("\.A:",GENERIC_READ,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); 如果得到的句柄有效,就能夠使用ReadFile來(lái)讀取了, ReadFile(hDev,Buffer,512,&dwRet,0); 讀取結(jié)束要關(guān)閉該句柄, CloseHandle(hDev); 這比WIN95/98下的磁盤(pán)扇區(qū)讀取方便多了。 另外,上面的例子是操作邏輯磁盤(pán)的,它包括軟驅(qū)、硬盤(pán)分區(qū)等;物理磁盤(pán)指的是實(shí)際的硬盤(pán),它不關(guān)心該硬盤(pán)被分成幾個(gè)區(qū),硬盤(pán)的編號(hào)是從0開(kāi)始的,".PHYSICALDRIVE0"表示第1塊硬盤(pán),其它依此類(lèi)推。大家可能馬上會(huì)想起,利用這類(lèi)機(jī)制可以對(duì)硬盤(pán)的分區(qū)表進(jìn)行存取了。確切如此,此時(shí)即可以對(duì)硬盤(pán)的主引導(dǎo)扇區(qū)(獨(dú)立存在的1個(gè)扇區(qū),包括分區(qū)表信息,不同于磁盤(pán)分區(qū)的BOOT區(qū))進(jìn)行操作了。 unsigned char Buffer[512]={0}; HANDLE hDev=CreateFile("\.PHYSICALDRIVE0",GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); WriteFile(hDev,Buffer,512,&dwRet,0); CloseHandle(hDev); 危險(xiǎn)!??!千萬(wàn)別這么做!??! 5、1個(gè)自適應(yīng)的磁盤(pán)讀寫(xiě)類(lèi) 由上面的例子可以看出,不同的操作系統(tǒng)下對(duì)磁盤(pán)扇區(qū)的讀寫(xiě)有不同的方式,為了能夠在各類(lèi)操作系統(tǒng)下能夠使用統(tǒng)1的方法讀寫(xiě)磁盤(pán)扇區(qū),特設(shè)計(jì)了1個(gè)通用類(lèi)。該類(lèi)的設(shè)計(jì)思想以下:首先編寫(xiě)各類(lèi)操作系統(tǒng)下的磁盤(pán)扇區(qū)存取函數(shù),然后通過(guò)GetVersionEx來(lái)判斷操作系統(tǒng),進(jìn)而選取對(duì)應(yīng)的函數(shù)來(lái)實(shí)現(xiàn)磁盤(pán)扇區(qū)的讀寫(xiě)。由上面的分析可知,WINDOWS操作系統(tǒng)對(duì)INT13的支持是最差的,所以在這里只使用INT25、INT26、INT21-⑺305等中斷調(diào)用來(lái)實(shí)現(xiàn)。類(lèi)的定義以下: class CDiskInfo{ public: CDiskInfo(); ~CDiskInfo(); private: HANDLE hDev; DWORD dwCurrentPlatform; void GetPlatform(); //取
得操作系統(tǒng),并存入變量dwCurrentPlatform BOOL Win2000_AccessSectors(WORD CMD,BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff);//用于WIN2000、WINNT等操作系統(tǒng), BOOL Int25_ReadSectors(BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff); BOOL Int26_WriteSectors(BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff);//用于WIN95之前的操作系統(tǒng) BOOL Int21_AccessSectors(WORD CMD,BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff);//7305功能實(shí)現(xiàn),用于WIN95OSR2、WIN98等操作系統(tǒng) public: //對(duì)
外統(tǒng)1提供Read和Write操作,類(lèi)內(nèi)部根據(jù)平臺(tái)選用合適的函數(shù)調(diào)用 BOOL ReadSectors(BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff); BOOL WriteSectors(BYTE bDrive,DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff); }; 該類(lèi)對(duì)外提供了兩個(gè)接口,即ReadSectors和WriteSectors,其參數(shù)是1樣的,分別是要讀寫(xiě)的磁盤(pán)編號(hào)bDrive,要存取磁盤(pán)的開(kāi)始扇區(qū)號(hào)dwStartSector,要讀取的扇區(qū)數(shù)wSectors和讀寫(xiě)扇區(qū)數(shù)據(jù)的緩沖區(qū)lpSectBuff。這里磁盤(pán)編號(hào)是從1開(kāi)始的,即1代表A:,2代表B:,3代表C:,依此類(lèi)推。扇區(qū)的編號(hào)從0開(kāi)始。使用時(shí)也很簡(jiǎn)單,只要作以下聲明便可: BYTE Buffer[1024]; CDiskInfo A; BOOL bRet=A.ReadSectors(1,0,2,Buffer); 詳細(xì)情況見(jiàn)附帶的類(lèi)文件及測(cè)試程序。 6、補(bǔ)充說(shuō)明 嚴(yán)格來(lái)講,在對(duì)磁盤(pán)進(jìn)行讀寫(xiě)時(shí),應(yīng)當(dāng)遵守以下順序:打開(kāi)裝備(WIN95/98下為VWIN32服務(wù),WIN2000下為磁盤(pán)裝備)、鎖卷、驗(yàn)證卷的有效性、讀/寫(xiě)、開(kāi)鎖卷、關(guān)閉裝備。這里為了描寫(xiě)上的簡(jiǎn)潔,疏忽了鎖卷/開(kāi)鎖卷及驗(yàn)證有效性等操作。有興趣的朋友可以自行添加。 另外,該類(lèi)僅實(shí)現(xiàn)了邏輯驅(qū)動(dòng)器的讀寫(xiě),要想實(shí)現(xiàn)諸如對(duì)物理硬盤(pán)的主引導(dǎo)扇區(qū)的讀寫(xiě),還需要其它技術(shù),如thunk技術(shù),即編寫(xiě)兩個(gè)動(dòng)態(tài)庫(kù),1個(gè)是WIN32動(dòng)態(tài)庫(kù),1個(gè)是WIN16動(dòng)態(tài)庫(kù)(thunk技術(shù)只可以用動(dòng)態(tài)庫(kù)實(shí)現(xiàn)),其中WIN16動(dòng)態(tài)庫(kù)轉(zhuǎn)到DPMI模式,調(diào)用INT13(或擴(kuò)大INT13)來(lái)實(shí)現(xiàn)物理磁盤(pán)扇區(qū)的讀寫(xiě)。有關(guān)thunk技術(shù)請(qǐng)參閱相干文檔資料。 所有的例子在WIN98、WIN2000操作系統(tǒng)、VC6集成環(huán)境下調(diào)試通過(guò)。
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
------分隔線----------------------------
------分隔線----------------------------