Skip to content

Commit 86cfa4e

Browse files
committed
Library (Windows): prefers Ldr APIs
1 parent bab1e4f commit 86cfa4e

7 files changed

Lines changed: 128 additions & 14 deletions

File tree

src/common/impl/FFPlatform_windows.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ static void getUserShell(FFPlatform* platform)
199199
static const char* detectWine(void)
200200
{
201201
const char * __cdecl wine_get_version(void);
202-
HMODULE hntdll = GetModuleHandleW(L"ntdll.dll");
202+
void* hntdll = ffLibraryGetModule(L"ntdll.dll");
203203
if (!hntdll) return NULL;
204204
FF_LIBRARY_LOAD_SYMBOL_LAZY(hntdll, wine_get_version);
205205
if (!ffwine_get_version) return NULL;

src/common/impl/library.c

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#include "fastfetch.h"
22
#include "common/library.h"
33

4+
#if _WIN32
5+
#include "common/debug.h"
6+
#include "common/windows/nt.h"
7+
#include <errno.h>
8+
#include <ntstatus.h>
9+
#endif
10+
411
#ifndef FF_DISABLE_DLOPEN
512

613
#include <stdarg.h>
@@ -36,7 +43,7 @@ static void* libraryLoad(const char* path, int maxVersion)
3643
if (pathLen == instance.state.platform.exePath.length)
3744
return result;
3845

39-
char absPath[MAX_PATH + 1];
46+
char absPath[MAX_PATH * 2];
4047
strcpy(mempcpy(absPath, instance.state.platform.exePath.chars, pathLen + 1), path);
4148
return dlopen(absPath, FF_DLOPEN_FLAGS);
4249

@@ -92,3 +99,81 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...)
9299
}
93100

94101
#endif
102+
103+
#if _WIN32
104+
105+
void* dlopen(const char* path, FF_MAYBE_UNUSED int mode)
106+
{
107+
wchar_t pathW[MAX_PATH + 1];
108+
ULONG pathWBytes = 0;
109+
110+
NTSTATUS status = RtlUTF8ToUnicodeN(pathW, sizeof(pathW), &pathWBytes, path, (uint32_t)strlen(path) + 1);
111+
if (!NT_SUCCESS(status))
112+
{
113+
FF_DEBUG("RtlUTF8ToUnicodeN failed for path %s with status 0x%08lX: %s", path, status, ffDebugNtStatus(status));
114+
return NULL;
115+
}
116+
117+
PVOID module = NULL;
118+
status = LdrLoadDll(NULL, NULL, &(UNICODE_STRING) {
119+
.Length = (USHORT) pathWBytes - sizeof(wchar_t), // Exclude null terminator
120+
.MaximumLength = (USHORT) pathWBytes,
121+
.Buffer = pathW,
122+
}, &module);
123+
124+
if (!NT_SUCCESS(status))
125+
{
126+
FF_DEBUG("LdrLoadDll failed for path %s with status 0x%08lX: %s", path, status, ffDebugNtStatus(status));
127+
return NULL;
128+
}
129+
130+
return module;
131+
}
132+
133+
int dlclose(void* handle)
134+
{
135+
NTSTATUS status = LdrUnloadDll(handle);
136+
if (!NT_SUCCESS(status))
137+
{
138+
FF_DEBUG("LdrUnloadDll failed for handle %p with status 0x%08lX: %s", handle, status, ffDebugNtStatus(status));
139+
return -1;
140+
}
141+
return 0;
142+
}
143+
144+
void* dlsym(void* handle, const char* symbol)
145+
{
146+
void* address;
147+
USHORT symbolBytes = (USHORT) strlen(symbol) + 1;
148+
NTSTATUS status = LdrGetProcedureAddress(handle, &(ANSI_STRING) {
149+
.Length = symbolBytes - sizeof(char),
150+
.MaximumLength = symbolBytes,
151+
.Buffer = (char*) symbol,
152+
}, 0, &address);
153+
if (!NT_SUCCESS(status))
154+
{
155+
FF_DEBUG("LdrGetProcedureAddress failed for symbol %s with status 0x%08lX: %s", symbol, status, ffDebugNtStatus(status));
156+
return NULL;
157+
}
158+
return address;
159+
}
160+
161+
void* ffLibraryGetModule(const wchar_t* libraryFileName)
162+
{
163+
assert(libraryFileName != NULL && "Use \"ffGetPeb()->ImageBaseAddress\" instead");
164+
165+
void* module = NULL;
166+
USHORT libraryFileNameBytes = (USHORT) (wcslen(libraryFileName) * sizeof(wchar_t)) + sizeof(wchar_t);
167+
NTSTATUS status = LdrGetDllHandle(NULL, NULL, &(UNICODE_STRING) {
168+
.Length = libraryFileNameBytes - sizeof(wchar_t),
169+
.MaximumLength = libraryFileNameBytes,
170+
.Buffer = (wchar_t*) libraryFileName,
171+
}, &module);
172+
if (!NT_SUCCESS(status))
173+
{
174+
FF_DEBUG("LdrGetDllHandle failed for library %ls with status 0x%08lX: %s", libraryFileName, status, ffDebugNtStatus(status));
175+
return NULL;
176+
}
177+
return module;
178+
}
179+
#endif

