日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

《Undocumented Windows 2000 Secrets》翻譯 --- 3( 四 )


{
if (dCount <= dSize)
{
dCount /= sizeof( HMODULE );
break;
}
}
else
{
dCount = 0;
}
phList = dbgMemoryDestroy(phList);
if ( !(dSize = dCount) ) break;
}
}
if ( pdCount != NULL) *pdCount = dCount;
return phList;
}
列表1-7; 枚舉進(jìn)程模塊
EnumProcessModules()返回指定進(jìn)程所有模塊的句柄的引用 。在Windows 2000中,一個(gè)HMODULE只是簡(jiǎn)單的模塊映像基址 。在SDK頭文件windef.h中,HMODULE被定義為HINSTANCE的別名,二者都是HANDLE類型 。嚴(yán)格的來講HMODULE并不是一個(gè)句柄 。通常,句柄是系統(tǒng)管理的一個(gè)表的索引,可通過此表來查找對(duì)象屬性 。系統(tǒng)返回的所有句柄都有一個(gè)與特定對(duì)象相關(guān)的計(jì)數(shù)器,在一個(gè)對(duì)象的所有句柄沒有返回系統(tǒng)時(shí),該對(duì)象不能從內(nèi)存中被移除 。Win32 API提供了CloseHandle()函數(shù)用于關(guān)閉句柄 。該函數(shù)與Native API NtClose()等價(jià) 。有關(guān)HMODULEs最重要的事情是,這些“handles”不需要關(guān)閉 。
另一件讓人困惑的事是,事實(shí)上,模塊句柄通常并不被保證是一直有效的 。SDK的GetModuleHandle()函數(shù)文檔提示到,在多線程程序中必須更加注意模塊句柄,因?yàn)橐粋€(gè)線程可以通過卸載HMODULE引用的模塊而讓另一個(gè)線程擁有的HMODULE無效 。在多任務(wù)環(huán)境下,一個(gè)程序(如調(diào)試器)使用另一程序的模塊句柄時(shí)也許注意這一點(diǎn) 。這似乎使HMODULEs沒有多大用處了,但是,在下面兩種情況中,HMODULE的有效性會(huì)保持足夠長的時(shí)間:
1.由LoadLibrary()或LoadLibraryEx()返回的HMODULE在進(jìn)程調(diào)用FreeLibrary()之前都會(huì)一直有效,由于這些函數(shù)包含了模塊引用計(jì)數(shù),所以即使在多線程程序中,這也會(huì)阻止模塊被意外卸載 。
2.如果HMODULE指向的模塊會(huì)永久的存在,那么它也會(huì)一直有效 。例如,所有Windows 2000內(nèi)核組件(不包括內(nèi)核模式的驅(qū)動(dòng)程序)總是被映射到每個(gè)進(jìn)程的相同固定地址上,并且在進(jìn)程生命期里一直在那里 。
不幸地是,這些情況并不適用于EnumProcessModules()函數(shù)返回的模塊句柄,至少通常不行 。復(fù)制到調(diào)用者提供的緩沖區(qū)中的HMODULE,在獲取進(jìn)程快照那一刻其所表示映像基址是有效的 。稍后,進(jìn)程可能調(diào)用FreeLibrary()來釋放一個(gè)或多個(gè)模塊,并將其從內(nèi)存中移除,此時(shí)它們的句柄將無效,隨后進(jìn)程很有可能立即調(diào)用LoadLibrary()加載了另一個(gè)DLL,而此新模塊恰好映射到了前面釋放的地址上 。這看上去是不是很熟悉?是的,同樣的問題也存在于EnumDeviceDrivers()的指針數(shù)組和EnumProcesses()函數(shù)的ID數(shù)組 。不過,這些問題是可以避免的 。psapid.dll通過調(diào)用未文檔化的API函數(shù)來完成數(shù)據(jù)收集工作后,考慮這些數(shù)據(jù)的完整性,可返回一個(gè)完整的請(qǐng)求對(duì)象的快照,其中應(yīng)包括所有感興趣的屬性信息 。這樣就沒有必要在稍后調(diào)用另一個(gè)函數(shù)來獲取附加的信息了 。我的觀點(diǎn)是,psapi.dll的設(shè)計(jì)過于簡(jiǎn)單,因?yàn)樗雎粤藬?shù)據(jù)的完整性,這也是我不會(huì)將此DLL作為一個(gè)專業(yè)調(diào)試工具的基礎(chǔ)的原因 。
與EnumDeviceDrivers()和EnunProcesses()函數(shù)相比EnumProcessModules()函數(shù)算是個(gè)好公民了,因?yàn)槿绻{(diào)用者提供的緩沖區(qū)不能放下全部的輸出數(shù)據(jù),它會(huì)準(zhǔn)確地提示有多少字節(jié)沒有復(fù)制 。注意列表1-7沒有包括一個(gè)循環(huán),在那里緩沖區(qū)會(huì)不斷增大直到足夠的大 。然而,仍然需要trial-and-error循環(huán),因?yàn)樵谙乱淮握{(diào)用時(shí),EnumProcessModules報(bào)告的所需大小可能已經(jīng)無效了(如果指定進(jìn)程在兩次調(diào)用之間又加載了新的模塊) 。因此,列表1-7中的代碼將不斷枚舉模塊直到EnumProcessModules()報(bào)告需要的緩沖區(qū)等于或小于實(shí)際可用大小,或者出現(xiàn)了錯(cuò)誤 。
我不想描述EnumProcessModules()的等價(jià)函數(shù),因?yàn)樵摵瘮?shù)要比EnumDeviceDrivers和EnumProcesses稍微復(fù)雜些,它涉及幾個(gè)未文檔化的數(shù)據(jù)結(jié)構(gòu) ?;旧?,它還是通過調(diào)用NtQuerySystemInformation()函數(shù)(當(dāng)然,該函數(shù)也沒有文檔化)來獲取目標(biāo)進(jìn)程環(huán)境塊(PEB)的地址,通過該地址可獲取一個(gè)模塊信息鏈表 。因?yàn)椴还苁荘EB還是這個(gè)鏈表在調(diào)用進(jìn)程的地址空間都是無法直接使用的,EnumProcessModules調(diào)用Win32 API ReadProcessMemory()(該函數(shù)有文檔記載)來遍歷目標(biāo)進(jìn)程的地址空間 。順便說一下,PEB結(jié)構(gòu)的布局將在第7章討論,在附錄C中,可以找到該結(jié)構(gòu)的定義 。

推薦閱讀