Library (Windows): prefers Ldr APIs

This commit is contained in:
李通洲
2026-03-19 15:24:55 +08:00
parent bab1e4ff82
commit 86cfa4eded
7 changed files with 128 additions and 14 deletions
+1 -1
View File
@@ -199,7 +199,7 @@ static void getUserShell(FFPlatform* platform)
static const char* detectWine(void)
{
const char * __cdecl wine_get_version(void);
HMODULE hntdll = GetModuleHandleW(L"ntdll.dll");
void* hntdll = ffLibraryGetModule(L"ntdll.dll");
if (!hntdll) return NULL;
FF_LIBRARY_LOAD_SYMBOL_LAZY(hntdll, wine_get_version);
if (!ffwine_get_version) return NULL;
+86 -1
View File
@@ -1,6 +1,13 @@
#include "fastfetch.h"
#include "common/library.h"
#if _WIN32
#include "common/debug.h"
#include "common/windows/nt.h"
#include <errno.h>
#include <ntstatus.h>
#endif
#ifndef FF_DISABLE_DLOPEN
#include <stdarg.h>
@@ -36,7 +43,7 @@ static void* libraryLoad(const char* path, int maxVersion)
if (pathLen == instance.state.platform.exePath.length)
return result;
char absPath[MAX_PATH + 1];
char absPath[MAX_PATH * 2];
strcpy(mempcpy(absPath, instance.state.platform.exePath.chars, pathLen + 1), path);
return dlopen(absPath, FF_DLOPEN_FLAGS);
@@ -92,3 +99,81 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...)
}
#endif
#if _WIN32
void* dlopen(const char* path, FF_MAYBE_UNUSED int mode)
{
wchar_t pathW[MAX_PATH + 1];
ULONG pathWBytes = 0;
NTSTATUS status = RtlUTF8ToUnicodeN(pathW, sizeof(pathW), &pathWBytes, path, (uint32_t)strlen(path) + 1);
if (!NT_SUCCESS(status))
{
FF_DEBUG("RtlUTF8ToUnicodeN failed for path %s with status 0x%08lX: %s", path, status, ffDebugNtStatus(status));
return NULL;
}
PVOID module = NULL;
status = LdrLoadDll(NULL, NULL, &(UNICODE_STRING) {
.Length = (USHORT) pathWBytes - sizeof(wchar_t), // Exclude null terminator
.MaximumLength = (USHORT) pathWBytes,
.Buffer = pathW,
}, &module);
if (!NT_SUCCESS(status))
{
FF_DEBUG("LdrLoadDll failed for path %s with status 0x%08lX: %s", path, status, ffDebugNtStatus(status));
return NULL;
}
return module;
}
int dlclose(void* handle)
{
NTSTATUS status = LdrUnloadDll(handle);
if (!NT_SUCCESS(status))
{
FF_DEBUG("LdrUnloadDll failed for handle %p with status 0x%08lX: %s", handle, status, ffDebugNtStatus(status));
return -1;
}
return 0;
}
void* dlsym(void* handle, const char* symbol)
{
void* address;
USHORT symbolBytes = (USHORT) strlen(symbol) + 1;
NTSTATUS status = LdrGetProcedureAddress(handle, &(ANSI_STRING) {
.Length = symbolBytes - sizeof(char),
.MaximumLength = symbolBytes,
.Buffer = (char*) symbol,
}, 0, &address);
if (!NT_SUCCESS(status))
{
FF_DEBUG("LdrGetProcedureAddress failed for symbol %s with status 0x%08lX: %s", symbol, status, ffDebugNtStatus(status));
return NULL;
}
return address;
}
void* ffLibraryGetModule(const wchar_t* libraryFileName)
{
assert(libraryFileName != NULL && "Use \"ffGetPeb()->ImageBaseAddress\" instead");
void* module = NULL;
USHORT libraryFileNameBytes = (USHORT) (wcslen(libraryFileName) * sizeof(wchar_t)) + sizeof(wchar_t);
NTSTATUS status = LdrGetDllHandle(NULL, NULL, &(UNICODE_STRING) {
.Length = libraryFileNameBytes - sizeof(wchar_t),
.MaximumLength = libraryFileNameBytes,
.Buffer = (wchar_t*) libraryFileName,
}, &module);
if (!NT_SUCCESS(status))
{
FF_DEBUG("LdrGetDllHandle failed for library %ls with status 0x%08lX: %s", libraryFileName, status, ffDebugNtStatus(status));
return NULL;
}
return module;
}
#endif
+11 -9
View File
@@ -6,11 +6,10 @@
#ifndef FF_DISABLE_DLOPEN
#if defined(_WIN32)
#include <libloaderapi.h>
#define FF_DLOPEN_FLAGS 0
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
FF_C_NODISCARD static inline void* dlsym(void* handle, const char* symbol) { return (void*) GetProcAddress((HMODULE)handle, symbol); }
static inline int dlclose(void* handle) { return !FreeLibrary((HMODULE)handle); }
FF_C_NODISCARD void* dlopen(const char* path, int mode);
FF_C_NODISCARD void* dlsym(void* handle, const char* symbol);
int dlclose(void* handle);
#else
#include <dlfcn.h>
#endif
@@ -30,6 +29,10 @@ static inline void ffLibraryUnload(void** handle)
dlclose(*handle);
}
#if __cplusplus
#define __auto_type auto
#endif
#define FF_LIBRARY_SYMBOL(symbolName) \
__typeof__(&symbolName) ff ## symbolName;
@@ -38,13 +41,8 @@ static inline void ffLibraryUnload(void** handle)
if(libraryObjectName == NULL) \
return returnValue;
#if _WIN32
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
FF_LIBRARY_LOAD(libraryObjectName, "LoadLibraryA(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)
#else
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
FF_LIBRARY_LOAD(libraryObjectName, "dlopen(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)
#endif
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
symbolMapping = (__typeof__(&symbolName)) dlsym(library, #symbolName); \
@@ -106,3 +104,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...);
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff ## symbolName, symbolName, returnValue);
#endif
#if _WIN32
void* ffLibraryGetModule(const wchar_t* libraryFileName);
#endif
+25
View File
@@ -1249,3 +1249,28 @@ NTSYSAPI NTSTATUS NTAPI NtOpenProcess(
_In_ PCOBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientId
);
NTSYSAPI NTSTATUS NTAPI LdrLoadDll(
_In_opt_ PCWSTR DllPath,
_In_opt_ PULONG DllCharacteristics,
_In_ PCUNICODE_STRING DllName,
_Out_ PVOID *DllHandle
);
NTSYSAPI NTSTATUS NTAPI LdrUnloadDll(
_In_ PVOID DllHandle
);
NTSYSAPI NTSTATUS NTAPI LdrGetDllHandle(
_In_opt_ PCWSTR DllPath,
_In_opt_ PULONG DllCharacteristics,
_In_ PCUNICODE_STRING DllName,
_Out_ PVOID *DllHandle
);
NTSYSAPI NTSTATUS NTAPI LdrGetProcedureAddress(
_In_ PVOID DllHandle,
_In_opt_ PCANSI_STRING ProcedureName,
_In_opt_ ULONG ProcedureNumber,
_Out_ PVOID *ProcedureAddress
);
@@ -63,8 +63,8 @@ static const char* detectWithWmi(FFlist* result)
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result)
{
HMODULE gdi32 = GetModuleHandleW(L"gdi32.dll");
if (!gdi32) return "GetModuleHandleW(gdi32.dll) failed";
void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
if (!gdi32) return "ffLibraryGetModule(gdi32.dll) failed";
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)
+2 -1
View File
@@ -1,6 +1,7 @@
#include "opengl.h"
#include "common/library.h"
#include "common/printing.h"
#include "common/windows/nt.h"
#include <windows.h>
#include <GL/gl.h>
@@ -81,7 +82,7 @@ static const char* wglDetectOpenGL(FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglDeleteContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
HINSTANCE hInstance = GetModuleHandleW(NULL);
HINSTANCE hInstance = ffGetPeb()->ImageBaseAddress;
WNDCLASSW wc = {
.lpfnWndProc = DefWindowProcW,
+1
View File
@@ -1,6 +1,7 @@
#include "tpm.h"
#include "common/library.h"
#include <windef.h>
#include <tbs.h>
#include <winerror.h>