From b4312bfe2f8cb357a2c18f00345dc9e6e2371afb Mon Sep 17 00:00:00 2001 From: RDW Date: Sat, 18 Oct 2025 22:32:03 +0200 Subject: [PATCH 1/3] Tools: Create a CLI utility to scan PE DLL imports Could instead do it with Unix tools, but this way works OOB on Win32. Should also be easier to customize this later to perform other checks. --- Tools/DependencyCheck.cpp | 74 +++++++++++++++++++++++++++++++++++++++ build.bat | 10 ++++++ 2 files changed, 84 insertions(+) create mode 100644 Tools/DependencyCheck.cpp diff --git a/Tools/DependencyCheck.cpp b/Tools/DependencyCheck.cpp new file mode 100644 index 00000000..289b3fbb --- /dev/null +++ b/Tools/DependencyCheck.cpp @@ -0,0 +1,74 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +static const char* expectedDependencies[] = { + "KERNEL32.DLL", + "USER32.DLL", + "GDI32.DLL", + "SHLWAPI.DLL", + "XINPUT1_4.DLL", + "WINMM.DLL", + "IMAGEHLP.DLL", + NULL +}; + +inline bool StringEqualsCaseInsensitive(const char* first, const char* second) { + return _stricmp(first, second) == 0; +} + +static bool IsExpectedDependency(const char* dllName) { + for(int i = 0; expectedDependencies[i]; ++i) { + if(StringEqualsCaseInsensitive(expectedDependencies[i], dllName)) return true; + } + return false; +} + +int main(int argc, char** argv) { + if(argc != 2) { + fprintf(stderr, "No input path provided (missing CLI arguments)\n"); + return 2; + } + + const char* inputFilePath = argv[1]; + LOADED_IMAGE image; + + if(!MapAndLoad(inputFilePath, NULL, &image, TRUE, TRUE)) { + fprintf(stderr, "Failed to load PE image: %s\n", inputFilePath); + return 2; + } + + IMAGE_IMPORT_DESCRIPTOR* descriptor = (IMAGE_IMPORT_DESCRIPTOR*) + ImageRvaToVa(image.FileHeader, image.MappedAddress, + image.FileHeader->OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress, + NULL); + + if(!descriptor) { + printf("No imports found in PE image: %s\n", inputFilePath); + UnMapAndLoad(&image); + return 0; + } + + int numUnexpectedImports = 0; + printf("Scanning PE image for runtime dependencies: %s\n", inputFilePath); + for(; descriptor->Name; descriptor++) { + const char* dllName = (const char*)ImageRvaToVa(image.FileHeader, + image.MappedAddress, + descriptor->Name, NULL); + if(!dllName) continue; + + printf(" ✓ %s\n", dllName); + if(!IsExpectedDependency(dllName)) { + fprintf(stderr, " ⚠ Unexpected runtime dependency: %s\n", dllName); + numUnexpectedImports++; + } + } + if(numUnexpectedImports == 0) printf("SUCCESS: No unexpected runtime dependencies found in %s\n", inputFilePath); + else fprintf(stderr, "FAILED: %d unexpected runtime dependencies found in %s\n", numUnexpectedImports, inputFilePath); + + UnMapAndLoad(&image); + return numUnexpectedImports; +} diff --git a/build.bat b/build.bat index 96fb4c05..774b9c22 100644 --- a/build.bat +++ b/build.bat @@ -8,6 +8,7 @@ set CPP_MAIN=Core\RagLite2.cpp set DEBUG_EXE=%DEFAULT_BUILD_DIR%/RagLiteWin32Dbg.exe set RELEASE_EXE=%DEFAULT_BUILD_DIR%/RagLiteWin32.exe set PROGRAM_DLLS=PatternTest DummyTest +set CLI_TOOLS=DependencyCheck set RUNTIME_LIBS=gdi32.lib shlwapi.lib user32.lib xinput.lib winmm.lib for /f "delims=" %%i in ('call git describe --always --dirty') do set GIT_COMMIT_HASH=\"%%i\" @@ -117,6 +118,15 @@ set RELEASE_LINK_FLAGS=%RELEASE_LINK_FLAGS% /OPT:ICF set RELEASE_COMPILE_FLAGS=%RELEASE_COMPILE_FLAGS% %SHARED_COMPILE_FLAGS% set RELEASE_LINK_FLAGS=%RELEASE_LINK_FLAGS% %SHARED_LINK_FLAGS% +for %%T in (%CLI_TOOLS%) do ( + set CLI_MAIN=Tools/%%T.cpp + set DEBUG_CLI=%DEFAULT_BUILD_DIR%/%%TDbg.exe + set RELEASE_CLI=%DEFAULT_BUILD_DIR%/%%T.exe + set NO_LIBS="" + call :msvcbuild !RELEASE_CLI! !CLI_MAIN! "%NO_LIBS%" "%RELEASE_COMPILE_FLAGS%" "%RELEASE_LINK_FLAGS%" || exit /b + call :msvcbuild !DEBUG_CLI! !CLI_MAIN! "%NO_LIBS%" "%DEBUG_COMPILE_FLAGS%" "%DEBUG_LINK_FLAGS%" || exit /b +) + call :msvcbuild !DEBUG_EXE! "%CPP_MAIN%" "%RUNTIME_LIBS%" "%DEBUG_COMPILE_FLAGS%" "%ICON_RES% %DEBUG_LINK_FLAGS%" || exit /b call :msvcbuild !RELEASE_EXE! "%CPP_MAIN%" "%RUNTIME_LIBS%" "%RELEASE_COMPILE_FLAGS%" "%ICON_RES% %RELEASE_LINK_FLAGS%" || exit /b From 12061282c8e2ef1390f5fc258c0a9e8471f82c87 Mon Sep 17 00:00:00 2001 From: RDW Date: Sat, 18 Oct 2025 22:49:38 +0200 Subject: [PATCH 2/3] Build: Enable DLL dependency checks for Win32 build artifacts --- build.bat | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/build.bat b/build.bat index 774b9c22..50359924 100644 --- a/build.bat +++ b/build.bat @@ -9,7 +9,7 @@ set DEBUG_EXE=%DEFAULT_BUILD_DIR%/RagLiteWin32Dbg.exe set RELEASE_EXE=%DEFAULT_BUILD_DIR%/RagLiteWin32.exe set PROGRAM_DLLS=PatternTest DummyTest set CLI_TOOLS=DependencyCheck -set RUNTIME_LIBS=gdi32.lib shlwapi.lib user32.lib xinput.lib winmm.lib +set RUNTIME_LIBS=gdi32.lib shlwapi.lib user32.lib xinput.lib winmm.lib imagehlp.lib for /f "delims=" %%i in ('call git describe --always --dirty') do set GIT_COMMIT_HASH=\"%%i\" @@ -122,21 +122,26 @@ for %%T in (%CLI_TOOLS%) do ( set CLI_MAIN=Tools/%%T.cpp set DEBUG_CLI=%DEFAULT_BUILD_DIR%/%%TDbg.exe set RELEASE_CLI=%DEFAULT_BUILD_DIR%/%%T.exe - set NO_LIBS="" - call :msvcbuild !RELEASE_CLI! !CLI_MAIN! "%NO_LIBS%" "%RELEASE_COMPILE_FLAGS%" "%RELEASE_LINK_FLAGS%" || exit /b - call :msvcbuild !DEBUG_CLI! !CLI_MAIN! "%NO_LIBS%" "%DEBUG_COMPILE_FLAGS%" "%DEBUG_LINK_FLAGS%" || exit /b + call :msvcbuild !RELEASE_CLI! !CLI_MAIN! "%RUNTIME_LIBS%" "%RELEASE_COMPILE_FLAGS%" "%RELEASE_LINK_FLAGS%" || exit /b + call :msvcbuild !DEBUG_CLI! !CLI_MAIN! "%RUNTIME_LIBS%" "%DEBUG_COMPILE_FLAGS%" "%DEBUG_LINK_FLAGS%" || exit /b + call :checkdeps !RELEASE_CLI! %DEFAULT_BUILD_DIR% || exit /b + call :checkdeps !DEBUG_CLI! %DEFAULT_BUILD_DIR% || exit /b ) call :msvcbuild !DEBUG_EXE! "%CPP_MAIN%" "%RUNTIME_LIBS%" "%DEBUG_COMPILE_FLAGS%" "%ICON_RES% %DEBUG_LINK_FLAGS%" || exit /b call :msvcbuild !RELEASE_EXE! "%CPP_MAIN%" "%RUNTIME_LIBS%" "%RELEASE_COMPILE_FLAGS%" "%ICON_RES% %RELEASE_LINK_FLAGS%" || exit /b +call :checkdeps !DEBUG_EXE! %DEFAULT_BUILD_DIR% || exit /b +call :checkdeps !RELEASE_EXE! %DEFAULT_BUILD_DIR% || exit /b for %%D in (%PROGRAM_DLLS%) do ( set DLL_MAIN=Core/%%D.cpp set DEBUG_DLL=%DEFAULT_BUILD_DIR%/RagLite%%DDbg.dll set RELEASE_DLL=%DEFAULT_BUILD_DIR%/RagLite%%D.dll - set NO_LIBS="" + set NO_LIBS= call :msvcbuild !DEBUG_DLL! !DLL_MAIN! "%NO_LIBS%" "%DEBUG_COMPILE_FLAGS%" "/DLL %DEBUG_LINK_FLAGS%" || exit /b call :msvcbuild !RELEASE_DLL! !DLL_MAIN! "%NO_LIBS%" "%RELEASE_COMPILE_FLAGS%" "/DLL %RELEASE_LINK_FLAGS%" || exit /b + call :checkdeps !DEBUG_DLL! %DEFAULT_BUILD_DIR% || exit /b + call :checkdeps !RELEASE_DLL! %DEFAULT_BUILD_DIR% || exit /b ) endlocal @@ -159,3 +164,18 @@ echo --------------------------------------------------------------------------- echo -------------------------------------------------------------------------------------------------------- exit /b + +:checkdeps + +set INPUT_FILE=%1 +set ROOT_DIR=%2 +set CHECK_COMMAND=%ROOT_DIR%\DependencyCheck.exe %INPUT_FILE% || exit /b +echo The Ancient One speaketh: +echo Let us ensure no evil hides in %INPUT_FILE% +echo Behold, mortal, as I expose what treachery it may obscure... +echo %CHECK_COMMAND% +echo -------------------------------------------------------------------------------------------------------- +%CHECK_COMMAND% +echo -------------------------------------------------------------------------------------------------------- + +exit /b \ No newline at end of file From 01fca9e83de3824811193b95ae09765ff3274855 Mon Sep 17 00:00:00 2001 From: RDW Date: Sat, 25 Oct 2025 12:12:45 +0200 Subject: [PATCH 3/3] Cleanup: Remove an unescaped ! symbol Just cmd.exe things (it's cosmetic, but wasn't printed, anyway). --- build.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.bat b/build.bat index 50359924..86c9913f 100644 --- a/build.bat +++ b/build.bat @@ -156,7 +156,7 @@ set COMPILE_FLAGS=%~4 set LINKAGE_FLAGS=%~5 set BUILD_COMMAND=cl %COMPILE_FLAGS% %SOURCE_FILES% %STATIC_LIBS% /link %LINKAGE_FLAGS% /out:%BUILD_TARGET% || exit /b echo The Ancient One speaketh: -echo Let us now turn %SOURCE_FILES% into %BUILD_TARGET%! +echo Let us now turn %SOURCE_FILES% into %BUILD_TARGET% echo Harken, mortal, as I prepare thy unholy incantation... echo %BUILD_COMMAND% echo --------------------------------------------------------------------------------------------------------