diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
index 9b12cd0132b4..8fb960261590 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
@@ -197,7 +197,7 @@ HostFxrResolver::TryGetHostFxrPath(
size_t size = MAX_PATH * 2;
hostfxrPath.resize(size);
- get_hostfxr_parameters params;
+ get_hostfxr_parameters params{};
params.size = sizeof(get_hostfxr_parameters);
params.assembly_path = applicationPath.c_str();
params.dotnet_root = dotnetRoot.c_str();
@@ -393,7 +393,7 @@ HostFxrResolver::GetAbsolutePathToDotnetFromHostfxr(const fs::path& hostfxrPath)
// Tries to call where.exe to find the location of dotnet.exe.
// Will check that the bitness of dotnet matches the current
// worker process bitness.
-// Returns true if a valid dotnet was found, else false.R
+// Returns true if a valid dotnet was found, else false.
//
std::optional<fs::path>
HostFxrResolver::InvokeWhereToFindDotnet()
@@ -415,8 +415,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
DWORD dwExitCode;
STRU struDotnetSubstring;
STRU struDotnetLocationsString;
- DWORD dwNumBytesRead;
- DWORD dwBinaryType;
+ DWORD dwNumBytesRead = 0;
INT index = 0;
INT prevIndex = 0;
std::optional<fs::path> result;
@@ -521,14 +520,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr());
- if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType)))
- {
- continue;
- }
-
- LOG_INFOF(L"Binary type %d", dwBinaryType);
-
- if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
+ if (fIsCurrentProcess64Bit == IsX64(struDotnetSubstring.QueryStr()))
{
// The bitness of dotnet matched with the current worker process bitness.
return std::make_optional(struDotnetSubstring.QueryStr());
@@ -539,6 +531,62 @@ HostFxrResolver::InvokeWhereToFindDotnet()
return result;
}
+BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
+{
+ // Errors while reading from the file shouldn't throw unless
+ // file.exception(bits) is set
+ std::ifstream file(dotnetPath, std::ios::binary);
+ if (!file.is_open())
+ {
+ LOG_TRACEF(L"Failed to open file %ls", dotnetPath);
+ return false;
+ }
+
+ // Read the DOS header
+ IMAGE_DOS_HEADER dosHeader{};
+ file.read(reinterpret_cast<char*>(&dosHeader), sizeof(dosHeader));
+ if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) // 'MZ'
+ {
+ LOG_TRACEF(L"%ls is not a valid executable file (missing MZ header).", dotnetPath);
+ return false;
+ }
+
+ // Seek to the PE header
+ file.seekg(dosHeader.e_lfanew, std::ios::beg);
+
+ // Read the PE header
+ DWORD peSignature{};
+ file.read(reinterpret_cast<char*>(&peSignature), sizeof(peSignature));
+ if (peSignature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
+ {
+ LOG_TRACEF(L"%ls is not a valid PE file (missing PE header).", dotnetPath);
+ return false;
+ }
+
+ // Read the file header
+ IMAGE_FILE_HEADER fileHeader{};
+ file.read(reinterpret_cast<char*>(&fileHeader), sizeof(fileHeader));
+
+ // Read the optional header magic field
+ WORD magic{};
+ file.read(reinterpret_cast<char*>(&magic), sizeof(magic));
+
+ // Determine the architecture based on the magic value
+ if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ LOG_INFOF(L"%ls is 32-bit", dotnetPath);
+ return false;
+ }
+ else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ LOG_INFOF(L"%ls is 64-bit", dotnetPath);
+ return true;
+ }
+
+ LOG_INFOF(L"%ls is unknown architecture %i", dotnetPath, fileHeader.Machine);
+ return false;
+}
+
std::optional<fs::path>
HostFxrResolver::GetAbsolutePathToDotnetFromProgramFiles()
{
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
index 519f6df52c97..08ec650aec54 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
@@ -74,6 +74,8 @@ class HostFxrResolver
const std::filesystem::path & requestedPath
);
+ static BOOL IsX64(const WCHAR* dotnetPath);
+
struct LocalFreeDeleter
{
void operator ()(_In_ LPWSTR* ptr) const
diff --git a/src/Servers/IIS/build/Build.Lib.Settings b/src/Servers/IIS/build/Build.Lib.Settings
index 0dcba8c2011a..9327eb363771 100644
--- a/src/Servers/IIS/build/Build.Lib.Settings
+++ b/src/Servers/IIS/build/Build.Lib.Settings
@@ -9,7 +9,7 @@
<ItemDefinitionGroup>
<ClCompile>
- <SDLCheck>false</SDLCheck>
+ <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>