How to load GetMappedFileName correctly based on windows version

可紊 提交于 2020-01-02 07:08:18

问题


MSDN's remarks section, described here, specifically mentions there is a difference between the loading types of the following function.

Since my module is portable and loads models dynamically, I'm not allowed / able to use any pre-processors commands:

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

In addition -

Kernel32.dll on Windows 7 and Windows Server 2008 R2; Psapi.dll (if PSAPI_VERSION=1) on Windows 7 and Windows Server 2008 R2; Psapi.dll on Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP

Doesn't make it much clearer of how windows version is exactly coordinated with the PSAPI version.


回答1:


The GetMappedFileName() documentation specifically says:

Starting with Windows 7 and Windows Server 2008 R2, Psapi.h establishes version numbers for the PSAPI functions. The PSAPI version number affects the name used to call the function and the library that a program must load.

If PSAPI_VERSION is 2 or greater, this function is defined as K32GetMappedFileName in Psapi.h and exported in Kernel32.lib and Kernel32.dll. If PSAPI_VERSION is 1, this function is defined as GetMappedFileName in Psapi.h and exported in Psapi.lib and Psapi.dll as a wrapper that calls K32GetMappedFileName.

Programs that must run on earlier versions of Windows as well as Windows 7 and later versions should always call this function as GetMappedFileName. To ensure correct resolution of symbols, add Psapi.lib to the TARGETLIBS macro and compile the program with -DPSAPI_VERSION=1. To use run-time dynamic linking, load Psapi.dll.

If static linking is not an option for you, and you need to dynamically load the function at runtime without using #ifdef statements, then simply check both DLLs unconditionally, eg:

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);

Or, just do what the documentation says - simply ignore kernel32 altogether and just use psapi.dll by itself on all Windows versions. On Windows 7 and later, psapi.GetMappedFileNameW() is a wrapper for 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);


来源:https://stackoverflow.com/questions/29369597/how-to-load-getmappedfilename-correctly-based-on-windows-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!