-
Program Files 的重定向
很多開發人員都知道,在 64 位 Windows 系統上,32 位程序是無法獲取得到 C:\Program Files 的完整路徑的,只能獲取到 C:\Program Files (x86)。不管你用的是什么方法:
TCHAR szPath[MAX_PATH] = { 0 }; ExpandEnvironmentStrings(_T("%ProgramFiles%"), szPath, MAX_PATH);又或者是:
SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAM_FILES, FALSE);
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, szPath);
這個問題在 Windows NT 6.0 (Windows Vista) 之前的系統上無解,只有 64 程序可以拿到這個路徑。Windows NT 6.0 開始,微軟對此進行了重新設計,以前稱作「Special Folders」(特殊文件夾)的系統文件夾有了一個全新的名字,叫「Known Folders」(已知文件夾),同時提供了一套新的接口,包括 Windows API 函數 SHGetKnownFolderPath,COM 接口 IKnownFolder 和 IKnownFolderManager 來管理這些系統文件夾,原來的 CSIDL(Constant Special Item ID list)系列整數值也被一套新的「KNOWNFOLDERID」系列 GUID 所代替,可以獲取得到的文件夾數量比以前也更多,而且隨着 Windows 的版本越來越高,可獲取的文件夾路徑也越來越多。如,程序可以直接通過 FOLDERID_QuickLaunch 獲取 Quick Launch(快速啟動),以及通過 FOLDERID_LocalAppDataLow 獲取 LocalLow 等路徑。不過,經測試,32 位程序使用下面的代碼仍然無法獲取到 C:\Program Files。
PWSTR pszPath = NULL; HRESULT hr = SHGetKnownFolderPath(FOLDERID_ProgramFilesX64, 0, NULL, &pszPath); if (hr == S_OK) { CoTaskMemFree((void *)pszPath); }在 64 位系統上,上面的代碼編譯為 32 位程序,結果依然是失敗。多年來,經過多次不懈的搜索,終於找到 32 位程序在 64 位系統上獲取 C:\Program Files 的方法:
TCHAR szPath[MAX_PATH] = { 0 }; ExpandEnvironmentStrings(_T("%ProgramW6432%"), szPath, MAX_PATH);雖然說這個環境變量並無法在批處理和命令行中使用。個人猜測,這個環境變量僅在 64 位系統上的 32 位程序中有效。而 64 位系統的 cmd 也是 64 位,自然批處理中無法使用環境變量。經測試,Windows XP x64 Edition 也能通過這個方法得到該路徑。
-
System32 的重定向
System32 重定向和 Program Files 不同的是,System32 的重定向是底層實現的,即 32 位程序顯式的指定向 System32 文件夾寫入,實際還是寫入到 SysWOW64。而 32 位程序在擁有權限的情況下,向 Program Files 寫入並不會被重定向到 Program Files (x86)。向 System32 和 Program Files 兩個文件夾中寫入數據的相同點是都需要管理員權限,否則無法寫入。System32 的重定向是可以通過以下的 API 來更改:
PVOID lpOldValue = NULL; if (Wow64DisableWow64FsRedirection(&lpOldValue)) { // 調用 CreateFile、_open、fopen 等 Wow64RevertWow64FsRedirection(lpOldValue); }