src/common/library.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
#ifndef FF_DISABLE_DLOPEN
77

88
#if defined(_WIN32)
9-
#include <libloaderapi.h>
109
#define FF_DLOPEN_FLAGS 0
11-
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
12-
FF_C_NODISCARD static inline void* dlsym(void* handle, const char* symbol) { return (void*) GetProcAddress((HMODULE)handle, symbol); }
13-
static inline int dlclose(void* handle) { return !FreeLibrary((HMODULE)handle); }
10+
FF_C_NODISCARD void* dlopen(const char* path, int mode);
11+
FF_C_NODISCARD void* dlsym(void* handle, const char* symbol);
12+
int dlclose(void* handle);
1413
#else
1514
#include <dlfcn.h>
1615
#endif
@@ -30,6 +29,10 @@ static inline void ffLibraryUnload(void** handle)
3029
dlclose(*handle);
3130
}
3231

32+
#if __cplusplus
33+
#define __auto_type auto
34+
#endif
35+
3336
#define FF_LIBRARY_SYMBOL(symbolName) \
3437
__typeof__(&symbolName) ff ## symbolName;
3538

@@ -38,13 +41,8 @@ static inline void ffLibraryUnload(void** handle)
3841
if(libraryObjectName == NULL) \
3942
return returnValue;
4043

41-
#if _WIN32
42-
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
43-
FF_LIBRARY_LOAD(libraryObjectName, "LoadLibraryA(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)
44-
#else
4544
#define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
4645
FF_LIBRARY_LOAD(libraryObjectName, "dlopen(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)
47-
#endif
4846

4947
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
5048
symbolMapping = (__typeof__(&symbolName)) dlsym(library, #symbolName); \
@@ -106,3 +104,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...);
106104
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff ## symbolName, symbolName, returnValue);
107105

108106
#endif
107+
108+
#if _WIN32
109+
void* ffLibraryGetModule(const wchar_t* libraryFileName);
110+
#endif

src/common/windows/nt.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,3 +1249,28 @@ NTSYSAPI NTSTATUS NTAPI NtOpenProcess(
12491249
_In_ PCOBJECT_ATTRIBUTES ObjectAttributes,
12501250
_In_opt_ PCLIENT_ID ClientId
12511251
);
1252+
1253+
NTSYSAPI NTSTATUS NTAPI LdrLoadDll(
1254+
_In_opt_ PCWSTR DllPath,
1255+
_In_opt_ PULONG DllCharacteristics,
1256+
_In_ PCUNICODE_STRING DllName,
1257+
_Out_ PVOID *DllHandle
1258+
);
1259+
1260+
NTSYSAPI NTSTATUS NTAPI LdrUnloadDll(
1261+
_In_ PVOID DllHandle
1262+
);
1263+
1264+
NTSYSAPI NTSTATUS NTAPI LdrGetDllHandle(
1265+
_In_opt_ PCWSTR DllPath,
1266+
_In_opt_ PULONG DllCharacteristics,
1267+
_In_ PCUNICODE_STRING DllName,
1268+
_Out_ PVOID *DllHandle
1269+
);
1270+
1271+
NTSYSAPI NTSTATUS NTAPI LdrGetProcedureAddress(
1272+
_In_ PVOID DllHandle,
1273+
_In_opt_ PCANSI_STRING ProcedureName,
1274+
_In_opt_ ULONG ProcedureNumber,
1275+
_Out_ PVOID *ProcedureAddress
1276+
);

src/detection/brightness/brightness_windows.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ static const char* detectWithWmi(FFlist* result)
6363

6464
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result)
6565
{
66-
HMODULE gdi32 = GetModuleHandleW(L"gdi32.dll");
67-
if (!gdi32) return "GetModuleHandleW(gdi32.dll) failed";
66+
void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
67+
if (!gdi32) return "ffLibraryGetModule(gdi32.dll) failed";
6868
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
6969
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
7070
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)

src/detection/opengl/opengl_windows.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "opengl.h"
22
#include "common/library.h"
33
#include "common/printing.h"
4+
#include "common/windows/nt.h"
45

56
#include <windows.h>
67
#include <GL/gl.h>
@@ -81,7 +82,7 @@ static const char* wglDetectOpenGL(FFOpenGLResult* result)
8182
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglDeleteContext);
8283
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
8384

84-
HINSTANCE hInstance = GetModuleHandleW(NULL);
85+
HINSTANCE hInstance = ffGetPeb()->ImageBaseAddress;
8586

8687
WNDCLASSW wc = {
8788
.lpfnWndProc = DefWindowProcW,

src/detection/tpm/tpm_windows.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "tpm.h"
22
#include "common/library.h"
33

4+
#include <windef.h>
45
#include <tbs.h>
56
#include <winerror.h>
67

0 commit comments

Comments
 (0)