@@ -197,7 +197,7 @@ HostFxrResolver::TryGetHostFxrPath(
197
197
size_t size = MAX_PATH * 2 ;
198
198
hostfxrPath.resize (size);
199
199
200
- get_hostfxr_parameters params;
200
+ get_hostfxr_parameters params{} ;
201
201
params.size = sizeof (get_hostfxr_parameters);
202
202
params.assembly_path = applicationPath.c_str ();
203
203
params.dotnet_root = dotnetRoot.c_str ();
@@ -393,7 +393,7 @@ HostFxrResolver::GetAbsolutePathToDotnetFromHostfxr(const fs::path& hostfxrPath)
393
393
// Tries to call where.exe to find the location of dotnet.exe.
394
394
// Will check that the bitness of dotnet matches the current
395
395
// 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.
397
397
//
398
398
std::optional<fs::path>
399
399
HostFxrResolver::InvokeWhereToFindDotnet ()
@@ -416,7 +416,6 @@ HostFxrResolver::InvokeWhereToFindDotnet()
416
416
STRU struDotnetSubstring;
417
417
STRU struDotnetLocationsString;
418
418
DWORD dwNumBytesRead = 0 ;
419
- DWORD dwBinaryType = 0 ;
420
419
INT index = 0 ;
421
420
INT prevIndex = 0 ;
422
421
std::optional<fs::path> result;
@@ -521,14 +520,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
521
520
522
521
LOG_INFOF (L" Processing entry '%ls'" , struDotnetSubstring.QueryStr ());
523
522
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 ()))
532
524
{
533
525
// The bitness of dotnet matched with the current worker process bitness.
534
526
return std::make_optional (struDotnetSubstring.QueryStr ());
@@ -539,6 +531,62 @@ HostFxrResolver::InvokeWhereToFindDotnet()
539
531
return result;
540
532
}
541
533
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
+
542
590
std::optional<fs::path>
543
591
HostFxrResolver::GetAbsolutePathToDotnetFromProgramFiles ()
544
592
{
0 commit comments