134 lines
4.1 KiB
C++
134 lines
4.1 KiB
C++
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
#include <Windows.h>
|
|
#include <filesystem>
|
|
|
|
#include "GlobalVersionUtility.h"
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
// throws runtime error if no request handler versions are installed.
|
|
// Throw invalid_argument if any argument is null
|
|
std::wstring
|
|
GlobalVersionUtility::GetGlobalRequestHandlerPath(PCWSTR pwzAspNetCoreFolderPath, PCWSTR pwzHandlerVersion, PCWSTR pwzHandlerName)
|
|
{
|
|
if (pwzAspNetCoreFolderPath == NULL)
|
|
{
|
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
|
}
|
|
|
|
if (pwzHandlerVersion == NULL)
|
|
{
|
|
throw new std::invalid_argument("pwzHandlerVersion is NULL");
|
|
}
|
|
|
|
if (pwzHandlerName == NULL)
|
|
{
|
|
throw new std::invalid_argument("pwzHandlerName is NULL");
|
|
}
|
|
|
|
std::wstring folderVersion(pwzHandlerVersion);
|
|
fs::path aspNetCoreFolderPath(pwzAspNetCoreFolderPath);
|
|
|
|
if (folderVersion.empty())
|
|
{
|
|
folderVersion = FindHighestGlobalVersion(pwzAspNetCoreFolderPath);
|
|
}
|
|
|
|
aspNetCoreFolderPath = aspNetCoreFolderPath
|
|
.append(folderVersion)
|
|
.append(pwzHandlerName);
|
|
return aspNetCoreFolderPath;
|
|
}
|
|
|
|
// Throw filesystem_error if directory_iterator can't iterate over the directory
|
|
// Throw invalid_argument if any argument is null
|
|
std::vector<fx_ver_t>
|
|
GlobalVersionUtility::GetRequestHandlerVersions(PCWSTR pwzAspNetCoreFolderPath)
|
|
{
|
|
if (pwzAspNetCoreFolderPath == NULL)
|
|
{
|
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
|
}
|
|
|
|
std::vector<fx_ver_t> versionsInDirectory;
|
|
for (auto& p : fs::directory_iterator(pwzAspNetCoreFolderPath))
|
|
{
|
|
if (!fs::is_directory(p))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
fx_ver_t requested_ver(-1, -1, -1);
|
|
if (fx_ver_t::parse(p.path().filename(), &requested_ver, false))
|
|
{
|
|
versionsInDirectory.push_back(requested_ver);
|
|
}
|
|
}
|
|
return versionsInDirectory;
|
|
}
|
|
|
|
// throws runtime error if no request handler versions are installed.
|
|
// Throw invalid_argument if any argument is null
|
|
std::wstring
|
|
GlobalVersionUtility::FindHighestGlobalVersion(PCWSTR pwzAspNetCoreFolderPath)
|
|
{
|
|
if (pwzAspNetCoreFolderPath == NULL)
|
|
{
|
|
throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL");
|
|
}
|
|
|
|
std::vector<fx_ver_t> versionsInDirectory = GetRequestHandlerVersions(pwzAspNetCoreFolderPath);
|
|
if (versionsInDirectory.empty())
|
|
{
|
|
throw new std::runtime_error("Cannot find request handler next to aspnetcorev2.dll. Verify a version of the request handler is installed in a version folder.");
|
|
}
|
|
std::sort(versionsInDirectory.begin(), versionsInDirectory.end());
|
|
|
|
return versionsInDirectory.back().as_str();
|
|
}
|
|
|
|
// Throws std::out_of_range if there is an index out of range
|
|
// Throw invalid_argument if any argument is null
|
|
std::wstring
|
|
GlobalVersionUtility::RemoveFileNameFromFolderPath(std::wstring fileName)
|
|
{
|
|
fs::path path(fileName);
|
|
return path.parent_path();
|
|
}
|
|
|
|
std::wstring
|
|
GlobalVersionUtility::GetModuleName(HMODULE hModuleName)
|
|
{
|
|
DWORD dwSize = MAX_PATH;
|
|
BOOL fDone = FALSE;
|
|
|
|
// Instead of creating a temporary buffer, use the std::wstring directly as the receive buffer.
|
|
std::wstring retVal;
|
|
retVal.resize(dwSize);
|
|
|
|
while (!fDone)
|
|
{
|
|
DWORD dwReturnedSize = GetModuleFileNameW(hModuleName, &retVal[0], dwSize);
|
|
if (dwReturnedSize == 0)
|
|
{
|
|
throw new std::runtime_error("GetModuleFileNameW returned 0.");
|
|
}
|
|
else if ((dwReturnedSize == dwSize) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
|
{
|
|
dwSize *= 2;
|
|
retVal.resize(dwSize); // smaller buffer. increase the buffer and retry
|
|
}
|
|
else
|
|
{
|
|
// GetModuleFilename will not account for the null terminator
|
|
// std::wstring auto appends one, so we don't need to subtract 1 when resizing.
|
|
retVal.resize(dwReturnedSize);
|
|
fDone = TRUE;
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|