diff --git a/src/common/impl/FFPlatform_windows.c b/src/common/impl/FFPlatform_windows.c index b60f551d0..9edb26db3 100644 --- a/src/common/impl/FFPlatform_windows.c +++ b/src/common/impl/FFPlatform_windows.c @@ -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; diff --git a/src/common/impl/library.c b/src/common/impl/library.c index 8a47a1039..ee3626b45 100644 --- a/src/common/impl/library.c +++ b/src/common/impl/library.c @@ -1,6 +1,13 @@ #include "fastfetch.h" #include "common/library.h" +#if _WIN32 +#include "common/debug.h" +#include "common/windows/nt.h" +#include +#include +#endif + #ifndef FF_DISABLE_DLOPEN #include @@ -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 diff --git a/src/common/library.h b/src/common/library.h index 0a6729081..9c4ee7282 100644 --- a/src/common/library.h +++ b/src/common/library.h @@ -6,11 +6,10 @@ #ifndef FF_DISABLE_DLOPEN #if defined(_WIN32) - #include #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 #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 diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index ea8e5ea70..5767b8d4c 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -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 +); diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp index c90195972..eadf21efb 100644 --- a/src/detection/brightness/brightness_windows.cpp +++ b/src/detection/brightness/brightness_windows.cpp @@ -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) diff --git a/src/detection/opengl/opengl_windows.c b/src/detection/opengl/opengl_windows.c index 50e0e88da..8e86ad475 100644 --- a/src/detection/opengl/opengl_windows.c +++ b/src/detection/opengl/opengl_windows.c @@ -1,6 +1,7 @@ #include "opengl.h" #include "common/library.h" #include "common/printing.h" +#include "common/windows/nt.h" #include #include @@ -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, diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c index 32ec92da9..ecc5f21c2 100644 --- a/src/detection/tpm/tpm_windows.c +++ b/src/detection/tpm/tpm_windows.c @@ -1,6 +1,7 @@ #include "tpm.h" #include "common/library.h" +#include #include #include