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..86c9913f 100644 --- a/build.bat +++ b/build.bat @@ -8,7 +8,8 @@ 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 RUNTIME_LIBS=gdi32.lib shlwapi.lib user32.lib xinput.lib winmm.lib +set CLI_TOOLS=DependencyCheck +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\" @@ -117,16 +118,30 @@ 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 + 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 @@ -141,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 -------------------------------------------------------------------------------------------------------- @@ -149,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