aspnetcore/src/AspNetCoreModuleV2/CommonLib/GlobalVersionUtility.cpp

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;
}