From 9162ab343658c3487c0d032c078cf4dd153e40a4 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Tue, 6 Feb 2018 12:12:23 -0800 Subject: [PATCH] Default to using program files if where.exe doesn't find dotnet.exe (#578) --- src/CommonLib/hostfxr_utility.cpp | 181 +++++++++++++++++------------- 1 file changed, 104 insertions(+), 77 deletions(-) diff --git a/src/CommonLib/hostfxr_utility.cpp b/src/CommonLib/hostfxr_utility.cpp index 15ec45d649..d346f7044c 100644 --- a/src/CommonLib/hostfxr_utility.cpp +++ b/src/CommonLib/hostfxr_utility.cpp @@ -145,10 +145,6 @@ HOSTFXR_UTILITY::GetStandaloneHostfxrParameters( { goto Finished; } - if (FAILED(hr = struHostFxrDllLocation->Copy(struDllPath))) - { - goto Finished; - } Finished: @@ -479,6 +475,7 @@ HOSTFXR_UTILITY::FindDotnetExePath( DWORD dwNumBytesRead; DWORD dwFilePointer; DWORD dwBinaryType; + DWORD dwPathSize = MAX_PATH; INT index = 0; INT prevIndex = 0; BOOL fResult = FALSE; @@ -545,105 +542,135 @@ HOSTFXR_UTILITY::FindDotnetExePath( } // - // where.exe will return 1 if the file is not found + // where.exe will return 0 on success, 1 if the file is not found // and 2 if there was an error. Check if the exit code is 1 and set // a new hr result saying it couldn't find dotnet.exe // - if (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode) || - dwExitCode != 0) + if (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode)) { - if (dwExitCode == 1) + goto Fallback; + } + + // + // In this block, if anything fails, we will goto our fallback of + // looking in C:/Program Files/ + // + if (dwExitCode == 0) + { + // Where succeeded. + // Reset file pointer to the beginning of the file. + dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN); + if (dwFilePointer == INVALID_SET_FILE_POINTER) { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + goto Fallback; + } + + // + // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang. + // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block. + // + if (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL)) + { + goto Fallback; + } + if (dwNumBytesRead >= READ_BUFFER_SIZE) + { + // This shouldn't ever be this large. We could continue to call ReadFile in a loop, + // however I'd rather error out here and report an issue. + goto Fallback; + } + + if (FAILED(hr = struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead))) + { + goto Finished; + } + + // Check the bitness of the currently running process + // matches the dotnet.exe found. + if (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process)) + { + // Calling IsWow64Process failed + hr = HRESULT_FROM_WIN32(GetLastError()); + goto Finished; + } + if (fIsWow64Process) + { + // 32 bit mode + fIsCurrentProcess64Bit = FALSE; } else { - hr = HRESULT_FROM_WIN32(GetLastError()); + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&systemInfo); + fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + } + + while (!fFound) + { + index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex); + if (index == -1) + { + break; + } + if (FAILED(hr = struDotnetSubstring.Copy(struDotnetLocationsString.QueryStr(), index - prevIndex))) + { + goto Finished; + } + prevIndex = index; + + if (GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType) && + fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY)) { + // Found a valid dotnet. + if (FAILED(hr = struDotnetPath->Copy(struDotnetSubstring))) + { + goto Finished; + } + fFound = TRUE; + } } - goto Finished; } - // Reset file pointer to the beginning of the file. - dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN); - if (dwFilePointer == INVALID_SET_FILE_POINTER) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID); - goto Finished; - } - - // - // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang. - // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block. - // - if (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL)) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID); - goto Finished; - } - if (dwNumBytesRead >= READ_BUFFER_SIZE) - { - // This shouldn't ever be this large. We could continue to call ReadFile in a loop, - // however I'd rather error out here and report an issue. - hr = HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); - goto Finished; - } - - if (FAILED(hr = struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead))) - { - goto Finished; - } - - // Check the bitness of the currently running process - // matches the dotnet.exe found. - if (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process)) - { - // Calling IsWow64Process failed - hr = HRESULT_FROM_WIN32(GetLastError()); - goto Finished; - } - if (fIsWow64Process) - { - // 32 bit mode - fIsCurrentProcess64Bit = FALSE; - } - else - { - SYSTEM_INFO systemInfo; - GetNativeSystemInfo(&systemInfo); - fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; - } +Fallback: + // Look in ProgramFiles while (!fFound) { - index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex); - if (index == -1) - { - break; - } - if (FAILED(hr = struDotnetSubstring.Copy(struDotnetLocationsString.QueryStr(), index - prevIndex))) + if (FAILED(hr = struDotnetSubstring.Resize(dwPathSize))) { goto Finished; } - prevIndex = index; - if (!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType)) + // Program files will changes based on the + dwNumBytesRead = GetEnvironmentVariable(L"ProgramFiles", struDotnetSubstring.QueryStr(), dwPathSize); + if (dwNumBytesRead == 0) { - // TODO should we ignore this failure and continue to trying the next dotnet.exe? hr = HRESULT_FROM_WIN32(GetLastError()); goto Finished; } - if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY)) { - // Found a valid dotnet. - struDotnetPath->Copy(struDotnetSubstring); + else if (dwNumBytesRead == dwPathSize) + { + dwPathSize *= 2 + 30; // for dotnet substring + } + else + { + if (FAILED(hr = struDotnetSubstring.SyncWithBuffer()) || + FAILED(hr = struDotnetSubstring.Append(L"\\dotnet\\dotnet.exe"))) + { + goto Finished; + } + if (!UTILITY::CheckIfFileExists(struDotnetSubstring.QueryStr())) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + goto Finished; + } + if (FAILED(hr = struDotnetPath->Copy(struDotnetSubstring))) + { + goto Finished; + } fFound = TRUE; } } - if (!fFound) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - goto Finished; - } Finished: