c++ - renamer - Cómo cargar GetMappedFileName correctamente según la versión de Windows
tag rename (1)
La sección de observaciones de MSDN, descrita aquí , menciona específicamente que existe una diferencia entre los tipos de carga de la siguiente función.
Como mi módulo es portátil y carga modelos dinámicamente, no puedo / puedo usar ningún comando de preprocesador:
#if (PSAPI_VERSION == 2)
(GetProcAddress("kernel32.dll", OBFUSCATE(L"K32GetMappedFileNameW")));
#elif (PSAPI_VERSION == 1)
(GetProcAddress("psapi.dll", OBFUSCATE(L"GetMappedFileNameW")));
#endif
En adición -
Kernel32.dll en Windows 7 y Windows Server 2008 R2; Psapi.dll (si PSAPI_VERSION = 1) en Windows 7 y Windows Server 2008 R2; Psapi.dll en Windows Server 2008, Windows Vista, Windows Server 2003 y Windows XP
No deja mucho más claro cómo la versión de Windows está coordinada exactamente con la versión de PSAPI.
La documentación de GetMappedFileName()
dice específicamente:
Comenzando con Windows 7 y Windows Server 2008 R2, Psapi.h establece números de versión para las funciones de PSAPI. El número de versión de PSAPI afecta el nombre utilizado para llamar a la función y la biblioteca que debe cargar un programa .
Si PSAPI_VERSION es 2 o mayor, esta función se define como K32GetMappedFileName en Psapi.h y se exporta en Kernel32.lib y Kernel32.dll . Si PSAPI_VERSION es 1, esta función se define como GetMappedFileName en Psapi.h y se exporta en Psapi.lib y Psapi.dll como un contenedor que llama a K32GetMappedFileName .
Los programas que deben ejecutarse en versiones anteriores de Windows y en Windows 7 y versiones posteriores siempre deben llamar a esta función como GetMappedFileName. Para garantizar la resolución correcta de los símbolos, agregue Psapi.lib a la macro TARGETLIBS y compile el programa con -DPSAPI_VERSION = 1. Para usar el enlace dinámico en tiempo de ejecución, cargue Psapi.dll.
Si la vinculación estática no es una opción para usted, y necesita cargar dinámicamente la función en tiempo de ejecución sin utilizar sentencias #ifdef
, simplemente verifique ambas DLL incondicionalmente, por ejemplo:
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);
O simplemente haga lo que dice la documentación: simplemente ignore kernel32 por completo y simplemente use psapi.dll por sí mismo en todas las versiones de Windows. En Windows 7 y psapi.GetMappedFileNameW()
posteriores, psapi.GetMappedFileNameW()
es un contenedor para 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);