如何根据windows版本正确加载GetMappedFileName

How to load GetMappedFileName correctly based on windows version

本文关键字:加载 GetMappedFileName 版本 何根 windows      更新时间:2023-10-16

MSDN的备注部分在这里描述,特别提到以下函数的加载类型之间存在差异。

由于我的模块是可移植的,并且动态加载模型,所以我不允许/不能使用任何预处理器命令:

#if (PSAPI_VERSION == 2)
            (GetProcAddress("kernel32.dll", OBFUSCATE(L"K32GetMappedFileNameW")));
#elif (PSAPI_VERSION == 1)
            (GetProcAddress("psapi.dll", OBFUSCATE(L"GetMappedFileNameW")));
#endif

此外-

Windows 7和Windows Server 2008 R2上的Kernel32.dll;Psapi.dll(如果PSAPI_VERSION=1)在Windows 7和Windows Server 2008 R2上;上的Psapi.dllWindows Server 2008、Windows Vista、Windows Server 2003和WindowsXP

并没有让我们更清楚地了解windows版本是如何与PSAPI版本精确协调的。

GetMappedFileName()文档特别指出:

从Windows7和WindowsServer2008R2开始,Psapi.h为Psapi函数建立版本号PSAPI版本号影响用于调用函数的名称以及程序必须加载的库

如果PSAPI_VERSION为2或更大,则此函数在PSAPI.h中定义为K32GetMappedFileName,并在Kernel32.lib和Kernel32.dll中导出。如果PSAPI_VERSION为1,则此功能在PSAPI.h中定义为GetMappedFileNName,并在PSAPI.lib和PSAPI.dll中导出为调用K32GetMappedFileName的包装器。

必须在早期版本的Windows以及Windows 7及更高版本上运行的程序应始终将此函数调用为GetMappedFileName。为了确保符号的正确分辨率,请将Psapi.lib添加到TARGETLIBS宏中,并使用-DSAPI_VERSION=1编译程序。要使用运行时动态链接,请加载Psapi.dll。

如果静态链接不适合您,并且您需要在运行时动态加载函数而不使用#ifdef语句,那么只需无条件地检查两个DLL,例如:

typedef DWORD WINAPI (*LPFN_GetMappedFileNameW)(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize);
HINSTANCE hPsapi = NULL;
LPFN_GetMappedFileNameW lpGetMappedFileNameW = NULL; 
...
lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(GetModuleHandle("kernel32.dll"), L"K32GetMappedFileNameW"));
if (lpGetMappedFileNameW == NULL)
{
    hPsapi = LoadLibraryW(L"psapi.dll");
    lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(hPsapi, L"GetMappedFileNameW");
}
// use lpGetMappedFileNameW() as needed ...
if (hPsapi)
    FreeLibrary(hPsapi);

或者,按照文档所说的去做——完全忽略kernel32,在所有Windows版本上单独使用psapi.dll。在Windows7及更高版本上,psapi.GetMappedFileNameW()kernel32.K32GetMappedFileNameW()的包装器。

typedef DWORD WINAPI (*LPFN_GetMappedFileNameW)(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize);
HINSTANCE hPsapi = NULL;
LPFN_GetMappedFileNameW lpGetMappedFileNameW = NULL;
...
hPsapi = LoadLibraryW(L"psapi.dll");
lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(hPsapi, L"GetMappedFileNameW");
// use lpGetMappedFileNameW() as needed ...
FreeLibrary(hPsapi);