| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | |
| 3 | #include "precomp.h" |
| 4 | |
| 5 | HRESULT RunNetCoreSearch( |
| 6 | __in NETFX_NET_CORE_PLATFORM platform, |
| 7 | __in LPCWSTR wzBaseDirectory, |
| 8 | __in LPCWSTR wzArguments, |
| 9 | __inout LPWSTR* psczLatestVersion |
| 10 | ) |
| 11 | { |
| 12 | HRESULT hr = S_OK; |
| 13 | LPCWSTR wzPlatformName = NULL; |
| 14 | LPWSTR sczExePath = NULL; |
| 15 | LPWSTR sczCommandLine = NULL; |
| 16 | HANDLE hProcess = NULL; |
| 17 | HANDLE hStdOutErr = INVALID_HANDLE_VALUE; |
| 18 | BYTE* rgbOutput = NULL; |
| 19 | DWORD cbOutput = 0; |
| 20 | DWORD cbTotalRead = 0; |
| 21 | DWORD cbRead = 0; |
| 22 | DWORD dwExitCode = 0; |
| 23 | |
| 24 | ReleaseNullStr(*psczLatestVersion); |
| 25 | |
| 26 | switch (platform) |
| 27 | { |
| 28 | case NETFX_NET_CORE_PLATFORM_ARM64: |
| 29 | wzPlatformName = L"arm64"; |
| 30 | break; |
| 31 | case NETFX_NET_CORE_PLATFORM_X64: |
| 32 | wzPlatformName = L"x64"; |
| 33 | break; |
| 34 | case NETFX_NET_CORE_PLATFORM_X86: |
| 35 | wzPlatformName = L"x86"; |
| 36 | break; |
| 37 | default: |
| 38 | BextExitWithRootFailure(hr, E_INVALIDARG, "Unknown platform: %u", platform); |
| 39 | break; |
| 40 | } |
| 41 | |
| 42 | hr = StrAllocFormatted(&sczExePath, L"%ls%ls\\netcoresearch.exe", wzBaseDirectory, wzPlatformName); |
| 43 | BextExitOnFailure(hr, "Failed to build netcoresearch.exe path."); |
| 44 | |
| 45 | hr = StrAllocFormatted(&sczCommandLine, L"\"%ls\" %ls", sczExePath, wzArguments); |
| 46 | BextExitOnFailure(hr, "Failed to build netcoresearch.exe command line."); |
| 47 | |
| 48 | hr = ProcExecute(sczExePath, sczCommandLine, &hProcess, NULL, &hStdOutErr); |
| 49 | if (HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH) == hr) |
| 50 | { |
| 51 | ExitFunction1(hr = S_FALSE); |
| 52 | } |
| 53 | BextExitOnFailure(hr, "Failed to run: %ls", sczCommandLine); |
| 54 | |
| 55 | cbOutput = 64; |
| 56 | |
| 57 | rgbOutput = reinterpret_cast<BYTE*>(MemAlloc(cbOutput, TRUE)); |
| 58 | BextExitOnNull(rgbOutput, hr, E_OUTOFMEMORY, "Failed to alloc output string."); |
| 59 | |
| 60 | while (::ReadFile(hStdOutErr, rgbOutput + cbTotalRead, cbOutput - cbTotalRead, &cbRead, NULL)) |
| 61 | { |
| 62 | cbTotalRead += cbRead; |
| 63 | |
| 64 | if (cbTotalRead == cbOutput) |
| 65 | { |
| 66 | cbOutput *= 2; |
| 67 | |
| 68 | LPVOID pvNew = MemReAlloc(rgbOutput, cbOutput, TRUE); |
| 69 | BextExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to realloc output string."); |
| 70 | |
| 71 | rgbOutput = reinterpret_cast<BYTE*>(pvNew); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | if (ERROR_BROKEN_PIPE != ::GetLastError()) |
| 76 | { |
| 77 | BextExitWithLastError(hr, "Failed to read netcoresearch.exe output."); |
| 78 | } |
| 79 | |
| 80 | hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode); |
| 81 | BextExitOnFailure(hr, "Failed to wait for netcoresearch.exe to exit."); |
| 82 | |
| 83 | if (0 != dwExitCode) |
| 84 | { |
| 85 | BextExitWithRootFailure(hr, E_UNEXPECTED, "netcoresearch.exe failed with exit code: 0x%x\r\nOutput:\r\n%hs", dwExitCode, rgbOutput); |
| 86 | } |
| 87 | |
| 88 | if (*rgbOutput) |
| 89 | { |
| 90 | hr = StrAllocStringAnsi(psczLatestVersion, reinterpret_cast<LPSTR>(rgbOutput), 0, CP_UTF8); |
| 91 | BextExitOnFailure(hr, "Failed to widen output string: %hs", rgbOutput); |
| 92 | } |
| 93 | |
| 94 | LExit: |
| 95 | ReleaseFileHandle(hStdOutErr); |
| 96 | ReleaseHandle(hProcess); |
| 97 | ReleaseMem(rgbOutput); |
| 98 | ReleaseStr(sczCommandLine); |
| 99 | ReleaseStr(sczExePath); |
| 100 | |
| 101 | return hr; |
| 102 | } |