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

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


*lpcbNeeded = i*sizeof(DWORD);
fOk = TRUE;
}
LocalFree(psmi);
if ( !fOk ); SetLastError( RtlNtStatusToDosError(ns) );
}
}
else
SetLastError( RtlNtStatusToDosError(ns) );
return fOk;
}
列表1-4; EnumDeviceDrivers函數(shù)的示列
列表1-4列出了EnumDeviceDrivers()一種可能的實(shí)現(xiàn)方式 。注意這并不是來(lái)自psapi.dll的原始代碼 。但通過(guò)C編譯器它可以變成等效的二進(jìn)制代碼 。為了保持簡(jiǎn)單干凈,我省略了源代碼中易分散注意力的細(xì)節(jié),比如結(jié)構(gòu)化異常等 。在列表1-4的中間,你會(huì)看到NtQuerySystemInformation()函數(shù)作了很多工作 。這是我非常喜歡的Windows 2000函數(shù)之一,因?yàn)樵摵瘮?shù)可以訪問(wèn)多種重要的數(shù)據(jù)結(jié)構(gòu),如驅(qū)動(dòng)、進(jìn)程、線程、句柄(handle)和LPC端口列表等等 。我的文章“Inside Windows NT Sytem Data”(出版于1999年11月的Dr.Dobb’s Journal)在第一時(shí)間提供了有關(guān)該函數(shù)的內(nèi)部信息及其搭檔函數(shù)NtSetSystemInformation()的文檔化資料 。另外的全面講述這兩個(gè)函數(shù)的文檔可以在Gary Nebbett的《Indispendsable Windows NT/2000 Native API Reference》中找到 。
不要過(guò)于擔(dān)心列表1-4列出的EnumDeviceDrivers()函數(shù)的實(shí)現(xiàn)細(xì)節(jié) 。我增加這些代碼片斷只是為了例舉該函數(shù)有趣的一面,這像一根紅線貫穿于psapi.dll 。在使用SystemModuleInformation標(biāo)志第二次調(diào)用NtQuerySystemInformation()獲取了完整的驅(qū)動(dòng)列表后,代碼遍歷驅(qū)動(dòng)模塊數(shù)組并將其pImageBase成員復(fù)制到調(diào)用者提供的指針數(shù)組(名為lpImageBase[])中 。這似乎很正確,但除非你不知道NtQuerySystemInformation提供的模塊數(shù)組所包含的其他信息 。這些數(shù)據(jù)結(jié)構(gòu)都是沒(méi)有文檔化的,但是我現(xiàn)在可以告訴你,這些信息同樣是有關(guān)模塊在內(nèi)存中的大小、它們的路徑和名稱(chēng)、引用計(jì)數(shù)(load counts)和其他一些標(biāo)志信息的 。甚至文件名在路徑中的偏移量也是很容易就能得到的!,EnumDeviceDrivers()殘忍的丟掉了所有這些有用的信息,僅僅保留了映像基址(Image Base address) 。
所以如果你試圖通過(guò)返回的指針來(lái)獲取有關(guān)模塊的更多信息,則肯定會(huì)失敗 。當(dāng)你調(diào)用GetDeviceDriverFileName()來(lái)獲取指定映像基址對(duì)應(yīng)的文件路徑時(shí),猜猜psapi.dll會(huì)怎樣做?它會(huì)運(yùn)行與列表1-4類(lèi)似的代碼來(lái)獲取完整的驅(qū)動(dòng)列表,并遍歷該列表來(lái)尋找指定的映像基址 。如果它找到一個(gè)匹配項(xiàng),就將其路徑復(fù)制到調(diào)用者的緩沖區(qū)中 。這難道很高效嗎?為什么EnumDeviceDrivers不在它首次遍歷驅(qū)動(dòng)列表時(shí)就復(fù)制路徑呢?按這樣的方式實(shí)現(xiàn)此函數(shù)并沒(méi)有多么困難 。除去性能問(wèn)題,這種設(shè)計(jì)還有另一個(gè)潛在的問(wèn)題:如果在GetDeviceDriverFileName()執(zhí)行之前指定的模塊就已經(jīng)被卸載了會(huì)怎么樣呢?該模塊的地址將不會(huì)出現(xiàn)在第二次獲取的驅(qū)動(dòng)列表中,GetDeviceDriverFileName()將會(huì)失敗 。我真不明白微軟為什么會(huì)發(fā)布這樣的DLL 。
枚舉活動(dòng)進(jìn)程
psapi.dll的另一個(gè)典型工作就是枚舉當(dāng)前系統(tǒng)中運(yùn)行的進(jìn)程 。為此目的,該DLL提供了EnumProcesses()函數(shù) 。該函數(shù)的工作與EnumDeviceDrivers()十分類(lèi)似,不過(guò)返回的是進(jìn)程ID而不是虛擬地址了 。再次提示,該函數(shù)并不會(huì)提示緩沖區(qū)大小不足,因此我們還需再次使用trial-and-error循環(huán),如列表1-5所示,這些代碼和列表1-3很相似,除了有些不同的符號(hào)和類(lèi)型名稱(chēng) 。
一個(gè)進(jìn)程ID是一個(gè)全局?jǐn)?shù)字標(biāo)簽可在整個(gè)系統(tǒng)中唯一標(biāo)識(shí)一個(gè)進(jìn)程 。進(jìn)程和線程ID都取自同一個(gè)數(shù)字池(pool of numbers),從以0開(kāi)始的Idle進(jìn)程,在同一時(shí)間,所有運(yùn)行的進(jìn)程和線程都不會(huì)有相同的ID 。但是,當(dāng)一個(gè)進(jìn)程結(jié)束后,另一個(gè)進(jìn)程可能會(huì)再次使用該結(jié)束進(jìn)程或線程的ID 。因此,在X時(shí)間獲取的一個(gè)進(jìn)程ID在Y時(shí)間可能會(huì)代表另一個(gè)完全不同的進(jìn)程 。也有可能在其使用的那一刻還沒(méi)有定義或者指定給了某個(gè)線程 。所以,EnumProcesses()返回一個(gè)簡(jiǎn)單的進(jìn)程ID列表并不能可靠的代表當(dāng)前系統(tǒng)活動(dòng)進(jìn)程的快照 。如果考慮該函數(shù)的實(shí)現(xiàn)方式,這個(gè)設(shè)計(jì)缺陷真是無(wú)法原諒 。列表1-6是psapi.dll另一個(gè)函數(shù)的克隆,大致勾勒出了EnumProcessees()的基本動(dòng)作 。和EnumDeviceDrivers()類(lèi)似,它也依賴(lài)NtQuerySystemInformation()函數(shù),不過(guò)在調(diào)用時(shí),用SystemProcessInformation代替了SystemModuleInformation 。注意列表1-6中間的循環(huán),在哪兒lpidProcess[]數(shù)組被來(lái)自SYSTEM_PROCESS_INFORMATION結(jié)構(gòu)中的數(shù)據(jù)填充 。沒(méi)什么好驚奇的,該結(jié)構(gòu)也沒(méi)有文檔化 。

推薦閱讀