@@ -197,7 +197,7 @@ HostFxrResolver::TryGetHostFxrPath(
197197 size_t size = MAX_PATH * 2 ;
198198 hostfxrPath.resize (size);
199199
200- get_hostfxr_parameters params;
200+ get_hostfxr_parameters params{} ;
201201 params.size = sizeof (get_hostfxr_parameters);
202202 params.assembly_path = applicationPath.c_str ();
203203 params.dotnet_root = dotnetRoot.c_str ();
@@ -393,7 +393,7 @@ HostFxrResolver::GetAbsolutePathToDotnetFromHostfxr(const fs::path& hostfxrPath)
393393// Tries to call where.exe to find the location of dotnet.exe.
394394// Will check that the bitness of dotnet matches the current
395395// worker process bitness.
396- // Returns true if a valid dotnet was found, else false.R
396+ // Returns true if a valid dotnet was found, else false.
397397//
398398std::optional<fs::path>
399399HostFxrResolver::InvokeWhereToFindDotnet ()
@@ -415,8 +415,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
415415 DWORD dwExitCode;
416416 STRU struDotnetSubstring;
417417 STRU struDotnetLocationsString;
418- DWORD dwNumBytesRead;
419- DWORD dwBinaryType;
418+ DWORD dwNumBytesRead = 0 ;
420419 INT index = 0 ;
421420 INT prevIndex = 0 ;
422421 std::optional<fs::path> result;
@@ -521,14 +520,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
521520
522521 LOG_INFOF (L" Processing entry '%ls'" , struDotnetSubstring.QueryStr ());
523522
524- if (LOG_LAST_ERROR_IF (!GetBinaryTypeW (struDotnetSubstring.QueryStr (), &dwBinaryType)))
525- {
526- continue ;
527- }
528-
529- LOG_INFOF (L" Binary type %d" , dwBinaryType);
530-
531- if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
523+ if (fIsCurrentProcess64Bit == IsX64 (struDotnetSubstring.QueryStr ()))
532524 {
533525 // The bitness of dotnet matched with the current worker process bitness.
534526 return std::make_optional (struDotnetSubstring.QueryStr ());
@@ -539,6 +531,62 @@ HostFxrResolver::InvokeWhereToFindDotnet()
539531 return result;
540532}
541533
534+ BOOL HostFxrResolver::IsX64 (const WCHAR* dotnetPath)
535+ {
536+ // Errors while reading from the file shouldn't throw unless
537+ // file.exception(bits) is set
538+ std::ifstream file (dotnetPath, std::ios::binary);
539+ if (!file.is_open ())
540+ {
541+ LOG_TRACEF (L" Failed to open file %ls" , dotnetPath);
542+ return false ;
543+ }
544+
545+ // Read the DOS header
546+ IMAGE_DOS_HEADER dosHeader{};
547+ file.read (reinterpret_cast <char *>(&dosHeader), sizeof (dosHeader));
548+ if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) // 'MZ'
549+ {
550+ LOG_TRACEF (L" %ls is not a valid executable file (missing MZ header)." , dotnetPath);
551+ return false ;
552+ }
553+
554+ // Seek to the PE header
555+ file.seekg (dosHeader.e_lfanew , std::ios::beg);
556+
557+ // Read the PE header
558+ DWORD peSignature{};
559+ file.read (reinterpret_cast <char *>(&peSignature), sizeof (peSignature));
560+ if (peSignature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
561+ {
562+ LOG_TRACEF (L" %ls is not a valid PE file (missing PE header)." , dotnetPath);
563+ return false ;
564+ }
565+
566+ // Read the file header
567+ IMAGE_FILE_HEADER fileHeader{};
568+ file.read (reinterpret_cast <char *>(&fileHeader), sizeof (fileHeader));
569+
570+ // Read the optional header magic field
571+ WORD magic{};
572+ file.read (reinterpret_cast <char *>(&magic), sizeof (magic));
573+
574+ // Determine the architecture based on the magic value
575+ if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
576+ {
577+ LOG_INFOF (L" %ls is 32-bit" , dotnetPath);
578+ return false ;
579+ }
580+ else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
581+ {
582+ LOG_INFOF (L" %ls is 64-bit" , dotnetPath);
583+ return true ;
584+ }
585+
586+ LOG_INFOF (L" %ls is unknown architecture %i" , dotnetPath, fileHeader.Machine );
587+ return false ;
588+ }
589+
542590std::optional<fs::path>
543591HostFxrResolver::GetAbsolutePathToDotnetFromProgramFiles ()
544592{
0 commit comments