Merge branch 'merge/release/2.2-to-master'
This commit is contained in:
commit
f4f6e50b22
|
|
@ -1,5 +1,11 @@
|
|||
init:
|
||||
- git config --global core.autocrlf true
|
||||
# Reset dynamic port range from AppVeyor setting (1025-65535) to Windows default (49152-65535),
|
||||
# to prevent conflicts with ANCM random ports (1025-48000).
|
||||
- netsh int ipv4 show dynamicport tcp
|
||||
- netsh int ipv4 set dynamic tcp start=49152 num=16384
|
||||
- netsh int ipv4 show dynamicport tcp
|
||||
|
||||
- git config --global core.autocrlf true
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04B1EDB6-E96
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EF45656-B25D-40D8-959C-726EAF185E60}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.appveyor.yml = .appveyor.yml
|
||||
.editorconfig = .editorconfig
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CodeAnalysisRuleSet>..\DefaultRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<!-- Do not enable code analysis on old compiler versions -->
|
||||
<RunCodeAnalysis Condition="'$(VCToolsRedistVersion)' != '' AND '$(VCToolsRedistVersion)' >= 14.15.26706">true</RunCodeAnalysis>
|
||||
<EnablePREfast>$(RunCodeAnalysis)</EnablePREfast>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<MicrosoftAspNetCoreAllPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreAllPackageVersion>
|
||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreHostingPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreHostingPackageVersion>
|
||||
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>3.0.0-alpha1-10400</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <windows.h>
|
||||
#include "version.h"
|
||||
#include "resource.h"
|
||||
#include "Aspnetcore_msg.rc"
|
||||
#include "aspnetcore_msg.rc"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ HRESULT AppOfflineApplication::CreateHandler(IHttpContext* pHttpContext, IREQUES
|
|||
{
|
||||
try
|
||||
{
|
||||
*pRequestHandler = new AppOfflineHandler(pHttpContext, m_strAppOfflineContent);
|
||||
auto handler = std::make_unique<AppOfflineHandler>(*pHttpContext, m_strAppOfflineContent);
|
||||
*pRequestHandler = handler.release();
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
|
|
@ -44,9 +45,9 @@ HRESULT AppOfflineApplication::OnAppOfflineFound()
|
|||
if (li.LowPart > 0)
|
||||
{
|
||||
DWORD bytesRead = 0;
|
||||
std::string pszBuff(li.LowPart + 1, '\0');
|
||||
std::string pszBuff(static_cast<size_t>(li.LowPart) + 1, '\0');
|
||||
|
||||
RETURN_LAST_ERROR_IF(!ReadFile(handle, pszBuff.data(), li.LowPart, &bytesRead, NULL));
|
||||
RETURN_LAST_ERROR_IF(!ReadFile(handle, pszBuff.data(), li.LowPart, &bytesRead, nullptr));
|
||||
pszBuff.resize(bytesRead);
|
||||
|
||||
m_strAppOfflineContent = pszBuff;
|
||||
|
|
@ -55,7 +56,7 @@ HRESULT AppOfflineApplication::OnAppOfflineFound()
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
bool AppOfflineApplication::ShouldBeStarted(IHttpApplication& pApplication)
|
||||
bool AppOfflineApplication::ShouldBeStarted(const IHttpApplication& pApplication)
|
||||
{
|
||||
return FileExists(GetAppOfflineLocation(pApplication));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
HRESULT OnAppOfflineFound() override;
|
||||
|
||||
static bool ShouldBeStarted(IHttpApplication& pApplication);
|
||||
static bool ShouldBeStarted(const IHttpApplication& pApplication);
|
||||
|
||||
private:
|
||||
std::string m_strAppOfflineContent;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
REQUEST_NOTIFICATION_STATUS AppOfflineHandler::OnExecuteRequestHandler()
|
||||
{
|
||||
HTTP_DATA_CHUNK DataChunk;
|
||||
IHttpResponse* pResponse = m_pContext->GetResponse();
|
||||
HTTP_DATA_CHUNK DataChunk {};
|
||||
auto pResponse = m_pContext.GetResponse();
|
||||
|
||||
DBG_ASSERT(pResponse);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
class AppOfflineHandler: public REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
AppOfflineHandler(IHttpContext* pContext, const std::string appOfflineContent)
|
||||
AppOfflineHandler(IHttpContext& pContext, const std::string appOfflineContent)
|
||||
: m_pContext(pContext),
|
||||
m_strAppOfflineContent(appOfflineContent)
|
||||
{
|
||||
|
|
@ -18,6 +18,6 @@ public:
|
|||
REQUEST_NOTIFICATION_STATUS OnExecuteRequestHandler() override;
|
||||
|
||||
private:
|
||||
IHttpContext* m_pContext;
|
||||
IHttpContext& m_pContext;
|
||||
std::string m_strAppOfflineContent;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "iapplication.h"
|
||||
#include "HandleWrapper.h"
|
||||
|
||||
|
|
@ -21,9 +22,9 @@ HRESULT
|
|||
class ApplicationFactory
|
||||
{
|
||||
public:
|
||||
ApplicationFactory(HMODULE hRequestHandlerDll, std::wstring location, PFN_ASPNETCORE_CREATE_APPLICATION pfnAspNetCoreCreateApplication):
|
||||
ApplicationFactory(HMODULE hRequestHandlerDll, std::wstring location, PFN_ASPNETCORE_CREATE_APPLICATION pfnAspNetCoreCreateApplication) noexcept:
|
||||
m_pfnAspNetCoreCreateApplication(pfnAspNetCoreCreateApplication),
|
||||
m_location(location),
|
||||
m_location(std::move(location)),
|
||||
m_hRequestHandlerDll(hRequestHandlerDll)
|
||||
{
|
||||
}
|
||||
|
|
@ -31,10 +32,10 @@ public:
|
|||
HRESULT Execute(
|
||||
_In_ IHttpServer *pServer,
|
||||
_In_ IHttpApplication *pHttpApplication,
|
||||
_Out_ IAPPLICATION **pApplication) const
|
||||
_Outptr_ IAPPLICATION **pApplication) const noexcept
|
||||
{
|
||||
std::array<APPLICATION_PARAMETER, 1> parameters {
|
||||
{"InProcessExeLocation", reinterpret_cast<const void*>(m_location.data())}
|
||||
{"InProcessExeLocation", m_location.data()}
|
||||
};
|
||||
return m_pfnAspNetCoreCreateApplication(pServer, pHttpApplication, parameters.data(), static_cast<DWORD>(parameters.size()), pApplication);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\Build\Build.Settings" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
|
|
@ -56,6 +55,7 @@
|
|||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="..\..\..\Build\Build.Settings" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
|
|
|
|||
|
|
@ -14,11 +14,12 @@
|
|||
#include "resources.h"
|
||||
#include "ConfigurationLoadException.h"
|
||||
#include "WebConfigConfigurationSource.h"
|
||||
#include "ModuleHelpers.h"
|
||||
|
||||
const PCWSTR HandlerResolver::s_pwzAspnetcoreInProcessRequestHandlerName = L"aspnetcorev2_inprocess.dll";
|
||||
const PCWSTR HandlerResolver::s_pwzAspnetcoreOutOfProcessRequestHandlerName = L"aspnetcorev2_outofprocess.dll";
|
||||
|
||||
HandlerResolver::HandlerResolver(HMODULE hModule, IHttpServer &pServer)
|
||||
HandlerResolver::HandlerResolver(HMODULE hModule, const IHttpServer &pServer)
|
||||
: m_hModule(hModule),
|
||||
m_pServer(pServer),
|
||||
m_loadedApplicationHostingModel(HOSTING_UNKNOWN)
|
||||
|
|
@ -27,11 +28,11 @@ HandlerResolver::HandlerResolver(HMODULE hModule, IHttpServer &pServer)
|
|||
}
|
||||
|
||||
HRESULT
|
||||
HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory)
|
||||
HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory)
|
||||
{
|
||||
HRESULT hr;
|
||||
PCWSTR pstrHandlerDllName;
|
||||
bool preventUnload;
|
||||
HRESULT hr = S_OK;
|
||||
PCWSTR pstrHandlerDllName = nullptr;
|
||||
bool preventUnload = false;
|
||||
if (pConfiguration.QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
||||
{
|
||||
preventUnload = false;
|
||||
|
|
@ -56,10 +57,10 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, Shim
|
|||
std::unique_ptr<IOutputManager> outputManager;
|
||||
|
||||
RETURN_IF_FAILED(HOSTFXR_OPTIONS::Create(
|
||||
NULL,
|
||||
pConfiguration.QueryProcessPath().c_str(),
|
||||
L"",
|
||||
pConfiguration.QueryProcessPath(),
|
||||
pApplication.GetApplicationPhysicalPath(),
|
||||
pConfiguration.QueryArguments().c_str(),
|
||||
pConfiguration.QueryArguments(),
|
||||
options));
|
||||
|
||||
location = options->GetDotnetExeLocation();
|
||||
|
|
@ -76,7 +77,7 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, Shim
|
|||
hr = FindNativeAssemblyFromHostfxr(*options.get(), pstrHandlerDllName, handlerDllPath);
|
||||
outputManager->Stop();
|
||||
|
||||
if (FAILED(hr) && m_hHostFxrDll != NULL)
|
||||
if (FAILED(hr) && m_hHostFxrDll != nullptr)
|
||||
{
|
||||
STRA content;
|
||||
STRU struStdMsg;
|
||||
|
|
@ -119,7 +120,7 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, Shim
|
|||
RETURN_LAST_ERROR_IF_NULL(hRequestHandlerDll);
|
||||
}
|
||||
|
||||
auto pfnAspNetCoreCreateApplication = reinterpret_cast<PFN_ASPNETCORE_CREATE_APPLICATION>(GetProcAddress(hRequestHandlerDll, "CreateApplication"));
|
||||
auto pfnAspNetCoreCreateApplication = ModuleHelpers::GetKnownProcAddress<PFN_ASPNETCORE_CREATE_APPLICATION>(hRequestHandlerDll, "CreateApplication");
|
||||
RETURN_LAST_ERROR_IF_NULL(pfnAspNetCoreCreateApplication);
|
||||
|
||||
pApplicationFactory = std::make_unique<ApplicationFactory>(hRequestHandlerDll.release(), location, pfnAspNetCoreCreateApplication);
|
||||
|
|
@ -127,7 +128,7 @@ HandlerResolver::LoadRequestHandlerAssembly(IHttpApplication &pApplication, Shim
|
|||
}
|
||||
|
||||
HRESULT
|
||||
HandlerResolver::GetApplicationFactory(IHttpApplication &pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory)
|
||||
HandlerResolver::GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -189,7 +190,7 @@ void HandlerResolver::ResetHostingModel()
|
|||
|
||||
HRESULT
|
||||
HandlerResolver::FindNativeAssemblyFromGlobalLocation(
|
||||
ShimOptions& pConfiguration,
|
||||
const ShimOptions& pConfiguration,
|
||||
PCWSTR pstrHandlerDllName,
|
||||
std::wstring& handlerDllPath
|
||||
)
|
||||
|
|
@ -225,20 +226,20 @@ HandlerResolver::FindNativeAssemblyFromGlobalLocation(
|
|||
//
|
||||
HRESULT
|
||||
HandlerResolver::FindNativeAssemblyFromHostfxr(
|
||||
HOSTFXR_OPTIONS& hostfxrOptions,
|
||||
const HOSTFXR_OPTIONS& hostfxrOptions,
|
||||
PCWSTR libraryName,
|
||||
std::wstring& handlerDllPath
|
||||
)
|
||||
{
|
||||
std::wstring struNativeSearchPaths;
|
||||
size_t intIndex;
|
||||
size_t intIndex = 0;
|
||||
size_t intPrevIndex = 0;
|
||||
DWORD dwBufferSize = s_initialGetNativeSearchDirectoriesBufferSize;
|
||||
DWORD dwRequiredBufferSize = 0;
|
||||
|
||||
RETURN_LAST_ERROR_IF_NULL(m_hHostFxrDll = LoadLibraryW(hostfxrOptions.GetHostFxrLocation().c_str()));
|
||||
|
||||
auto pFnHostFxrSearchDirectories = reinterpret_cast<hostfxr_get_native_search_directories_fn>(GetProcAddress(m_hHostFxrDll, "hostfxr_get_native_search_directories"));
|
||||
const auto pFnHostFxrSearchDirectories = ModuleHelpers::GetKnownProcAddress<hostfxr_get_native_search_directories_fn>(m_hHostFxrDll, "hostfxr_get_native_search_directories");
|
||||
if (pFnHostFxrSearchDirectories == nullptr)
|
||||
{
|
||||
EventLog::Error(
|
||||
|
|
|
|||
|
|
@ -13,17 +13,17 @@
|
|||
class HandlerResolver
|
||||
{
|
||||
public:
|
||||
HandlerResolver(HMODULE hModule, IHttpServer &pServer);
|
||||
HRESULT GetApplicationFactory(IHttpApplication &pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory);
|
||||
HandlerResolver(HMODULE hModule, const IHttpServer &pServer);
|
||||
HRESULT GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory);
|
||||
void ResetHostingModel();
|
||||
|
||||
private:
|
||||
HRESULT LoadRequestHandlerAssembly(IHttpApplication &pApplication, ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory);
|
||||
HRESULT FindNativeAssemblyFromGlobalLocation(ShimOptions& pConfiguration, PCWSTR libraryName, std::wstring& handlerDllPath);
|
||||
HRESULT FindNativeAssemblyFromHostfxr(HOSTFXR_OPTIONS& hostfxrOptions, PCWSTR libraryName, std::wstring& handlerDllPath);
|
||||
HRESULT LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory);
|
||||
HRESULT FindNativeAssemblyFromGlobalLocation(const ShimOptions& pConfiguration, PCWSTR libraryName, std::wstring& handlerDllPath);
|
||||
HRESULT FindNativeAssemblyFromHostfxr(const HOSTFXR_OPTIONS& hostfxrOptions, PCWSTR libraryName, std::wstring& handlerDllPath);
|
||||
|
||||
HMODULE m_hModule;
|
||||
IHttpServer &m_pServer;
|
||||
const IHttpServer &m_pServer;
|
||||
|
||||
SRWLOCK m_requestHandlerLoadLock {};
|
||||
std::wstring m_loadedApplicationId;
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ PollingAppOfflineApplication::CheckAppOffline()
|
|||
}
|
||||
|
||||
|
||||
std::filesystem::path PollingAppOfflineApplication::GetAppOfflineLocation(IHttpApplication& pApplication)
|
||||
std::filesystem::path PollingAppOfflineApplication::GetAppOfflineLocation(const IHttpApplication& pApplication)
|
||||
{
|
||||
return std::filesystem::path(pApplication.GetApplicationPhysicalPath()) / "app_offline.htm";
|
||||
}
|
||||
|
||||
bool PollingAppOfflineApplication::FileExists(const std::filesystem::path& path)
|
||||
bool PollingAppOfflineApplication::FileExists(const std::filesystem::path& path) noexcept
|
||||
{
|
||||
std::error_code ec;
|
||||
return is_regular_file(path, ec) || ec.value() == ERROR_SHARING_VIOLATION;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ public:
|
|||
|
||||
protected:
|
||||
std::filesystem::path m_appOfflineLocation;
|
||||
static std::filesystem::path GetAppOfflineLocation(IHttpApplication& pApplication);
|
||||
static bool FileExists(const std::filesystem::path& path);
|
||||
static std::filesystem::path GetAppOfflineLocation(const IHttpApplication& pApplication);
|
||||
static bool FileExists(const std::filesystem::path& path) noexcept;
|
||||
private:
|
||||
static const int c_appOfflineRefreshIntervalMS = 200;
|
||||
std::string m_strAppOfflineContent;
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ public:
|
|||
|
||||
~ServerErrorApplication() = default;
|
||||
|
||||
HRESULT CreateHandler(IHttpContext * pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override
|
||||
HRESULT CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler) override
|
||||
{
|
||||
*pRequestHandler = new ServerErrorHandler(pHttpContext, m_HR);
|
||||
auto handler = std::make_unique<ServerErrorHandler>(*pHttpContext, m_HR);
|
||||
*pRequestHandler = handler.release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OnAppOfflineFound() override { return S_OK; }
|
||||
HRESULT OnAppOfflineFound() noexcept override { return S_OK; }
|
||||
private:
|
||||
HRESULT m_HR;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@
|
|||
class ServerErrorHandler : public REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
ServerErrorHandler(IHttpContext* pContext, HRESULT hr) : m_pContext(pContext), m_HR(hr)
|
||||
ServerErrorHandler(IHttpContext &pContext, HRESULT hr) : m_pContext(pContext), m_HR(hr)
|
||||
{
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS OnExecuteRequestHandler() override
|
||||
{
|
||||
m_pContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, m_HR);
|
||||
m_pContext.GetResponse()->SetStatus(500, "Internal Server Error", 0, m_HR);
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
|
||||
private:
|
||||
IHttpContext * m_pContext;
|
||||
IHttpContext &m_pContext;
|
||||
HRESULT m_HR;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,37 +18,37 @@ class ShimOptions: NonCopyable
|
|||
{
|
||||
public:
|
||||
const std::wstring&
|
||||
QueryProcessPath() const
|
||||
QueryProcessPath() const noexcept
|
||||
{
|
||||
return m_strProcessPath;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryArguments() const
|
||||
QueryArguments() const noexcept
|
||||
{
|
||||
return m_strArguments;
|
||||
}
|
||||
|
||||
APP_HOSTING_MODEL
|
||||
QueryHostingModel() const
|
||||
QueryHostingModel() const noexcept
|
||||
{
|
||||
return m_hostingModel;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryHandlerVersion() const
|
||||
QueryHandlerVersion() const noexcept
|
||||
{
|
||||
return m_strHandlerVersion;
|
||||
}
|
||||
|
||||
BOOL
|
||||
QueryStdoutLogEnabled() const
|
||||
QueryStdoutLogEnabled() const noexcept
|
||||
{
|
||||
return m_fStdoutLogEnabled;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryStdoutLogFile() const
|
||||
QueryStdoutLogFile() const noexcept
|
||||
{
|
||||
return m_struStdoutLogFile;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,14 +13,9 @@
|
|||
#include "ServerErrorApplication.h"
|
||||
#include "AppOfflineApplication.h"
|
||||
|
||||
APPLICATION_INFO::~APPLICATION_INFO()
|
||||
{
|
||||
ShutDownApplication(/* fServerInitiated */ false);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::GetOrCreateApplication(
|
||||
IHttpContext *pHttpContext,
|
||||
IHttpContext& pHttpContext,
|
||||
std::unique_ptr<IAPPLICATION, IAPPLICATION_DELETER>& pApplication
|
||||
)
|
||||
{
|
||||
|
|
@ -28,7 +23,7 @@ APPLICATION_INFO::GetOrCreateApplication(
|
|||
|
||||
SRWExclusiveLock lock(m_applicationLock);
|
||||
|
||||
auto& httpApplication = *pHttpContext->GetApplication();
|
||||
auto& httpApplication = *pHttpContext.GetApplication();
|
||||
|
||||
if (m_pApplication != nullptr)
|
||||
{
|
||||
|
|
@ -51,7 +46,10 @@ APPLICATION_INFO::GetOrCreateApplication(
|
|||
if (AppOfflineApplication::ShouldBeStarted(httpApplication))
|
||||
{
|
||||
LOG_INFO(L"Detected app_offline file, creating polling application");
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26409 ) // Disable "Avoid using new", using custom deleter here
|
||||
m_pApplication.reset(new AppOfflineApplication(httpApplication));
|
||||
#pragma warning( pop )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -77,8 +75,11 @@ Finished:
|
|||
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG,
|
||||
httpApplication.GetApplicationId(),
|
||||
hr);
|
||||
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26409 ) // Disable "Avoid using new", using custom deleter here
|
||||
m_pApplication.reset(new ServerErrorApplication(httpApplication, hr));
|
||||
#pragma warning( pop )
|
||||
}
|
||||
|
||||
if (m_pApplication)
|
||||
|
|
@ -97,7 +98,7 @@ APPLICATION_INFO::ShutDownApplication(bool fServerInitiated)
|
|||
|
||||
if (m_pApplication)
|
||||
{
|
||||
LOG_ERRORF(L"Stopping application '%ls'", QueryApplicationInfoKey().c_str());
|
||||
LOG_INFOF(L"Stopping application '%ls'", QueryApplicationInfoKey().c_str());
|
||||
m_pApplication ->Stop(fServerInitiated);
|
||||
m_pApplication = nullptr;
|
||||
m_pApplicationFactory = nullptr;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
extern BOOL g_fRecycleProcessCalled;
|
||||
|
||||
class APPLICATION_INFO
|
||||
class APPLICATION_INFO: NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -29,16 +29,16 @@ public:
|
|||
InitializeSRWLock(&m_applicationLock);
|
||||
}
|
||||
|
||||
~APPLICATION_INFO();
|
||||
~APPLICATION_INFO() = default;
|
||||
|
||||
std::wstring&
|
||||
QueryApplicationInfoKey()
|
||||
const std::wstring&
|
||||
QueryApplicationInfoKey() const noexcept
|
||||
{
|
||||
return m_strInfoKey;
|
||||
}
|
||||
|
||||
std::wstring&
|
||||
QueryConfigPath()
|
||||
const std::wstring&
|
||||
QueryConfigPath() const noexcept
|
||||
{
|
||||
return m_strConfigPath;
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
HRESULT
|
||||
GetOrCreateApplication(
|
||||
IHttpContext *pHttpContext,
|
||||
IHttpContext& pHttpContext,
|
||||
std::unique_ptr<IAPPLICATION, IAPPLICATION_DELETER>& pApplication
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
|
||||
extern BOOL g_fInShutdown;
|
||||
|
||||
// The application manager is a singleton across ANCM.
|
||||
APPLICATION_MANAGER* APPLICATION_MANAGER::sm_pApplicationManager = NULL;
|
||||
|
||||
//
|
||||
// Retrieves the application info from the application manager
|
||||
// Will create the application info if it isn't initalized
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
#include "exceptions.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#define DEFAULT_HASH_BUCKETS 17
|
||||
|
||||
//
|
||||
// This class will manage the lifecycle of all Asp.Net Core applciation
|
||||
// It should be global singleton.
|
||||
|
|
@ -21,25 +19,6 @@ class APPLICATION_MANAGER
|
|||
{
|
||||
public:
|
||||
|
||||
static
|
||||
APPLICATION_MANAGER*
|
||||
GetInstance()
|
||||
{
|
||||
assert(sm_pApplicationManager);
|
||||
return sm_pApplicationManager;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Cleanup()
|
||||
{
|
||||
if(sm_pApplicationManager != NULL)
|
||||
{
|
||||
delete sm_pApplicationManager;
|
||||
sm_pApplicationManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
GetOrCreateApplicationInfo(
|
||||
_In_ IHttpContext& pHttpContext,
|
||||
|
|
@ -53,16 +32,7 @@ public:
|
|||
|
||||
VOID
|
||||
ShutDown();
|
||||
|
||||
static HRESULT StaticInitialize(HMODULE hModule, IHttpServer& pHttpServer)
|
||||
{
|
||||
assert(!sm_pApplicationManager);
|
||||
sm_pApplicationManager = new APPLICATION_MANAGER(hModule, pHttpServer);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
APPLICATION_MANAGER(HMODULE hModule, IHttpServer& pHttpServer) :
|
||||
m_pApplicationInfoHash(NULL),
|
||||
m_fDebugInitialize(FALSE),
|
||||
|
|
@ -72,8 +42,9 @@ private:
|
|||
InitializeSRWLock(&m_srwLock);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_map<std::wstring, std::shared_ptr<APPLICATION_INFO>> m_pApplicationInfoHash;
|
||||
static APPLICATION_MANAGER *sm_pApplicationManager;
|
||||
SRWLOCK m_srwLock {};
|
||||
BOOL m_fDebugInitialize;
|
||||
IHttpServer &m_pHttpServer;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
DECLARE_DEBUG_PRINT_OBJECT("aspnetcorev2.dll");
|
||||
|
||||
HANDLE g_hEventLog = NULL;
|
||||
HANDLE g_hEventLog = nullptr;
|
||||
BOOL g_fRecycleProcessCalled = FALSE;
|
||||
BOOL g_fInShutdown = FALSE;
|
||||
HINSTANCE g_hServerModule;
|
||||
|
|
@ -21,14 +21,14 @@ HINSTANCE g_hServerModule;
|
|||
VOID
|
||||
StaticCleanup()
|
||||
{
|
||||
APPLICATION_MANAGER::Cleanup();
|
||||
if (g_hEventLog != NULL)
|
||||
if (g_hEventLog != nullptr)
|
||||
{
|
||||
DeregisterEventSource(g_hEventLog);
|
||||
g_hEventLog = NULL;
|
||||
g_hEventLog = nullptr;
|
||||
}
|
||||
|
||||
DebugStop();
|
||||
ALLOC_CACHE_HANDLER::StaticTerminate();
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE hModule,
|
||||
|
|
@ -41,11 +41,14 @@ BOOL WINAPI DllMain(HMODULE hModule,
|
|||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
ALLOC_CACHE_HANDLER::StaticInitialize();
|
||||
g_hServerModule = hModule;
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
DebugInitialize(hModule);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
// IIS can cause dll detach to occur before we receive global notifications
|
||||
// For example, when we switch the bitness of the worker process,
|
||||
// this is a bug in IIS. To try to avoid AVs, we will set a global flag
|
||||
|
|
@ -85,21 +88,18 @@ HRESULT
|
|||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HKEY hKey;
|
||||
HKEY hKey {};
|
||||
BOOL fDisableANCM = FALSE;
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY * pFactory = NULL;
|
||||
ASPNET_CORE_GLOBAL_MODULE * pGlobalModule = NULL;
|
||||
|
||||
UNREFERENCED_PARAMETER(dwServerVersion);
|
||||
|
||||
if (pHttpServer->IsCommandLineLaunch())
|
||||
{
|
||||
g_hEventLog = RegisterEventSource(NULL, ASPNETCORE_IISEXPRESS_EVENT_PROVIDER);
|
||||
g_hEventLog = RegisterEventSource(nullptr, ASPNETCORE_IISEXPRESS_EVENT_PROVIDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hEventLog = RegisterEventSource(NULL, ASPNETCORE_EVENT_PROVIDER);
|
||||
g_hEventLog = RegisterEventSource(nullptr, ASPNETCORE_EVENT_PROVIDER);
|
||||
}
|
||||
|
||||
// check whether the feature is disabled due to security reason
|
||||
|
|
@ -109,14 +109,14 @@ HRESULT
|
|||
KEY_READ,
|
||||
&hKey) == NO_ERROR)
|
||||
{
|
||||
DWORD dwType;
|
||||
DWORD dwData;
|
||||
DWORD dwType = 0;
|
||||
DWORD dwData = 0;
|
||||
DWORD cbData;
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"DisableANCM",
|
||||
NULL,
|
||||
nullptr,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
|
|
@ -136,7 +136,7 @@ HRESULT
|
|||
ASPNETCORE_EVENT_MODULE_DISABLED_MSG);
|
||||
// this will return 500 error to client
|
||||
// as we did not register the module
|
||||
goto Finished;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -144,43 +144,22 @@ HRESULT
|
|||
// The ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate method will clean any
|
||||
// static object initialized.
|
||||
//
|
||||
pFactory = new ASPNET_CORE_PROXY_MODULE_FACTORY;
|
||||
|
||||
auto applicationManager = std::make_shared<APPLICATION_MANAGER>(g_hServerModule, *pHttpServer);
|
||||
auto moduleFactory = std::make_unique<ASPNET_CORE_PROXY_MODULE_FACTORY>(applicationManager);
|
||||
|
||||
FINISHED_IF_FAILED(pModuleInfo->SetRequestNotifications(
|
||||
pFactory,
|
||||
RETURN_IF_FAILED(pModuleInfo->SetRequestNotifications(
|
||||
moduleFactory.release(),
|
||||
RQ_EXECUTE_REQUEST_HANDLER,
|
||||
0));
|
||||
;
|
||||
auto pGlobalModule = std::make_unique<ASPNET_CORE_GLOBAL_MODULE>(std::move(applicationManager));
|
||||
|
||||
pFactory = NULL;
|
||||
|
||||
FINISHED_IF_FAILED(APPLICATION_MANAGER::StaticInitialize(g_hServerModule, *pHttpServer));
|
||||
|
||||
pGlobalModule = NULL;
|
||||
|
||||
pGlobalModule = new ASPNET_CORE_GLOBAL_MODULE(APPLICATION_MANAGER::GetInstance());
|
||||
|
||||
FINISHED_IF_FAILED(pModuleInfo->SetGlobalNotifications(
|
||||
pGlobalModule,
|
||||
RETURN_IF_FAILED(pModuleInfo->SetGlobalNotifications(
|
||||
pGlobalModule.release(),
|
||||
GL_CONFIGURATION_CHANGE | // Configuration change trigers IIS application stop
|
||||
GL_STOP_LISTENING)); // worker process stop or recycle
|
||||
|
||||
pGlobalModule = NULL;
|
||||
|
||||
FINISHED_IF_FAILED(ALLOC_CACHE_HANDLER::StaticInitialize());
|
||||
|
||||
Finished:
|
||||
if (pGlobalModule != NULL)
|
||||
{
|
||||
delete pGlobalModule;
|
||||
pGlobalModule = NULL;
|
||||
}
|
||||
|
||||
if (pFactory != NULL)
|
||||
{
|
||||
pFactory->Terminate();
|
||||
pFactory = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
|
|
|||
|
|
@ -5,10 +5,9 @@
|
|||
|
||||
extern BOOL g_fInShutdown;
|
||||
|
||||
ASPNET_CORE_GLOBAL_MODULE::ASPNET_CORE_GLOBAL_MODULE(
|
||||
APPLICATION_MANAGER* pApplicationManager)
|
||||
ASPNET_CORE_GLOBAL_MODULE::ASPNET_CORE_GLOBAL_MODULE(std::shared_ptr<APPLICATION_MANAGER> pApplicationManager) noexcept
|
||||
:m_pApplicationManager(std::move(pApplicationManager))
|
||||
{
|
||||
m_pApplicationManager = pApplicationManager;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -30,11 +29,8 @@ ASPNET_CORE_GLOBAL_MODULE::OnGlobalStopListening(
|
|||
return GL_NOTIFICATION_CONTINUE;
|
||||
}
|
||||
|
||||
DBG_ASSERT(m_pApplicationManager);
|
||||
// we should let application manager to shutdown all allication
|
||||
// and dereference it as some requests may still reference to application manager
|
||||
m_pApplicationManager->ShutDown();
|
||||
m_pApplicationManager = NULL;
|
||||
m_pApplicationManager = nullptr;
|
||||
|
||||
// Return processing to the pipeline.
|
||||
return GL_NOTIFICATION_CONTINUE;
|
||||
|
|
@ -59,13 +55,13 @@ ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange(
|
|||
LOG_INFOF(L"ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange '%ls'", pwszChangePath);
|
||||
|
||||
// Test for an error.
|
||||
if (NULL != pwszChangePath &&
|
||||
if (nullptr != pwszChangePath &&
|
||||
_wcsicmp(pwszChangePath, L"MACHINE") != 0 &&
|
||||
_wcsicmp(pwszChangePath, L"MACHINE/WEBROOT") != 0)
|
||||
{
|
||||
if (m_pApplicationManager != NULL)
|
||||
if (m_pApplicationManager)
|
||||
{
|
||||
m_pApplicationManager->RecycleApplicationFromManager(pwszChangePath);
|
||||
m_pApplicationManager->RecycleApplicationFromManager(pwszChangePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,20 +5,18 @@
|
|||
|
||||
#include "applicationmanager.h"
|
||||
|
||||
class ASPNET_CORE_GLOBAL_MODULE : public CGlobalModule
|
||||
class ASPNET_CORE_GLOBAL_MODULE : NonCopyable, public CGlobalModule
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
ASPNET_CORE_GLOBAL_MODULE(
|
||||
APPLICATION_MANAGER* pApplicationManager
|
||||
);
|
||||
std::shared_ptr<APPLICATION_MANAGER> pApplicationManager
|
||||
) noexcept;
|
||||
|
||||
~ASPNET_CORE_GLOBAL_MODULE()
|
||||
{
|
||||
}
|
||||
virtual ~ASPNET_CORE_GLOBAL_MODULE() = default;
|
||||
|
||||
VOID Terminate()
|
||||
VOID Terminate() override
|
||||
{
|
||||
LOG_INFO(L"ASPNET_CORE_GLOBAL_MODULE::Terminate");
|
||||
// Remove the class from memory.
|
||||
|
|
@ -28,13 +26,13 @@ public:
|
|||
GLOBAL_NOTIFICATION_STATUS
|
||||
OnGlobalStopListening(
|
||||
_In_ IGlobalStopListeningProvider * pProvider
|
||||
);
|
||||
) override;
|
||||
|
||||
GLOBAL_NOTIFICATION_STATUS
|
||||
OnGlobalConfigurationChange(
|
||||
_In_ IGlobalConfigurationChangeProvider * pProvider
|
||||
);
|
||||
) override;
|
||||
|
||||
private:
|
||||
APPLICATION_MANAGER * m_pApplicationManager;
|
||||
std::shared_ptr<APPLICATION_MANAGER> m_pApplicationManager;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,31 +5,40 @@
|
|||
|
||||
#include "applicationmanager.h"
|
||||
#include "applicationinfo.h"
|
||||
#include "acache.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
extern BOOL g_fInShutdown;
|
||||
|
||||
__override
|
||||
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY::ASPNET_CORE_PROXY_MODULE_FACTORY(std::shared_ptr<APPLICATION_MANAGER> applicationManager) noexcept
|
||||
:m_pApplicationManager(std::move(applicationManager))
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY::GetHttpModule(
|
||||
CHttpModule ** ppModule,
|
||||
IModuleAllocator * pAllocator
|
||||
)
|
||||
{
|
||||
try
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26409 ) // Disable "Avoid using new"
|
||||
*ppModule = new (pAllocator) ASPNET_CORE_PROXY_MODULE(m_pApplicationManager);
|
||||
#pragma warning( push )
|
||||
if (*ppModule == nullptr)
|
||||
{
|
||||
*ppModule = THROW_IF_NULL_ALLOC(new (pAllocator) ASPNET_CORE_PROXY_MODULE());;
|
||||
return S_OK;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
__override
|
||||
VOID
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate(
|
||||
VOID
|
||||
)
|
||||
) noexcept
|
||||
/*++
|
||||
|
||||
Routine description:
|
||||
|
|
@ -46,12 +55,13 @@ Return value:
|
|||
|
||||
--*/
|
||||
{
|
||||
ALLOC_CACHE_HANDLER::StaticTerminate();
|
||||
delete this;
|
||||
}
|
||||
|
||||
ASPNET_CORE_PROXY_MODULE::ASPNET_CORE_PROXY_MODULE(
|
||||
) : m_pApplicationInfo(nullptr), m_pHandler(nullptr)
|
||||
ASPNET_CORE_PROXY_MODULE::ASPNET_CORE_PROXY_MODULE(std::shared_ptr<APPLICATION_MANAGER> applicationManager) noexcept
|
||||
: m_pApplicationManager(std::move(applicationManager)),
|
||||
m_pApplicationInfo(nullptr),
|
||||
m_pHandler(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +74,7 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
|||
{
|
||||
HRESULT hr = S_OK;
|
||||
REQUEST_NOTIFICATION_STATUS retVal = RQ_NOTIFICATION_CONTINUE;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
|
|
@ -72,14 +83,12 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
|||
FINISHED(HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS));
|
||||
}
|
||||
|
||||
auto pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
||||
|
||||
FINISHED_IF_FAILED(pApplicationManager->GetOrCreateApplicationInfo(
|
||||
FINISHED_IF_FAILED(m_pApplicationManager->GetOrCreateApplicationInfo(
|
||||
*pHttpContext,
|
||||
m_pApplicationInfo));
|
||||
|
||||
std::unique_ptr<IAPPLICATION, IAPPLICATION_DELETER> pApplication;
|
||||
FINISHED_IF_FAILED(m_pApplicationInfo->GetOrCreateApplication(pHttpContext, pApplication));
|
||||
FINISHED_IF_FAILED(m_pApplicationInfo->GetOrCreateApplication(*pHttpContext, pApplication));
|
||||
|
||||
IREQUEST_HANDLER* pHandler;
|
||||
// Create RequestHandler and process the request
|
||||
|
|
@ -94,7 +103,7 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
|||
}
|
||||
|
||||
Finished:
|
||||
if (LOG_IF_FAILED(hr))
|
||||
if (FAILED(LOG_IF_FAILED(hr)))
|
||||
{
|
||||
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS))
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@
|
|||
#include <memory>
|
||||
#include "applicationinfo.h"
|
||||
#include "irequesthandler.h"
|
||||
#include "applicationmanager.h"
|
||||
|
||||
extern HTTP_MODULE_ID g_pModuleId;
|
||||
|
||||
class ASPNET_CORE_PROXY_MODULE : public CHttpModule
|
||||
class ASPNET_CORE_PROXY_MODULE : NonCopyable, public CHttpModule
|
||||
{
|
||||
public:
|
||||
|
||||
ASPNET_CORE_PROXY_MODULE();
|
||||
ASPNET_CORE_PROXY_MODULE(std::shared_ptr<APPLICATION_MANAGER> applicationManager) noexcept;
|
||||
|
||||
~ASPNET_CORE_PROXY_MODULE() = default;
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ class ASPNET_CORE_PROXY_MODULE : public CHttpModule
|
|||
OnExecuteRequestHandler(
|
||||
IHttpContext * pHttpContext,
|
||||
IHttpEventProvider * pProvider
|
||||
);
|
||||
) override;
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
|
|
@ -43,22 +44,29 @@ class ASPNET_CORE_PROXY_MODULE : public CHttpModule
|
|||
BOOL fPostNotification,
|
||||
IHttpEventProvider * pProvider,
|
||||
IHttpCompletionInfo * pCompletionInfo
|
||||
);
|
||||
) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<APPLICATION_MANAGER> m_pApplicationManager;
|
||||
std::shared_ptr<APPLICATION_INFO> m_pApplicationInfo;
|
||||
std::unique_ptr<IREQUEST_HANDLER, IREQUEST_HANDLER_DELETER> m_pHandler;
|
||||
std::unique_ptr<IREQUEST_HANDLER, IREQUEST_HANDLER_DELETER> m_pHandler;
|
||||
};
|
||||
|
||||
class ASPNET_CORE_PROXY_MODULE_FACTORY : public IHttpModuleFactory
|
||||
class ASPNET_CORE_PROXY_MODULE_FACTORY : NonCopyable, public IHttpModuleFactory
|
||||
{
|
||||
public:
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY(std::shared_ptr<APPLICATION_MANAGER> applicationManager) noexcept;
|
||||
virtual ~ASPNET_CORE_PROXY_MODULE_FACTORY() = default;
|
||||
|
||||
HRESULT
|
||||
GetHttpModule(
|
||||
CHttpModule ** ppModule,
|
||||
IModuleAllocator * pAllocator
|
||||
);
|
||||
) override;
|
||||
|
||||
VOID
|
||||
Terminate();
|
||||
Terminate() noexcept override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<APPLICATION_MANAGER> m_pApplicationManager;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,16 +72,20 @@
|
|||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\AspNetCoreModule\src\IISLib;$(IncludePath)</IncludePath>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
|
@ -195,7 +199,6 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="application.h" />
|
||||
<ClInclude Include="ConfigurationLoadException.h" />
|
||||
<ClInclude Include="ConfigurationSection.h" />
|
||||
<ClInclude Include="ConfigurationSource.h" />
|
||||
<ClInclude Include="config_utility.h" />
|
||||
|
|
@ -211,9 +214,11 @@
|
|||
<ClInclude Include="hostfxr_utility.h" />
|
||||
<ClInclude Include="iapplication.h" />
|
||||
<ClInclude Include="debugutil.h" />
|
||||
<ClInclude Include="InvalidOperationException.h" />
|
||||
<ClInclude Include="IOutputManager.h" />
|
||||
<ClInclude Include="irequesthandler.h" />
|
||||
<ClInclude Include="LoggingHelpers.h" />
|
||||
<ClInclude Include="ModuleHelpers.h" />
|
||||
<ClInclude Include="NonCopyable.h" />
|
||||
<ClInclude Include="NullOutputManager.h" />
|
||||
<ClInclude Include="PipeOutputManager.h" />
|
||||
|
|
|
|||
|
|
@ -26,6 +26,16 @@ bool ConfigurationSection::GetRequiredBool(const std::wstring& name) const
|
|||
return result.value();
|
||||
}
|
||||
|
||||
DWORD ConfigurationSection::GetRequiredLong(const std::wstring& name) const
|
||||
{
|
||||
auto result = GetLong(name);
|
||||
if (!result.has_value())
|
||||
{
|
||||
ThrowRequiredException(name);
|
||||
}
|
||||
return result.value();
|
||||
}
|
||||
|
||||
DWORD ConfigurationSection::GetRequiredTimespan(const std::wstring& name) const
|
||||
{
|
||||
auto result = GetTimespan(name);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#define CS_ASPNETCORE_PROCESS_EXE_PATH L"processPath"
|
||||
#define CS_ASPNETCORE_PROCESS_ARGUMENTS L"arguments"
|
||||
#define CS_ASPNETCORE_PROCESS_ARGUMENTS_DEFAULT L""
|
||||
#define CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT L"startupTimeLimit"
|
||||
#define CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT L"shutdownTimeLimit"
|
||||
#define CS_ASPNETCORE_HOSTING_MODEL_OUTOFPROCESS L"outofprocess"
|
||||
#define CS_ASPNETCORE_HOSTING_MODEL_INPROCESS L"inprocess"
|
||||
#define CS_ASPNETCORE_HOSTING_MODEL L"hostingModel"
|
||||
|
|
@ -31,10 +33,12 @@ public:
|
|||
virtual ~ConfigurationSection() = default;
|
||||
virtual std::optional<std::wstring> GetString(const std::wstring& name) const = 0;
|
||||
virtual std::optional<bool> GetBool(const std::wstring& name) const = 0;
|
||||
virtual std::optional<DWORD> GetLong(const std::wstring& name) const = 0;
|
||||
virtual std::optional<DWORD> GetTimespan(const std::wstring& name) const = 0;
|
||||
|
||||
std::wstring GetRequiredString(const std::wstring& name) const;
|
||||
bool GetRequiredBool(const std::wstring& name) const;
|
||||
DWORD GetRequiredLong(const std::wstring& name) const;
|
||||
DWORD GetRequiredTimespan(const std::wstring& name) const;
|
||||
|
||||
virtual std::vector<std::pair<std::wstring, std::wstring>> GetKeyValuePairs(const std::wstring& name) const = 0;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,46 @@
|
|||
#include <array>
|
||||
#include "EventLog.h"
|
||||
#include "debugutil.h"
|
||||
#include "StringHelpers.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
extern HANDLE g_hEventLog;
|
||||
|
||||
bool
|
||||
EventLog::LogEventNoTrace(
|
||||
_In_ WORD dwEventInfoType,
|
||||
_In_ DWORD dwEventId,
|
||||
_In_ LPCWSTR pstrMsg
|
||||
)
|
||||
{
|
||||
if (g_hEventLog == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Static locals to avoid getting the process ID and string multiple times.
|
||||
// Effectively have the same semantics as global variables, except initialized
|
||||
// on first occurence.
|
||||
static const auto processIdString = GetProcessIdString();
|
||||
static const auto versionInfoString = GetVersionInfoString();
|
||||
|
||||
std::array<LPCWSTR, 3> eventLogDataStrings
|
||||
{
|
||||
pstrMsg,
|
||||
processIdString.c_str(),
|
||||
versionInfoString.c_str()
|
||||
};
|
||||
|
||||
return ReportEventW(g_hEventLog,
|
||||
dwEventInfoType,
|
||||
0, // wCategory
|
||||
dwEventId,
|
||||
NULL, // lpUserSid
|
||||
static_cast<WORD>(eventLogDataStrings.size()), // wNumStrings
|
||||
0, // dwDataSize,
|
||||
eventLogDataStrings.data(),
|
||||
NULL // lpRawData
|
||||
);
|
||||
}
|
||||
|
||||
VOID
|
||||
EventLog::LogEvent(
|
||||
_In_ WORD dwEventInfoType,
|
||||
|
|
@ -15,32 +51,7 @@ EventLog::LogEvent(
|
|||
_In_ LPCWSTR pstrMsg
|
||||
)
|
||||
{
|
||||
// Static locals to avoid getting the process ID and string multiple times.
|
||||
// Effectively have the same semantics as global variables, except initialized
|
||||
// on first occurence.
|
||||
static const auto processIdString = GetProcessIdString();
|
||||
static const auto versionInfoString = GetVersionInfoString();
|
||||
|
||||
std::array<LPCWSTR, 3> eventLogDataStrings
|
||||
{
|
||||
pstrMsg,
|
||||
processIdString.c_str(),
|
||||
versionInfoString.c_str()
|
||||
};
|
||||
|
||||
if (g_hEventLog != NULL)
|
||||
{
|
||||
ReportEventW(g_hEventLog,
|
||||
dwEventInfoType,
|
||||
0, // wCategory
|
||||
dwEventId,
|
||||
NULL, // lpUserSid
|
||||
3, // wNumStrings
|
||||
0, // dwDataSize,
|
||||
eventLogDataStrings.data(),
|
||||
NULL // lpRawData
|
||||
);
|
||||
}
|
||||
LOG_LAST_ERROR_IF(!LogEventNoTrace(dwEventInfoType, dwEventId, pstrMsg));
|
||||
|
||||
DebugPrintfW(dwEventInfoType == EVENTLOG_ERROR_TYPE ? ASPNETCORE_DEBUG_FLAG_ERROR : ASPNETCORE_DEBUG_FLAG_INFO, L"Event Log: '%ls' \r\nEnd Event Log Message.", pstrMsg);
|
||||
}
|
||||
|
|
@ -50,7 +61,7 @@ EventLog::LogEventF(
|
|||
_In_ WORD dwEventInfoType,
|
||||
_In_ DWORD dwEventId,
|
||||
_In_ LPCWSTR pstrMsg,
|
||||
va_list argsList
|
||||
_In_ va_list argsList
|
||||
)
|
||||
{
|
||||
STACK_STRU ( strEventMsg, 256 );
|
||||
|
|
|
|||
|
|
@ -5,6 +5,18 @@
|
|||
|
||||
#include "resources.h"
|
||||
|
||||
#define _va_start(ap, x) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:26481 26492)) /*Don't use pointer arithmetic. Don't use const_cast to cast away const.*/ \
|
||||
va_start(ap, x) \
|
||||
__pragma(warning(pop))
|
||||
|
||||
#define _va_end(args) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:26477)) /*Use 'nullptr' rather than 0 or NULL*/ \
|
||||
va_end(args) \
|
||||
__pragma(warning(pop))
|
||||
|
||||
class EventLog
|
||||
{
|
||||
public:
|
||||
|
|
@ -16,9 +28,9 @@ public:
|
|||
...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pstrMsg);
|
||||
_va_start(args, pstrMsg);
|
||||
LogEventF(EVENTLOG_ERROR_TYPE, dwEventId, pstrMsg, args);
|
||||
va_end(args);
|
||||
_va_end(args);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -29,9 +41,9 @@ public:
|
|||
...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pstrMsg);
|
||||
_va_start(args, pstrMsg);
|
||||
LogEventF(EVENTLOG_INFORMATION_TYPE, dwEventId, pstrMsg, args);
|
||||
va_end(args);
|
||||
_va_end(args);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -42,11 +54,18 @@ public:
|
|||
...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pstrMsg);
|
||||
_va_start(args, pstrMsg);
|
||||
LogEventF(EVENTLOG_WARNING_TYPE, dwEventId, pstrMsg, args);
|
||||
va_end(args);
|
||||
_va_end(args);
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LogEventNoTrace(
|
||||
_In_ WORD dwEventInfoType,
|
||||
_In_ DWORD dwEventId,
|
||||
_In_ LPCWSTR pstrMsg);
|
||||
|
||||
private:
|
||||
static
|
||||
VOID
|
||||
|
|
|
|||
|
|
@ -49,6 +49,17 @@ FileOutputManager::Start()
|
|||
STRU struPath;
|
||||
FILETIME processCreationTime;
|
||||
FILETIME dummyFileTime;
|
||||
|
||||
// To make Console.* functions work, allocate a console
|
||||
// in the current process.
|
||||
if (!AllocConsole())
|
||||
{
|
||||
// ERROR_ACCESS_DENIED means there is a console already present.
|
||||
if (GetLastError() != ERROR_ACCESS_DENIED)
|
||||
{
|
||||
RETURN_LAST_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
// Concatenate the log file name and application path
|
||||
RETURN_IF_FAILED(FILE_UTILITY::ConvertPathToFullPath(
|
||||
|
|
@ -163,7 +174,7 @@ FileOutputManager::Stop()
|
|||
|
||||
if (li.LowPart == 0 || li.HighPart > 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
dwFilePointer = SetFilePointer(m_hLogFileHandle, 0, NULL, FILE_BEGIN);
|
||||
|
|
|
|||
|
|
@ -10,37 +10,41 @@ struct InvalidHandleTraits
|
|||
{
|
||||
using HandleType = HANDLE;
|
||||
static const HANDLE DefaultHandle;
|
||||
static void Close(HANDLE handle) { CloseHandle(handle); }
|
||||
static void Close(HANDLE handle) noexcept { CloseHandle(handle); }
|
||||
};
|
||||
|
||||
struct NullHandleTraits
|
||||
{
|
||||
using HandleType = HANDLE;
|
||||
static constexpr HANDLE DefaultHandle = NULL;
|
||||
static void Close(HANDLE handle) { CloseHandle(handle); }
|
||||
static constexpr HANDLE DefaultHandle = nullptr;
|
||||
static void Close(HANDLE handle) noexcept { CloseHandle(handle); }
|
||||
};
|
||||
|
||||
struct FindFileHandleTraits
|
||||
{
|
||||
using HandleType = HANDLE;
|
||||
static const HANDLE DefaultHandle;
|
||||
static void Close(HANDLE handle) { FindClose(handle); }
|
||||
static void Close(HANDLE handle) noexcept { FindClose(handle); }
|
||||
};
|
||||
|
||||
struct ModuleHandleTraits
|
||||
{
|
||||
using HandleType = HMODULE;
|
||||
static constexpr HMODULE DefaultHandle = NULL;
|
||||
static void Close(HMODULE handle) { FreeModule(handle); }
|
||||
static constexpr HMODULE DefaultHandle = nullptr;
|
||||
static void Close(HMODULE handle) noexcept { FreeModule(handle); }
|
||||
};
|
||||
|
||||
// Code analysis doesn't like nullptr usages via traits
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26477 ) // disable Use 'nullptr' rather than 0 or NULL (es.47).
|
||||
|
||||
template<typename traits>
|
||||
class HandleWrapper
|
||||
{
|
||||
public:
|
||||
using HandleType = typename traits::HandleType;
|
||||
|
||||
HandleWrapper(HandleType handle = traits::DefaultHandle) : m_handle(handle) { }
|
||||
HandleWrapper(HandleType handle = traits::DefaultHandle) noexcept : m_handle(handle) { }
|
||||
~HandleWrapper()
|
||||
{
|
||||
if (m_handle != traits::DefaultHandle)
|
||||
|
|
@ -49,15 +53,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
operator HandleType() { return m_handle; }
|
||||
HandleWrapper& operator =(HandleType value)
|
||||
operator HandleType() noexcept { return m_handle; }
|
||||
HandleWrapper& operator =(HandleType value) noexcept
|
||||
{
|
||||
DBG_ASSERT(m_handle == traits::DefaultHandle);
|
||||
m_handle = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HandleType* operator&() { return &m_handle; }
|
||||
HandleType* operator&() noexcept { return &m_handle; }
|
||||
|
||||
HandleType release() noexcept
|
||||
{
|
||||
|
|
@ -69,3 +73,5 @@ public:
|
|||
private:
|
||||
HandleType m_handle;
|
||||
};
|
||||
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public:
|
|||
Start() = 0;
|
||||
|
||||
virtual
|
||||
~IOutputManager() {};
|
||||
~IOutputManager() = default;
|
||||
|
||||
virtual
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
class InvalidOperationException: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidOperationException(std::wstring msg)
|
||||
: runtime_error("InvalidOperationException"), message(std::move(msg))
|
||||
{
|
||||
}
|
||||
|
||||
std::wstring as_wstring() const
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring message;
|
||||
};
|
||||
|
|
@ -27,13 +27,18 @@ LoggingHelpers::CreateLoggingProvider(
|
|||
|
||||
try
|
||||
{
|
||||
// Check if there is an existing active console window before redirecting
|
||||
// Window == IISExpress with active console window, don't redirect to a pipe
|
||||
// if true.
|
||||
CONSOLE_SCREEN_BUFFER_INFO dummy;
|
||||
|
||||
if (fIsLoggingEnabled)
|
||||
{
|
||||
auto manager = std::make_unique<FileOutputManager>(fEnableNativeLogging);
|
||||
hr = manager->Initialize(pwzStdOutFileName, pwzApplicationPath);
|
||||
outputManager = std::move(manager);
|
||||
}
|
||||
else if (!GetConsoleWindow())
|
||||
else if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &dummy))
|
||||
{
|
||||
outputManager = std::make_unique<PipeOutputManager>(fEnableNativeLogging);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
#include "HandleWrapper.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
extern HMODULE g_hModule;
|
||||
|
||||
class ModuleHelpers
|
||||
{
|
||||
public:
|
||||
static
|
||||
void IncrementCurrentModuleRefCount(HandleWrapper<ModuleHandleTraits> &handle)
|
||||
{
|
||||
WCHAR path[MAX_PATH];
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26485 ) // Calling WinAPI causes expected array to pointer decay
|
||||
|
||||
THROW_LAST_ERROR_IF(!GetModuleFileName(g_hModule, path, MAX_PATH));
|
||||
THROW_LAST_ERROR_IF(!GetModuleHandleEx(0, path, &handle));
|
||||
|
||||
#pragma warning( pop )
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
static
|
||||
Func GetKnownProcAddress(HMODULE hModule, LPCSTR lpProcName) {
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26490 ) // Disable Don't use reinterpret_cast
|
||||
auto proc = reinterpret_cast<Func>(GetProcAddress(hModule, lpProcName));
|
||||
#pragma warning( pop )
|
||||
|
||||
THROW_LAST_ERROR_IF (!proc);
|
||||
return proc;
|
||||
}
|
||||
};
|
||||
|
|
@ -6,6 +6,6 @@
|
|||
class NonCopyable {
|
||||
public:
|
||||
NonCopyable() = default;
|
||||
NonCopyable(const NonCopyable&) = default;
|
||||
NonCopyable& operator=(const NonCopyable&) = default;
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
NonCopyable& operator=(const NonCopyable&) = delete;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,17 @@ HRESULT PipeOutputManager::Start()
|
|||
HANDLE hStdErrReadPipe;
|
||||
HANDLE hStdErrWritePipe;
|
||||
|
||||
// To make Console.* functions work, allocate a console
|
||||
// in the current process.
|
||||
if (!AllocConsole())
|
||||
{
|
||||
// ERROR_ACCESS_DENIED means there is a console already present.
|
||||
if (GetLastError() != ERROR_ACCESS_DENIED)
|
||||
{
|
||||
RETURN_LAST_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_LAST_ERROR_IF(!CreatePipe(&hStdErrReadPipe, &hStdErrWritePipe, &saAttr, 0 /*nSize*/));
|
||||
|
||||
m_hErrReadPipe = hStdErrReadPipe;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class ResultException: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
ResultException(HRESULT hr, LOCATION_ARGUMENTS_ONLY) :
|
||||
runtime_error(format("HRESULT 0x%x returned at " LOCATION_FORMAT, hr, LOCATION_CALL_ONLY)),
|
||||
m_hr(hr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT GetResult() const noexcept { return m_hr; }
|
||||
|
||||
private:
|
||||
HRESULT m_hr;
|
||||
};
|
||||
|
|
@ -78,14 +78,14 @@ StdWrapper::StartRedirection()
|
|||
|
||||
if (fileDescriptor == -1)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
m_redirectedFile = _fdopen(fileDescriptor, "w");
|
||||
|
||||
if (m_redirectedFile == nullptr)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
// Set stdout/stderr to the newly created file.
|
||||
|
|
@ -93,13 +93,13 @@ StdWrapper::StartRedirection()
|
|||
|
||||
if (dup2Result != 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
// Removes buffering from the output
|
||||
if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
|
@ -117,7 +117,7 @@ StdWrapper::StopRedirection() const
|
|||
FILE * file = _fdopen(m_previousFileDescriptor, "w");
|
||||
if (file == nullptr)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
RETURN_LAST_ERROR_IF(!SetStdHandle(m_stdHandleNumber, reinterpret_cast<HANDLE>(_get_osfhandle(m_previousFileDescriptor))));
|
||||
|
|
@ -131,17 +131,17 @@ StdWrapper::StopRedirection() const
|
|||
const auto dup2Result = _dup2(_fileno(file), _fileno(m_stdStream));
|
||||
if (dup2Result != 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
if (setvbuf(m_stdStream, nullptr, _IONBF, 0) != 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
if (fclose(m_redirectedFile) != 0)
|
||||
{
|
||||
RETURN_IF_FAILED(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
RETURN_HR(HRESULT_FROM_WIN32(ERROR_FILE_INVALID));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
|
|
|||
|
|
@ -15,19 +15,33 @@ template<typename ... Args>
|
|||
[[nodiscard]]
|
||||
std::wstring format(const std::wstring& format, Args ... args)
|
||||
{
|
||||
const size_t size = swprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra char for '\0'
|
||||
std::unique_ptr<wchar_t[]> formattedBuffer(new wchar_t[size]);
|
||||
swprintf(formattedBuffer.get(), size, format.c_str(), args ... );
|
||||
return std::wstring(formattedBuffer.get(), formattedBuffer.get() + size - 1);
|
||||
std::wstring result;
|
||||
if (!format.empty())
|
||||
{
|
||||
const size_t size = swprintf(nullptr, 0, format.c_str(), args ...); // Extra char for '\0'
|
||||
result.resize(size + 1);
|
||||
if (swprintf(result.data(), result.size(), format.c_str(), args ... ) == -1)
|
||||
{
|
||||
throw std::system_error(std::error_code(errno, std::system_category()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ... Args>
|
||||
[[nodiscard]]
|
||||
std::string format(const std::string& format, Args ... args)
|
||||
{
|
||||
const size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra char for '\0'
|
||||
std::unique_ptr<char[]> formattedBuffer(new char[size]);
|
||||
snprintf(formattedBuffer.get(), size, format.c_str(), args ... );
|
||||
return std::string(formattedBuffer.get(), formattedBuffer.get() + size - 1);
|
||||
std::string result;
|
||||
if (!format.empty())
|
||||
{
|
||||
const size_t size = snprintf(nullptr, 0, format.c_str(), args ...); // Extra char for '\0'
|
||||
result.resize(size + 1);
|
||||
if (snprintf(result.data(), result.size(), format.c_str(), args ... ) == -1)
|
||||
{
|
||||
throw std::system_error(std::error_code(errno, std::system_category()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,17 @@ std::optional<bool> WebConfigConfigurationSection::GetBool(const std::wstring& n
|
|||
return std::make_optional(result);
|
||||
}
|
||||
|
||||
std::optional<DWORD> WebConfigConfigurationSection::GetLong(const std::wstring& name) const
|
||||
{
|
||||
DWORD result;
|
||||
if (FAILED_LOG(GetElementDWORDProperty(m_element, name.c_str(), &result)))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::make_optional(result);
|
||||
}
|
||||
|
||||
std::optional<DWORD> WebConfigConfigurationSection::GetTimespan(const std::wstring& name) const
|
||||
{
|
||||
ULONGLONG result;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
std::optional<std::wstring> GetString(const std::wstring& name) const override;
|
||||
std::optional<bool> GetBool(const std::wstring& name) const override;
|
||||
std::optional<DWORD> GetLong(const std::wstring& name) const override;
|
||||
std::optional<DWORD> GetTimespan(const std::wstring& name) const override;
|
||||
std::vector<std::pair<std::wstring, std::wstring>> GetKeyValuePairs(const std::wstring& name) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
class WebConfigConfigurationSource: public ConfigurationSource
|
||||
{
|
||||
public:
|
||||
WebConfigConfigurationSource(IAppHostAdminManager *pAdminManager, IHttpApplication &pHttpApplication)
|
||||
WebConfigConfigurationSource(IAppHostAdminManager *pAdminManager, const IHttpApplication &pHttpApplication) noexcept
|
||||
: m_manager(pAdminManager),
|
||||
m_application(pHttpApplication)
|
||||
{
|
||||
|
|
@ -19,5 +19,5 @@ public:
|
|||
|
||||
private:
|
||||
CComPtr<IAppHostAdminManager> m_manager;
|
||||
IHttpApplication &m_application;
|
||||
const IHttpApplication &m_application;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "iapplication.h"
|
||||
#include "ntassert.h"
|
||||
#include "SRWExclusiveLock.h"
|
||||
#include "SRWSharedLock.h"
|
||||
|
||||
class APPLICATION : public IAPPLICATION
|
||||
{
|
||||
|
|
@ -15,11 +16,6 @@ public:
|
|||
APPLICATION(const APPLICATION&) = delete;
|
||||
const APPLICATION& operator=(const APPLICATION&) = delete;
|
||||
|
||||
APPLICATION_STATUS
|
||||
QueryStatus() override
|
||||
{
|
||||
return m_fStopCalled ? APPLICATION_STATUS::RECYCLED : APPLICATION_STATUS::RUNNING;
|
||||
}
|
||||
|
||||
APPLICATION(const IHttpApplication& pHttpApplication)
|
||||
: m_fStopCalled(false),
|
||||
|
|
@ -32,6 +28,12 @@ public:
|
|||
m_applicationVirtualPath = ToVirtualPath(m_applicationConfigPath);
|
||||
}
|
||||
|
||||
APPLICATION_STATUS
|
||||
QueryStatus() override
|
||||
{
|
||||
SRWSharedLock stateLock(m_stateLock);
|
||||
return m_fStopCalled ? APPLICATION_STATUS::RECYCLED : APPLICATION_STATUS::RUNNING;
|
||||
}
|
||||
|
||||
VOID
|
||||
Stop(bool fServerInitiated) override
|
||||
|
|
@ -56,7 +58,7 @@ public:
|
|||
}
|
||||
|
||||
VOID
|
||||
ReferenceApplication() override
|
||||
ReferenceApplication() noexcept override
|
||||
{
|
||||
DBG_ASSERT(m_cRefs > 0);
|
||||
|
||||
|
|
@ -64,7 +66,7 @@ public:
|
|||
}
|
||||
|
||||
VOID
|
||||
DereferenceApplication() override
|
||||
DereferenceApplication() noexcept override
|
||||
{
|
||||
DBG_ASSERT(m_cRefs > 0);
|
||||
|
||||
|
|
@ -75,25 +77,25 @@ public:
|
|||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryApplicationId() const
|
||||
QueryApplicationId() const noexcept
|
||||
{
|
||||
return m_applicationId;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryApplicationPhysicalPath() const
|
||||
QueryApplicationPhysicalPath() const noexcept
|
||||
{
|
||||
return m_applicationPhysicalPath;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryApplicationVirtualPath() const
|
||||
QueryApplicationVirtualPath() const noexcept
|
||||
{
|
||||
return m_applicationVirtualPath;
|
||||
}
|
||||
|
||||
const std::wstring&
|
||||
QueryConfigPath() const
|
||||
QueryConfigPath() const noexcept
|
||||
{
|
||||
return m_applicationConfigPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,12 @@ Language=English
|
|||
%1
|
||||
.
|
||||
|
||||
Messageid=1036
|
||||
SymbolicName=ASPNETCORE_EVENT_DEBUG_LOG
|
||||
Language=English
|
||||
%1
|
||||
.
|
||||
|
||||
|
||||
;
|
||||
;#endif // _ASPNETCORE_MODULE_MSG_H_
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
LANGUAGE 0x9,0x1
|
||||
1 11 "MSG00001.bin"
|
||||
|
|
@ -3,17 +3,19 @@
|
|||
|
||||
#include "debugutil.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include "dbgutil.h"
|
||||
#include "stringu.h"
|
||||
#include "stringa.h"
|
||||
#include "dbgutil.h"
|
||||
#include "Environment.h"
|
||||
#include "SRWExclusiveLock.h"
|
||||
#include "exceptions.h"
|
||||
#include "atlbase.h"
|
||||
#include "config_utility.h"
|
||||
#include "StringHelpers.h"
|
||||
#include "aspnetcore_msg.h"
|
||||
#include "EventLog.h"
|
||||
|
||||
inline HANDLE g_logFile = INVALID_HANDLE_VALUE;
|
||||
inline HMODULE g_hModule;
|
||||
|
|
@ -23,7 +25,7 @@ HRESULT
|
|||
PrintDebugHeader()
|
||||
{
|
||||
// Major, minor are stored in dwFileVersionMS field and patch, build in dwFileVersionLS field as pair of 32 bit numbers
|
||||
DebugPrintfW(ASPNETCORE_DEBUG_FLAG_INFO, L"Initializing logs for '%ls'. %ls. %ls.",
|
||||
LOG_INFOF(L"Initializing logs for '%ls'. %ls. %ls.",
|
||||
GetModuleName().c_str(),
|
||||
GetProcessIdString().c_str(),
|
||||
GetVersionInfoString().c_str()
|
||||
|
|
@ -92,26 +94,6 @@ GetModuleName()
|
|||
|
||||
void SetDebugFlags(const std::wstring &debugValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!debugValue.empty() && debugValue.find_first_not_of(L"0123456789") == std::wstring::npos)
|
||||
{
|
||||
const auto value = std::stoi(debugValue);
|
||||
|
||||
if (value >= 1) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_ERROR;
|
||||
if (value >= 2) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_WARNING;
|
||||
if (value >= 3) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_INFO;
|
||||
if (value >= 4) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_CONSOLE;
|
||||
if (value >= 5) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_FILE;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::wstringstream stringStream(debugValue);
|
||||
|
|
@ -122,14 +104,16 @@ void SetDebugFlags(const std::wstring &debugValue)
|
|||
if (_wcsnicmp(flag.c_str(), L"error", wcslen(L"error")) == 0) DEBUG_FLAGS_VAR |= DEBUG_FLAGS_ERROR;
|
||||
if (_wcsnicmp(flag.c_str(), L"warning", wcslen(L"warning")) == 0) DEBUG_FLAGS_VAR |= DEBUG_FLAGS_WARN;
|
||||
if (_wcsnicmp(flag.c_str(), L"info", wcslen(L"info")) == 0) DEBUG_FLAGS_VAR |= DEBUG_FLAGS_INFO;
|
||||
if (_wcsnicmp(flag.c_str(), L"trace", wcslen(L"trace")) == 0) DEBUG_FLAGS_VAR |= DEBUG_FLAGS_TRACE;
|
||||
if (_wcsnicmp(flag.c_str(), L"console", wcslen(L"console")) == 0) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_CONSOLE;
|
||||
if (_wcsnicmp(flag.c_str(), L"file", wcslen(L"file")) == 0) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_FILE;
|
||||
if (_wcsnicmp(flag.c_str(), L"eventlog", wcslen(L"eventlog")) == 0) DEBUG_FLAGS_VAR |= ASPNETCORE_DEBUG_FLAG_EVENTLOG;
|
||||
}
|
||||
|
||||
// If file or console is enabled but level is not set, enable all levels
|
||||
// If file or console is enabled but level is not set, enable levels up to info
|
||||
if (DEBUG_FLAGS_VAR != 0 && (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ANY) == 0)
|
||||
{
|
||||
DEBUG_FLAGS_VAR |= DEBUG_FLAGS_ANY;
|
||||
DEBUG_FLAGS_VAR |= DEBUG_FLAGS_INFO;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
|
@ -209,7 +193,7 @@ DebugInitialize(HMODULE hModule)
|
|||
|
||||
try
|
||||
{
|
||||
SetDebugFlags(Environment::GetEnvironmentVariableValue(L"ASPNETCORE_MODULE_DEBUG").value_or(L"0"));
|
||||
SetDebugFlags(Environment::GetEnvironmentVariableValue(L"ASPNETCORE_MODULE_DEBUG").value_or(L""));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
@ -344,6 +328,24 @@ DebugPrintW(
|
|||
FlushFileBuffers(g_logFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEnabled(ASPNETCORE_DEBUG_FLAG_EVENTLOG))
|
||||
{
|
||||
WORD eventType;
|
||||
switch (dwFlag)
|
||||
{
|
||||
case ASPNETCORE_DEBUG_FLAG_ERROR:
|
||||
eventType = EVENTLOG_ERROR_TYPE;
|
||||
break;
|
||||
case ASPNETCORE_DEBUG_FLAG_WARNING:
|
||||
eventType = EVENTLOG_WARNING_TYPE;
|
||||
break;
|
||||
default:
|
||||
eventType = EVENTLOG_INFORMATION_TYPE;
|
||||
break;
|
||||
}
|
||||
EventLog::LogEventNoTrace(eventType, ASPNETCORE_EVENT_DEBUG_LOG, strOutput.QueryStr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,16 @@
|
|||
#include <Windows.h>
|
||||
#include "dbgutil.h"
|
||||
|
||||
#define ASPNETCORE_DEBUG_FLAG_TRACE DEBUG_FLAG_TRACE
|
||||
#define ASPNETCORE_DEBUG_FLAG_INFO DEBUG_FLAG_INFO
|
||||
#define ASPNETCORE_DEBUG_FLAG_WARNING DEBUG_FLAG_WARN
|
||||
#define ASPNETCORE_DEBUG_FLAG_ERROR DEBUG_FLAG_ERROR
|
||||
#define ASPNETCORE_DEBUG_FLAG_CONSOLE 0x00000008
|
||||
#define ASPNETCORE_DEBUG_FLAG_FILE 0x00000010
|
||||
#define ASPNETCORE_DEBUG_FLAG_CONSOLE 0x00000010
|
||||
#define ASPNETCORE_DEBUG_FLAG_FILE 0x00000020
|
||||
#define ASPNETCORE_DEBUG_FLAG_EVENTLOG 0x00000040
|
||||
|
||||
#define LOG_TRACE(...) DebugPrintW(ASPNETCORE_DEBUG_FLAG_TRACE, __VA_ARGS__)
|
||||
#define LOG_TRACEF(...) DebugPrintfW(ASPNETCORE_DEBUG_FLAG_TRACE, __VA_ARGS__)
|
||||
|
||||
#define LOG_INFO(...) DebugPrintW(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
|
||||
#define LOG_INFOF(...) DebugPrintfW(ASPNETCORE_DEBUG_FLAG_INFO, __VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <system_error>
|
||||
|
||||
#include "debugutil.h"
|
||||
#include "StringHelpers.h"
|
||||
#include "InvalidOperationException.h"
|
||||
|
||||
#define LOCATION_INFO_ENABLED TRUE
|
||||
|
||||
|
|
@ -29,22 +31,38 @@
|
|||
#define OBSERVE_CAUGHT_EXCEPTION() CaughtExceptionHResult(LOCATION_INFO);
|
||||
#define RETURN_CAUGHT_EXCEPTION() return CaughtExceptionHResult(LOCATION_INFO);
|
||||
|
||||
#define RETURN_HR(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } return __hrRet; } while (0, 0)
|
||||
#define _CHECK_FAILED(expr) __pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) /*disable condition is const warning*/ \
|
||||
FAILED(expr) \
|
||||
__pragma(warning(pop))
|
||||
|
||||
#define _HR_RET(hr) __pragma(warning(push)) \
|
||||
__pragma(warning(disable:26498)) /*disable constexpr warning */ \
|
||||
const HRESULT __hrRet = hr; \
|
||||
__pragma(warning(pop))
|
||||
|
||||
#define RETURN_HR(hr) do { _HR_RET(hr); if (_CHECK_FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } return __hrRet; } while (0, 0)
|
||||
#define RETURN_LAST_ERROR() do { return LogLastError(LOCATION_INFO); } while (0, 0)
|
||||
#define RETURN_IF_FAILED(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); return __hrRet; }} while (0, 0)
|
||||
#define RETURN_IF_FAILED(hr) do { _HR_RET(hr); if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); return __hrRet; }} while (0, 0)
|
||||
#define RETURN_LAST_ERROR_IF(condition) do { if (condition) { return LogLastError(LOCATION_INFO); }} while (0, 0)
|
||||
#define RETURN_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { return LogLastError(LOCATION_INFO); }} while (0, 0)
|
||||
|
||||
#define FINISHED(hrr) do { HRESULT __hrRet = hrr; LogHResultFailed(LOCATION_INFO, __hrRet); hr = __hrRet; goto Finished; } while (0, 0)
|
||||
#define FINISHED_IF_FAILED(hrr) do { HRESULT __hrRet = hrr; if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); hr = __hrRet; goto Finished; }} while (0, 0)
|
||||
#define FINISHED_IF_NULL_ALLOC(ptr) do { if ((ptr) == nullptr) { hr = LogHResultFailed(LOCATION_INFO, E_OUTOFMEMORY); goto Finished; }} while (0, 0)
|
||||
#define FINISHED_LAST_ERROR_IF(condition) do { if (condition) { hr = LogLastError(LOCATION_INFO); goto Finished; }} while (0, 0)
|
||||
#define FINISHED_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { hr = LogLastError(LOCATION_INFO); goto Finished; }} while (0, 0)
|
||||
#define _GOTO_FINISHED() __pragma(warning(push)) \
|
||||
__pragma(warning(disable:26438)) /*disable avoid goto warning*/ \
|
||||
goto Finished \
|
||||
__pragma(warning(pop))
|
||||
|
||||
#define THROW_LAST_ERROR() do { ThrowResultException(LogLastError(LOCATION_INFO)); } while (0, 0)
|
||||
#define THROW_IF_FAILED(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { ThrowResultException(LOCATION_INFO, __hrRet); }} while (0, 0)
|
||||
#define THROW_LAST_ERROR_IF(condition) do { if (condition) { ThrowResultException(LogLastError(LOCATION_INFO)); }} while (0, 0)
|
||||
#define THROW_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { ThrowResultException(LogLastError(LOCATION_INFO)); }} while (0, 0)
|
||||
|
||||
#define FINISHED(hrr) do { _HR_RET(hrr); if (_CHECK_FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } hr = __hrRet; _GOTO_FINISHED(); } while (0, 0)
|
||||
#define FINISHED_IF_FAILED(hrr) do { _HR_RET(hrr); if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); hr = __hrRet; _GOTO_FINISHED(); }} while (0, 0)
|
||||
#define FINISHED_IF_NULL_ALLOC(ptr) do { if ((ptr) == nullptr) { hr = LogHResultFailed(LOCATION_INFO, E_OUTOFMEMORY); _GOTO_FINISHED(); }} while (0, 0)
|
||||
#define FINISHED_LAST_ERROR_IF(condition) do { if (condition) { hr = LogLastError(LOCATION_INFO); _GOTO_FINISHED(); }} while (0, 0)
|
||||
#define FINISHED_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { hr = LogLastError(LOCATION_INFO); _GOTO_FINISHED(); }} while (0, 0)
|
||||
|
||||
#define THROW_LAST_ERROR() do { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); } while (0, 0)
|
||||
#define THROW_IF_FAILED(hr) do { _HR_RET(hr); if (FAILED(__hrRet)) { ThrowResultException(LOCATION_INFO, __hrRet); }} while (0, 0)
|
||||
#define THROW_LAST_ERROR_IF(condition) do { if (condition) { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); }} while (0, 0)
|
||||
#define THROW_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); }} while (0, 0)
|
||||
|
||||
#define THROW_IF_NULL_ALLOC(ptr) Throw_IfNullAlloc(ptr)
|
||||
|
||||
|
|
@ -55,21 +73,24 @@
|
|||
#define SUCCEEDED_LOG(hr) SUCCEEDED(LOG_IF_FAILED(hr))
|
||||
#define FAILED_LOG(hr) FAILED(LOG_IF_FAILED(hr))
|
||||
|
||||
|
||||
class ResultException: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit ResultException(HRESULT hr, LOCATION_ARGUMENTS_ONLY) :
|
||||
ResultException(HRESULT hr, LOCATION_ARGUMENTS_ONLY) :
|
||||
runtime_error(format("HRESULT 0x%x returned at " LOCATION_FORMAT, hr, LOCATION_CALL_ONLY)),
|
||||
m_hr(hr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT GetResult() const { return m_hr; }
|
||||
HRESULT GetResult() const noexcept { return m_hr; }
|
||||
|
||||
private:
|
||||
HRESULT m_hr;
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26495 ) // bug in CA: m_hr is reported as uninitialized
|
||||
const HRESULT m_hr = S_OK;
|
||||
};
|
||||
#pragma warning( pop )
|
||||
|
||||
__declspec(noinline) inline VOID ReportUntypedException(LOCATION_ARGUMENTS_ONLY)
|
||||
{
|
||||
|
|
@ -96,7 +117,7 @@ private:
|
|||
return condition;
|
||||
}
|
||||
|
||||
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS std::exception& exception)
|
||||
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const std::exception& exception)
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Exception '%s' caught at " LOCATION_FORMAT, exception.what(), LOCATION_CALL_ONLY);
|
||||
}
|
||||
|
|
@ -120,12 +141,12 @@ __declspec(noinline) inline HRESULT CaughtExceptionHResult(LOCATION_ARGUMENTS_ON
|
|||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (ResultException& exception)
|
||||
catch (const ResultException& exception)
|
||||
{
|
||||
ReportException(LOCATION_CALL exception);
|
||||
return exception.GetResult();
|
||||
}
|
||||
catch (std::exception& exception)
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
ReportException(LOCATION_CALL exception);
|
||||
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||
|
|
@ -152,3 +173,7 @@ template <typename PointerT> auto Throw_IfNullAlloc(PointerT pointer)
|
|||
}
|
||||
return pointer;
|
||||
}
|
||||
__declspec(noinline) inline std::wstring GetUnexpectedExceptionMessage(const std::runtime_error& ex)
|
||||
{
|
||||
return format(L"Unexpected exception: %S", ex.what());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ struct fx_ver_t
|
|||
fx_ver_t(int major, int minor, int patch, const std::wstring& pre);
|
||||
fx_ver_t(int major, int minor, int patch, const std::wstring& pre, const std::wstring& build);
|
||||
|
||||
int get_major() const { return m_major; }
|
||||
int get_minor() const { return m_minor; }
|
||||
int get_patch() const { return m_patch; }
|
||||
int get_major() const noexcept { return m_major; }
|
||||
int get_minor() const noexcept { return m_minor; }
|
||||
int get_patch() const noexcept { return m_patch; }
|
||||
|
||||
void set_major(int m) { m_major = m; }
|
||||
void set_minor(int m) { m_minor = m; }
|
||||
void set_patch(int p) { m_patch = p; }
|
||||
void set_major(int m) noexcept { m_major = m; }
|
||||
void set_minor(int m) noexcept { m_minor = m; }
|
||||
void set_patch(int p) noexcept { m_patch = p; }
|
||||
|
||||
bool is_prerelease() const { return !m_pre.empty(); }
|
||||
bool is_prerelease() const noexcept { return !m_pre.empty(); }
|
||||
|
||||
std::wstring as_str() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
}
|
||||
else if (!ends_with(expandedProcessPath, L".exe", true))
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"Process path '%s' doesn't have '.exe' extension.", expandedProcessPath.c_str()));
|
||||
throw InvalidOperationException(format(L"Process path '%s' doesn't have '.exe' extension.", expandedProcessPath.c_str()));
|
||||
}
|
||||
|
||||
// Check if the absolute path is to dotnet or not.
|
||||
|
|
@ -51,7 +51,7 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
|
||||
if (applicationArguments.empty())
|
||||
{
|
||||
throw StartupParametersResolutionException(L"Application arguments are empty.");
|
||||
throw InvalidOperationException(L"Application arguments are empty.");
|
||||
}
|
||||
|
||||
if (dotnetExePath.empty())
|
||||
|
|
@ -92,7 +92,7 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
LOG_INFOF(L"Checking application.dll at '%ls'", applicationDllPath.c_str());
|
||||
if (!is_regular_file(applicationDllPath))
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"Application .dll was not found at %s", applicationDllPath.c_str()));
|
||||
throw InvalidOperationException(format(L"Application .dll was not found at %s", applicationDllPath.c_str()));
|
||||
}
|
||||
|
||||
hostFxrDllPath = executablePath.parent_path() / "hostfxr.dll";
|
||||
|
|
@ -131,7 +131,7 @@ HOSTFXR_UTILITY::GetHostFxrParameters(
|
|||
// If the processPath file does not exist and it doesn't include dotnet.exe or dotnet
|
||||
// then it is an invalid argument.
|
||||
//
|
||||
throw StartupParametersResolutionException(format(L"Executable was not found at '%s'", executablePath.c_str()));
|
||||
throw InvalidOperationException(format(L"Executable was not found at '%s'", executablePath.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ HOSTFXR_UTILITY::AppendArguments(
|
|||
auto pwzArgs = std::unique_ptr<LPWSTR[], LocalFreeDeleter>(CommandLineToArgvW(applicationArguments.c_str(), &argc));
|
||||
if (!pwzArgs)
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"Unable parse command line arguments '%s'", applicationArguments.c_str()));
|
||||
throw InvalidOperationException(format(L"Unable parse command line arguments '%s'", applicationArguments.c_str()));
|
||||
}
|
||||
|
||||
for (int intArgsProcessed = 0; intArgsProcessed < argc; intArgsProcessed++)
|
||||
|
|
@ -246,7 +246,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
|
|||
{
|
||||
LOG_INFOF(L"Absolute path to dotnet.exe was not found at '%ls'", requestedPath.c_str());
|
||||
|
||||
throw StartupParametersResolutionException(format(L"Could not find dotnet.exe at '%s'", processPath.c_str()));
|
||||
throw InvalidOperationException(format(L"Could not find dotnet.exe at '%s'", processPath.c_str()));
|
||||
}
|
||||
|
||||
const auto dotnetViaWhere = InvokeWhereToFindDotnet();
|
||||
|
|
@ -266,7 +266,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
|
|||
}
|
||||
|
||||
LOG_INFOF(L"dotnet.exe not found");
|
||||
throw StartupParametersResolutionException(format(
|
||||
throw InvalidOperationException(format(
|
||||
L"Could not find dotnet.exe at '%s' or using the system PATH environment variable."
|
||||
" Check that a valid path to dotnet is on the PATH and the bitness of dotnet matches the bitness of the IIS worker process.",
|
||||
processPath.c_str()));
|
||||
|
|
@ -284,14 +284,14 @@ HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
|
|||
|
||||
if (!is_directory(hostFxrBase))
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"Unable to find hostfxr directory at %s", hostFxrBase.c_str()));
|
||||
throw InvalidOperationException(format(L"Unable to find hostfxr directory at %s", hostFxrBase.c_str()));
|
||||
}
|
||||
|
||||
FindDotNetFolders(hostFxrBase, versionFolders);
|
||||
|
||||
if (versionFolders.empty())
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"Hostfxr directory '%s' doesn't contain any version subdirectories", hostFxrBase.c_str()));
|
||||
throw InvalidOperationException(format(L"Hostfxr directory '%s' doesn't contain any version subdirectories", hostFxrBase.c_str()));
|
||||
}
|
||||
|
||||
const auto highestVersion = FindHighestDotNetVersion(versionFolders);
|
||||
|
|
@ -299,7 +299,7 @@ HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
|
|||
|
||||
if (!is_regular_file(hostFxrPath))
|
||||
{
|
||||
throw StartupParametersResolutionException(format(L"hostfxr.dll not found at '%s'", hostFxrPath.c_str()));
|
||||
throw InvalidOperationException(format(L"hostfxr.dll not found at '%s'", hostFxrPath.c_str()));
|
||||
}
|
||||
|
||||
LOG_INFOF(L"hostfxr.dll located at '%ls'", hostFxrPath.c_str());
|
||||
|
|
|
|||
|
|
@ -29,20 +29,6 @@ public:
|
|||
std::vector<std::wstring> &arguments
|
||||
);
|
||||
|
||||
class StartupParametersResolutionException: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
StartupParametersResolutionException(std::wstring msg)
|
||||
: runtime_error("Startup parameter resulution error occured"), message(std::move(msg))
|
||||
{
|
||||
}
|
||||
|
||||
std::wstring get_message() const { return message; }
|
||||
|
||||
private:
|
||||
std::wstring message;
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
AppendArguments(
|
||||
|
|
@ -96,7 +82,7 @@ private:
|
|||
|
||||
struct LocalFreeDeleter
|
||||
{
|
||||
void operator ()(LPWSTR* ptr) const
|
||||
void operator ()(_In_ LPWSTR* ptr) const
|
||||
{
|
||||
LocalFree(ptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,18 +9,19 @@
|
|||
#include "EventLog.h"
|
||||
|
||||
HRESULT HOSTFXR_OPTIONS::Create(
|
||||
_In_ PCWSTR pcwzDotnetExePath,
|
||||
_In_ PCWSTR pcwzProcessPath,
|
||||
_In_ PCWSTR pcwzApplicationPhysicalPath,
|
||||
_In_ PCWSTR pcwzArguments,
|
||||
_In_ const std::wstring& pcwzDotnetExePath,
|
||||
_In_ const std::wstring& pcwzProcessPath,
|
||||
_In_ const std::wstring& pcwzApplicationPhysicalPath,
|
||||
_In_ const std::wstring& pcwzArguments,
|
||||
_Out_ std::unique_ptr<HOSTFXR_OPTIONS>& ppWrapper)
|
||||
{
|
||||
std::filesystem::path knownDotnetLocation;
|
||||
|
||||
if (pcwzDotnetExePath != nullptr)
|
||||
if (!pcwzDotnetExePath.empty())
|
||||
{
|
||||
knownDotnetLocation = pcwzDotnetExePath;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::filesystem::path hostFxrDllPath;
|
||||
|
|
@ -40,17 +41,25 @@ HRESULT HOSTFXR_OPTIONS::Create(
|
|||
}
|
||||
ppWrapper = std::make_unique<HOSTFXR_OPTIONS>(knownDotnetLocation, hostFxrDllPath, arguments);
|
||||
}
|
||||
catch (HOSTFXR_UTILITY::StartupParametersResolutionException &resolutionException)
|
||||
catch (InvalidOperationException &ex)
|
||||
{
|
||||
OBSERVE_CAUGHT_EXCEPTION();
|
||||
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_START_ERROR,
|
||||
ASPNETCORE_EVENT_INPROCESS_START_ERROR_MSG,
|
||||
pcwzApplicationPhysicalPath,
|
||||
resolutionException.get_message().c_str());
|
||||
pcwzApplicationPhysicalPath.c_str(),
|
||||
ex.as_wstring().c_str());
|
||||
|
||||
return E_FAIL;
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
catch (std::runtime_error &ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_START_ERROR,
|
||||
ASPNETCORE_EVENT_INPROCESS_START_ERROR_MSG,
|
||||
pcwzApplicationPhysicalPath.c_str(),
|
||||
GetUnexpectedExceptionMessage(ex).c_str());
|
||||
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public:
|
|||
std::filesystem::path dotnetExeLocation,
|
||||
std::filesystem::path hostFxrLocation,
|
||||
std::vector<std::wstring> arguments
|
||||
)
|
||||
) noexcept
|
||||
: m_dotnetExeLocation(std::move(dotnetExeLocation)),
|
||||
m_hostFxrLocation(std::move(hostFxrLocation)),
|
||||
m_arguments(std::move(arguments))
|
||||
|
|
@ -27,7 +27,7 @@ public:
|
|||
GetArguments(DWORD &hostfxrArgc, std::unique_ptr<PCWSTR[]> &hostfxrArgv) const
|
||||
{
|
||||
hostfxrArgc = static_cast<DWORD>(m_arguments.size());
|
||||
hostfxrArgv = std::unique_ptr<PCWSTR[]>(new PCWSTR[hostfxrArgc]);
|
||||
hostfxrArgv = std::make_unique<PCWSTR[]>(hostfxrArgc);
|
||||
for (DWORD i = 0; i < hostfxrArgc; ++i)
|
||||
{
|
||||
hostfxrArgv[i] = m_arguments[i].c_str();
|
||||
|
|
@ -35,23 +35,23 @@ public:
|
|||
}
|
||||
|
||||
const std::filesystem::path&
|
||||
GetHostFxrLocation() const
|
||||
GetHostFxrLocation() const noexcept
|
||||
{
|
||||
return m_hostFxrLocation;
|
||||
}
|
||||
|
||||
const std::filesystem::path&
|
||||
GetDotnetExeLocation() const
|
||||
GetDotnetExeLocation() const noexcept
|
||||
{
|
||||
return m_dotnetExeLocation;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT Create(
|
||||
_In_ PCWSTR pcwzExeLocation,
|
||||
_In_ PCWSTR pcwzProcessPath,
|
||||
_In_ PCWSTR pcwzApplicationPhysicalPath,
|
||||
_In_ PCWSTR pcwzArguments,
|
||||
_In_ const std::wstring& pcwzExeLocation,
|
||||
_In_ const std::wstring& pcwzProcessPath,
|
||||
_In_ const std::wstring& pcwzApplicationPhysicalPath,
|
||||
_In_ const std::wstring& pcwzArguments,
|
||||
_Out_ std::unique_ptr<HOSTFXR_OPTIONS>& ppWrapper);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
HRESULT
|
||||
CreateHandler(
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ IREQUEST_HANDLER **pRequestHandler) = 0;
|
||||
_Outptr_ IREQUEST_HANDLER **pRequestHandler) = 0;
|
||||
};
|
||||
|
||||
struct IAPPLICATION_DELETER
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ class REQUEST_HANDLER: public virtual IREQUEST_HANDLER
|
|||
|
||||
public:
|
||||
VOID
|
||||
ReferenceRequestHandler() override
|
||||
ReferenceRequestHandler() noexcept override
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceRequestHandler() override
|
||||
DereferenceRequestHandler() noexcept override
|
||||
{
|
||||
DBG_ASSERT(m_cRefs != 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@
|
|||
#define ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown process '%d'."
|
||||
#define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST_MSG L"Sent shutdown HTTP message to process '%d' and received http status '%d'."
|
||||
#define ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown application '%s'."
|
||||
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG L"Application '%s' with physical root '%s' failed to load clr and managed application, ErrorCode = '0x%x."
|
||||
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG L"Application '%s' with physical root '%s' failed to load clr and managed application. %s"
|
||||
#define ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL_MSG L"Application '%s' has shutdown."
|
||||
#define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG L"Only one inprocess application is allowed per IIS application pool. Please assign the application '%s' to a different IIS application pool."
|
||||
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG L"Mixed hosting model is not supported. Application '%s' configured with different hostingModel value '%d' other than the one of running application(s)."
|
||||
#define ASPNETCORE_CONFIGURATION_LOAD_ERROR_MSG L"Configuration load error. %s"
|
||||
#define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG L"Failed to start application '%s', ErrorCode '0x%x'."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x'. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x'. Please check the stderr logs for more information."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, exit code = '%d'. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, exit code = '%d'. Please check the stderr logs for more information."
|
||||
#define ASPNETCORE_EVENT_APP_IN_SHUTDOWN_MSG L"Application shutting down."
|
||||
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_MSG L"Application '%s' was recycled after detecting the app_offline file."
|
||||
#define ASPNETCORE_EVENT_MONITOR_APPOFFLINE_ERROR_MSG L"Monitoring app_offline.htm failed for application '%s', ErrorCode '0x%x'. "
|
||||
|
|
@ -39,7 +39,8 @@
|
|||
#define ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG L"Failed to recycle application due to a configuration change at '%s'. Recycling worker process."
|
||||
#define ASPNETCORE_EVENT_MODULE_DISABLED_MSG L"AspNetCore Module is disabled"
|
||||
#define ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG L"Hostfxr version used does not support 'hostfxr_get_native_search_directories', update the version of hostfxr to a higher version. Path to hostfxr: '%s'."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, ErrorCode = '0x%x. Please check the stderr logs for more information."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x. Please check the stderr logs for more information."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
|
||||
#define ASPNETCORE_EVENT_INPROCESS_RH_ERROR_MSG L"Could not find the assembly '%s' for in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application. Captured output: %s"
|
||||
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG L"Could not find the assembly '%s' for out-of-process application. Please confirm the assembly is installed correctly for IIS or IISExpress."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_START_SUCCESS_MSG L"Application '%s' started the coreclr in-process successfully."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,432 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="DefaultRules" ToolsVersion="15.0">
|
||||
<Include Path="allrules.ruleset" Action="Default" />
|
||||
<Rules AnalyzerId="Microsoft.Analyzers.NativeCodeAnalysis" RuleNamespace="Microsoft.Rules.Native">
|
||||
<Rule Id="C26100" Action="Error" />
|
||||
<Rule Id="C26101" Action="Error" />
|
||||
<Rule Id="C26105" Action="Error" />
|
||||
<Rule Id="C26110" Action="Error" />
|
||||
<Rule Id="C26111" Action="Error" />
|
||||
<Rule Id="C26112" Action="Error" />
|
||||
<Rule Id="C26115" Action="Error" />
|
||||
<Rule Id="C26116" Action="Error" />
|
||||
<Rule Id="C26117" Action="Error" />
|
||||
<Rule Id="C26130" Action="Error" />
|
||||
<Rule Id="C26135" Action="Error" />
|
||||
<Rule Id="C26140" Action="Error" />
|
||||
<Rule Id="C26160" Action="Error" />
|
||||
<Rule Id="C26165" Action="Error" />
|
||||
<Rule Id="C26166" Action="Error" />
|
||||
<Rule Id="C26167" Action="Error" />
|
||||
<Rule Id="C26400" Action="Error" />
|
||||
<Rule Id="C26401" Action="Error" />
|
||||
<Rule Id="C26402" Action="Error" />
|
||||
<Rule Id="C26403" Action="Error" />
|
||||
<Rule Id="C26404" Action="Error" />
|
||||
<Rule Id="C26405" Action="Error" />
|
||||
<Rule Id="C26406" Action="Error" />
|
||||
<Rule Id="C26407" Action="Error" />
|
||||
<Rule Id="C26408" Action="Error" />
|
||||
<Rule Id="C26409" Action="Error" />
|
||||
<Rule Id="C26410" Action="Error" />
|
||||
<Rule Id="C26411" Action="Error" />
|
||||
<Rule Id="C26414" Action="Error" />
|
||||
<Rule Id="C26415" Action="Error" />
|
||||
<Rule Id="C26416" Action="Error" />
|
||||
<Rule Id="C26417" Action="Error" />
|
||||
<Rule Id="C26418" Action="Error" />
|
||||
<Rule Id="C26426" Action="Error" />
|
||||
<Rule Id="C26427" Action="Error" />
|
||||
<Rule Id="C26429" Action="None" />
|
||||
<Rule Id="C26430" Action="Error" />
|
||||
<Rule Id="C26431" Action="Error" />
|
||||
<Rule Id="C26432" Action="None" />
|
||||
<Rule Id="C26433" Action="Error" />
|
||||
<Rule Id="C26434" Action="Error" />
|
||||
<Rule Id="C26435" Action="Error" />
|
||||
<Rule Id="C26436" Action="Error" />
|
||||
<Rule Id="C26437" Action="Error" />
|
||||
<Rule Id="C26438" Action="Error" />
|
||||
<Rule Id="C26439" Action="Error" />
|
||||
<Rule Id="C26440" Action="Error" />
|
||||
<Rule Id="C26441" Action="Error" />
|
||||
<Rule Id="C26443" Action="Error" />
|
||||
<Rule Id="C26444" Action="Error" />
|
||||
<Rule Id="C26445" Action="Error" />
|
||||
<Rule Id="C26446" Action="None" />
|
||||
<Rule Id="C26447" Action="Error" />
|
||||
<Rule Id="C26448" Action="None" />
|
||||
<Rule Id="C26449" Action="Error" />
|
||||
<Rule Id="C26450" Action="Error" />
|
||||
<Rule Id="C26451" Action="Error" />
|
||||
<Rule Id="C26452" Action="Error" />
|
||||
<Rule Id="C26453" Action="Error" />
|
||||
<Rule Id="C26454" Action="Error" />
|
||||
<Rule Id="C26459" Action="Error" />
|
||||
<Rule Id="C26460" Action="Error" />
|
||||
<Rule Id="C26461" Action="Error" />
|
||||
<Rule Id="C26462" Action="Error" />
|
||||
<Rule Id="C26463" Action="Error" />
|
||||
<Rule Id="C26464" Action="Error" />
|
||||
<Rule Id="C26465" Action="Error" />
|
||||
<Rule Id="C26466" Action="Error" />
|
||||
<Rule Id="C26471" Action="Error" />
|
||||
<Rule Id="C26472" Action="None" />
|
||||
<Rule Id="C26473" Action="Error" />
|
||||
<Rule Id="C26474" Action="Error" />
|
||||
<Rule Id="C26475" Action="Error" />
|
||||
<Rule Id="C26476" Action="Error" />
|
||||
<Rule Id="C26477" Action="Error" />
|
||||
<Rule Id="C26481" Action="Error" />
|
||||
<Rule Id="C26482" Action="Error" />
|
||||
<Rule Id="C26483" Action="Error" />
|
||||
<Rule Id="C26485" Action="Error" />
|
||||
<Rule Id="C26486" Action="None" />
|
||||
<Rule Id="C26487" Action="Error" />
|
||||
<Rule Id="C26489" Action="None" />
|
||||
<Rule Id="C26490" Action="Error" />
|
||||
<Rule Id="C26491" Action="Error" />
|
||||
<Rule Id="C26492" Action="Error" />
|
||||
<Rule Id="C26493" Action="Error" />
|
||||
<Rule Id="C26494" Action="Error" />
|
||||
<Rule Id="C26495" Action="Error" />
|
||||
<Rule Id="C26496" Action="Error" />
|
||||
<Rule Id="C26497" Action="Error" />
|
||||
<Rule Id="C26498" Action="Error" />
|
||||
<Rule Id="C28020" Action="Error" />
|
||||
<Rule Id="C28021" Action="Error" />
|
||||
<Rule Id="C28022" Action="Error" />
|
||||
<Rule Id="C28023" Action="Error" />
|
||||
<Rule Id="C28024" Action="Error" />
|
||||
<Rule Id="C28039" Action="Error" />
|
||||
<Rule Id="C28101" Action="Error" />
|
||||
<Rule Id="C28103" Action="Error" />
|
||||
<Rule Id="C28104" Action="Error" />
|
||||
<Rule Id="C28105" Action="Error" />
|
||||
<Rule Id="C28106" Action="Error" />
|
||||
<Rule Id="C28107" Action="Error" />
|
||||
<Rule Id="C28108" Action="Error" />
|
||||
<Rule Id="C28109" Action="Error" />
|
||||
<Rule Id="C28110" Action="Error" />
|
||||
<Rule Id="C28111" Action="Error" />
|
||||
<Rule Id="C28112" Action="Error" />
|
||||
<Rule Id="C28113" Action="Error" />
|
||||
<Rule Id="C28114" Action="Error" />
|
||||
<Rule Id="C28120" Action="Error" />
|
||||
<Rule Id="C28121" Action="Error" />
|
||||
<Rule Id="C28122" Action="Error" />
|
||||
<Rule Id="C28123" Action="Error" />
|
||||
<Rule Id="C28124" Action="Error" />
|
||||
<Rule Id="C28125" Action="Error" />
|
||||
<Rule Id="C28126" Action="Error" />
|
||||
<Rule Id="C28127" Action="Error" />
|
||||
<Rule Id="C28128" Action="Error" />
|
||||
<Rule Id="C28129" Action="Error" />
|
||||
<Rule Id="C28131" Action="Error" />
|
||||
<Rule Id="C28132" Action="Error" />
|
||||
<Rule Id="C28133" Action="Error" />
|
||||
<Rule Id="C28134" Action="Error" />
|
||||
<Rule Id="C28135" Action="Error" />
|
||||
<Rule Id="C28137" Action="Error" />
|
||||
<Rule Id="C28138" Action="Error" />
|
||||
<Rule Id="C28141" Action="Error" />
|
||||
<Rule Id="C28143" Action="Error" />
|
||||
<Rule Id="C28144" Action="Error" />
|
||||
<Rule Id="C28145" Action="Error" />
|
||||
<Rule Id="C28146" Action="Error" />
|
||||
<Rule Id="C28147" Action="Error" />
|
||||
<Rule Id="C28150" Action="Error" />
|
||||
<Rule Id="C28151" Action="Error" />
|
||||
<Rule Id="C28152" Action="Error" />
|
||||
<Rule Id="C28153" Action="Error" />
|
||||
<Rule Id="C28156" Action="Error" />
|
||||
<Rule Id="C28157" Action="Error" />
|
||||
<Rule Id="C28158" Action="Error" />
|
||||
<Rule Id="C28159" Action="Error" />
|
||||
<Rule Id="C28160" Action="Error" />
|
||||
<Rule Id="C28161" Action="Error" />
|
||||
<Rule Id="C28162" Action="Error" />
|
||||
<Rule Id="C28163" Action="Error" />
|
||||
<Rule Id="C28164" Action="Error" />
|
||||
<Rule Id="C28165" Action="Error" />
|
||||
<Rule Id="C28166" Action="Error" />
|
||||
<Rule Id="C28167" Action="Error" />
|
||||
<Rule Id="C28168" Action="Error" />
|
||||
<Rule Id="C28169" Action="Error" />
|
||||
<Rule Id="C28170" Action="Error" />
|
||||
<Rule Id="C28171" Action="Error" />
|
||||
<Rule Id="C28172" Action="Error" />
|
||||
<Rule Id="C28173" Action="Error" />
|
||||
<Rule Id="C28175" Action="Error" />
|
||||
<Rule Id="C28176" Action="Error" />
|
||||
<Rule Id="C28182" Action="Error" />
|
||||
<Rule Id="C28183" Action="Error" />
|
||||
<Rule Id="C28193" Action="Error" />
|
||||
<Rule Id="C28194" Action="Error" />
|
||||
<Rule Id="C28195" Action="Error" />
|
||||
<Rule Id="C28196" Action="Error" />
|
||||
<Rule Id="C28197" Action="Error" />
|
||||
<Rule Id="C28198" Action="Error" />
|
||||
<Rule Id="C28199" Action="Error" />
|
||||
<Rule Id="C28202" Action="Error" />
|
||||
<Rule Id="C28203" Action="Error" />
|
||||
<Rule Id="C28204" Action="Error" />
|
||||
<Rule Id="C28205" Action="Error" />
|
||||
<Rule Id="C28206" Action="Error" />
|
||||
<Rule Id="C28207" Action="Error" />
|
||||
<Rule Id="C28208" Action="Error" />
|
||||
<Rule Id="C28209" Action="Error" />
|
||||
<Rule Id="C28210" Action="Error" />
|
||||
<Rule Id="C28211" Action="Error" />
|
||||
<Rule Id="C28212" Action="Error" />
|
||||
<Rule Id="C28213" Action="Error" />
|
||||
<Rule Id="C28214" Action="Error" />
|
||||
<Rule Id="C28215" Action="Error" />
|
||||
<Rule Id="C28216" Action="Error" />
|
||||
<Rule Id="C28217" Action="Error" />
|
||||
<Rule Id="C28218" Action="Error" />
|
||||
<Rule Id="C28219" Action="Error" />
|
||||
<Rule Id="C28220" Action="Error" />
|
||||
<Rule Id="C28221" Action="Error" />
|
||||
<Rule Id="C28222" Action="Error" />
|
||||
<Rule Id="C28223" Action="Error" />
|
||||
<Rule Id="C28224" Action="Error" />
|
||||
<Rule Id="C28225" Action="Error" />
|
||||
<Rule Id="C28226" Action="Error" />
|
||||
<Rule Id="C28227" Action="Error" />
|
||||
<Rule Id="C28228" Action="Error" />
|
||||
<Rule Id="C28229" Action="Error" />
|
||||
<Rule Id="C28230" Action="Error" />
|
||||
<Rule Id="C28231" Action="Error" />
|
||||
<Rule Id="C28232" Action="Error" />
|
||||
<Rule Id="C28233" Action="Error" />
|
||||
<Rule Id="C28234" Action="Error" />
|
||||
<Rule Id="C28235" Action="Error" />
|
||||
<Rule Id="C28236" Action="Error" />
|
||||
<Rule Id="C28237" Action="Error" />
|
||||
<Rule Id="C28238" Action="Error" />
|
||||
<Rule Id="C28239" Action="Error" />
|
||||
<Rule Id="C28240" Action="Error" />
|
||||
<Rule Id="C28241" Action="Error" />
|
||||
<Rule Id="C28243" Action="Error" />
|
||||
<Rule Id="C28244" Action="Error" />
|
||||
<Rule Id="C28245" Action="Error" />
|
||||
<Rule Id="C28246" Action="Error" />
|
||||
<Rule Id="C28250" Action="Error" />
|
||||
<Rule Id="C28251" Action="Error" />
|
||||
<Rule Id="C28252" Action="Error" />
|
||||
<Rule Id="C28253" Action="Error" />
|
||||
<Rule Id="C28254" Action="Error" />
|
||||
<Rule Id="C28260" Action="Error" />
|
||||
<Rule Id="C28262" Action="Error" />
|
||||
<Rule Id="C28263" Action="Error" />
|
||||
<Rule Id="C28266" Action="Error" />
|
||||
<Rule Id="C28267" Action="Error" />
|
||||
<Rule Id="C28272" Action="Error" />
|
||||
<Rule Id="C28273" Action="Error" />
|
||||
<Rule Id="C28275" Action="Error" />
|
||||
<Rule Id="C28278" Action="Error" />
|
||||
<Rule Id="C28279" Action="Error" />
|
||||
<Rule Id="C28280" Action="Error" />
|
||||
<Rule Id="C28282" Action="Error" />
|
||||
<Rule Id="C28283" Action="Error" />
|
||||
<Rule Id="C28284" Action="Error" />
|
||||
<Rule Id="C28285" Action="Error" />
|
||||
<Rule Id="C28286" Action="Error" />
|
||||
<Rule Id="C28287" Action="Error" />
|
||||
<Rule Id="C28288" Action="Error" />
|
||||
<Rule Id="C28289" Action="Error" />
|
||||
<Rule Id="C28290" Action="Error" />
|
||||
<Rule Id="C28291" Action="Error" />
|
||||
<Rule Id="C28300" Action="Error" />
|
||||
<Rule Id="C28301" Action="Error" />
|
||||
<Rule Id="C28302" Action="Error" />
|
||||
<Rule Id="C28303" Action="Error" />
|
||||
<Rule Id="C28304" Action="Error" />
|
||||
<Rule Id="C28305" Action="Error" />
|
||||
<Rule Id="C28306" Action="Error" />
|
||||
<Rule Id="C28307" Action="Error" />
|
||||
<Rule Id="C28308" Action="Error" />
|
||||
<Rule Id="C28309" Action="Error" />
|
||||
<Rule Id="C28350" Action="Error" />
|
||||
<Rule Id="C28351" Action="Error" />
|
||||
<Rule Id="C28601" Action="Error" />
|
||||
<Rule Id="C28602" Action="Error" />
|
||||
<Rule Id="C28604" Action="Error" />
|
||||
<Rule Id="C28615" Action="Error" />
|
||||
<Rule Id="C28616" Action="Error" />
|
||||
<Rule Id="C28617" Action="Error" />
|
||||
<Rule Id="C28623" Action="Error" />
|
||||
<Rule Id="C28624" Action="Error" />
|
||||
<Rule Id="C28625" Action="Error" />
|
||||
<Rule Id="C28636" Action="Error" />
|
||||
<Rule Id="C28637" Action="Error" />
|
||||
<Rule Id="C28638" Action="Error" />
|
||||
<Rule Id="C28639" Action="Error" />
|
||||
<Rule Id="C28640" Action="Error" />
|
||||
<Rule Id="C28645" Action="Error" />
|
||||
<Rule Id="C28648" Action="Error" />
|
||||
<Rule Id="C28649" Action="Error" />
|
||||
<Rule Id="C28650" Action="Error" />
|
||||
<Rule Id="C28714" Action="Error" />
|
||||
<Rule Id="C28715" Action="Error" />
|
||||
<Rule Id="C28716" Action="Error" />
|
||||
<Rule Id="C28717" Action="Error" />
|
||||
<Rule Id="C28719" Action="Error" />
|
||||
<Rule Id="C28720" Action="Error" />
|
||||
<Rule Id="C28721" Action="Error" />
|
||||
<Rule Id="C28726" Action="Error" />
|
||||
<Rule Id="C28727" Action="Error" />
|
||||
<Rule Id="C28730" Action="Error" />
|
||||
<Rule Id="C28735" Action="Error" />
|
||||
<Rule Id="C28736" Action="Error" />
|
||||
<Rule Id="C28750" Action="Error" />
|
||||
<Rule Id="C28751" Action="Error" />
|
||||
<Rule Id="C6001" Action="Error" />
|
||||
<Rule Id="C6011" Action="Error" />
|
||||
<Rule Id="C6014" Action="Error" />
|
||||
<Rule Id="C6029" Action="Error" />
|
||||
<Rule Id="C6031" Action="Error" />
|
||||
<Rule Id="C6053" Action="Error" />
|
||||
<Rule Id="C6054" Action="Error" />
|
||||
<Rule Id="C6059" Action="Error" />
|
||||
<Rule Id="C6063" Action="Error" />
|
||||
<Rule Id="C6064" Action="Error" />
|
||||
<Rule Id="C6066" Action="Error" />
|
||||
<Rule Id="C6067" Action="Error" />
|
||||
<Rule Id="C6101" Action="Error" />
|
||||
<Rule Id="C6200" Action="Error" />
|
||||
<Rule Id="C6201" Action="Error" />
|
||||
<Rule Id="C6211" Action="Error" />
|
||||
<Rule Id="C6214" Action="Error" />
|
||||
<Rule Id="C6215" Action="Error" />
|
||||
<Rule Id="C6216" Action="Error" />
|
||||
<Rule Id="C6217" Action="Error" />
|
||||
<Rule Id="C6219" Action="Error" />
|
||||
<Rule Id="C6220" Action="Error" />
|
||||
<Rule Id="C6221" Action="Error" />
|
||||
<Rule Id="C6225" Action="Error" />
|
||||
<Rule Id="C6226" Action="Error" />
|
||||
<Rule Id="C6230" Action="Error" />
|
||||
<Rule Id="C6235" Action="Error" />
|
||||
<Rule Id="C6236" Action="Error" />
|
||||
<Rule Id="C6237" Action="Error" />
|
||||
<Rule Id="C6239" Action="Error" />
|
||||
<Rule Id="C6240" Action="Error" />
|
||||
<Rule Id="C6242" Action="Error" />
|
||||
<Rule Id="C6244" Action="Error" />
|
||||
<Rule Id="C6246" Action="Error" />
|
||||
<Rule Id="C6248" Action="Error" />
|
||||
<Rule Id="C6250" Action="Error" />
|
||||
<Rule Id="C6255" Action="Error" />
|
||||
<Rule Id="C6258" Action="Error" />
|
||||
<Rule Id="C6259" Action="Error" />
|
||||
<Rule Id="C6260" Action="Error" />
|
||||
<Rule Id="C6262" Action="Error" />
|
||||
<Rule Id="C6263" Action="Error" />
|
||||
<Rule Id="C6268" Action="Error" />
|
||||
<Rule Id="C6269" Action="Error" />
|
||||
<Rule Id="C6270" Action="Error" />
|
||||
<Rule Id="C6271" Action="Error" />
|
||||
<Rule Id="C6272" Action="Error" />
|
||||
<Rule Id="C6273" Action="Error" />
|
||||
<Rule Id="C6274" Action="Error" />
|
||||
<Rule Id="C6276" Action="Error" />
|
||||
<Rule Id="C6277" Action="Error" />
|
||||
<Rule Id="C6278" Action="Error" />
|
||||
<Rule Id="C6279" Action="Error" />
|
||||
<Rule Id="C6280" Action="Error" />
|
||||
<Rule Id="C6281" Action="Error" />
|
||||
<Rule Id="C6282" Action="Error" />
|
||||
<Rule Id="C6283" Action="Error" />
|
||||
<Rule Id="C6284" Action="Error" />
|
||||
<Rule Id="C6285" Action="Error" />
|
||||
<Rule Id="C6286" Action="Error" />
|
||||
<Rule Id="C6287" Action="Error" />
|
||||
<Rule Id="C6288" Action="Error" />
|
||||
<Rule Id="C6289" Action="Error" />
|
||||
<Rule Id="C6290" Action="Error" />
|
||||
<Rule Id="C6291" Action="Error" />
|
||||
<Rule Id="C6292" Action="Error" />
|
||||
<Rule Id="C6293" Action="Error" />
|
||||
<Rule Id="C6294" Action="Error" />
|
||||
<Rule Id="C6295" Action="Error" />
|
||||
<Rule Id="C6296" Action="Error" />
|
||||
<Rule Id="C6297" Action="Error" />
|
||||
<Rule Id="C6298" Action="Error" />
|
||||
<Rule Id="C6299" Action="Error" />
|
||||
<Rule Id="C6302" Action="Error" />
|
||||
<Rule Id="C6303" Action="Error" />
|
||||
<Rule Id="C6305" Action="Error" />
|
||||
<Rule Id="C6306" Action="Error" />
|
||||
<Rule Id="C6308" Action="Error" />
|
||||
<Rule Id="C6310" Action="Error" />
|
||||
<Rule Id="C6312" Action="Error" />
|
||||
<Rule Id="C6313" Action="Error" />
|
||||
<Rule Id="C6314" Action="Error" />
|
||||
<Rule Id="C6315" Action="Error" />
|
||||
<Rule Id="C6316" Action="Error" />
|
||||
<Rule Id="C6317" Action="Error" />
|
||||
<Rule Id="C6318" Action="Error" />
|
||||
<Rule Id="C6319" Action="Error" />
|
||||
<Rule Id="C6320" Action="Error" />
|
||||
<Rule Id="C6322" Action="Error" />
|
||||
<Rule Id="C6323" Action="Error" />
|
||||
<Rule Id="C6324" Action="Error" />
|
||||
<Rule Id="C6326" Action="Error" />
|
||||
<Rule Id="C6328" Action="Error" />
|
||||
<Rule Id="C6329" Action="Error" />
|
||||
<Rule Id="C6330" Action="Error" />
|
||||
<Rule Id="C6331" Action="Error" />
|
||||
<Rule Id="C6332" Action="Error" />
|
||||
<Rule Id="C6333" Action="Error" />
|
||||
<Rule Id="C6334" Action="Error" />
|
||||
<Rule Id="C6335" Action="Error" />
|
||||
<Rule Id="C6336" Action="Error" />
|
||||
<Rule Id="C6340" Action="Error" />
|
||||
<Rule Id="C6381" Action="Error" />
|
||||
<Rule Id="C6383" Action="Error" />
|
||||
<Rule Id="C6384" Action="Error" />
|
||||
<Rule Id="C6385" Action="Error" />
|
||||
<Rule Id="C6386" Action="Error" />
|
||||
<Rule Id="C6387" Action="Error" />
|
||||
<Rule Id="C6388" Action="Error" />
|
||||
<Rule Id="C6400" Action="Error" />
|
||||
<Rule Id="C6401" Action="Error" />
|
||||
<Rule Id="C6411" Action="Error" />
|
||||
<Rule Id="C6412" Action="Error" />
|
||||
<Rule Id="C6500" Action="Error" />
|
||||
<Rule Id="C6501" Action="Error" />
|
||||
<Rule Id="C6503" Action="Error" />
|
||||
<Rule Id="C6504" Action="Error" />
|
||||
<Rule Id="C6505" Action="Error" />
|
||||
<Rule Id="C6506" Action="Error" />
|
||||
<Rule Id="C6508" Action="Error" />
|
||||
<Rule Id="C6509" Action="Error" />
|
||||
<Rule Id="C6510" Action="Error" />
|
||||
<Rule Id="C6511" Action="Error" />
|
||||
<Rule Id="C6513" Action="Error" />
|
||||
<Rule Id="C6514" Action="Error" />
|
||||
<Rule Id="C6515" Action="Error" />
|
||||
<Rule Id="C6516" Action="Error" />
|
||||
<Rule Id="C6517" Action="Error" />
|
||||
<Rule Id="C6518" Action="Error" />
|
||||
<Rule Id="C6522" Action="Error" />
|
||||
<Rule Id="C6525" Action="Error" />
|
||||
<Rule Id="C6527" Action="Error" />
|
||||
<Rule Id="C6530" Action="Error" />
|
||||
<Rule Id="C6540" Action="Error" />
|
||||
<Rule Id="C6551" Action="Error" />
|
||||
<Rule Id="C6552" Action="Error" />
|
||||
<Rule Id="C6701" Action="Error" />
|
||||
<Rule Id="C6702" Action="Error" />
|
||||
<Rule Id="C6703" Action="Error" />
|
||||
<Rule Id="C6704" Action="Error" />
|
||||
<Rule Id="C6705" Action="Error" />
|
||||
<Rule Id="C6706" Action="Error" />
|
||||
<Rule Id="C6707" Action="Error" />
|
||||
<Rule Id="C6993" Action="Error" />
|
||||
<Rule Id="C6995" Action="Error" />
|
||||
<Rule Id="C6997" Action="Error" />
|
||||
</Rules>
|
||||
</RuleSet>
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
LONG ALLOC_CACHE_HANDLER::sm_nFillPattern = 0xACA50000;
|
||||
HANDLE ALLOC_CACHE_HANDLER::sm_hHeap;
|
||||
|
||||
|
|
@ -440,4 +443,6 @@ Finished:
|
|||
}
|
||||
|
||||
return fRet;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <crtdbg.h>
|
||||
#include <CodeAnalysis/Warnings.h>
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
//
|
||||
// BUFFER_T class shouldn't be used directly. Use BUFFER specialization class instead.
|
||||
|
|
@ -269,3 +272,5 @@ C_ASSERT( sizeof(VOID*) <= sizeof(ULONGLONG) );
|
|||
|
||||
#define INLINE_BUFFER_INIT( _name ) \
|
||||
_name( (BYTE*)__aqw##_name, sizeof( __aqw##_name ) )
|
||||
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -21,19 +21,21 @@
|
|||
// Debug error levels for DEBUG_FLAGS_VAR.
|
||||
//
|
||||
|
||||
#define DEBUG_FLAG_INFO 0x00000001
|
||||
#define DEBUG_FLAG_WARN 0x00000002
|
||||
#define DEBUG_FLAG_ERROR 0x00000004
|
||||
#define DEBUG_FLAG_TRACE 0x00000001
|
||||
#define DEBUG_FLAG_INFO 0x00000002
|
||||
#define DEBUG_FLAG_WARN 0x00000004
|
||||
#define DEBUG_FLAG_ERROR 0x00000008
|
||||
|
||||
//
|
||||
// Predefined error level values. These are backwards from the
|
||||
// windows definitions.
|
||||
//
|
||||
|
||||
#define DEBUG_FLAGS_TRACE (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO | DEBUG_FLAG_TRACE)
|
||||
#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO)
|
||||
#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN)
|
||||
#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR)
|
||||
#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
|
||||
#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR | DEBUG_FLAG_TRACE)
|
||||
|
||||
//
|
||||
// Global variables to control tracing. Generally per module
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include "stringu.h"
|
||||
#include "ntassert.h"
|
||||
#include <CodeAnalysis/Warnings.h>
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
/*++
|
||||
class MULTISZ:
|
||||
|
|
@ -221,5 +225,6 @@ SplitCommaDelimitedString(
|
|||
MULTISZ * pmszList
|
||||
);
|
||||
|
||||
#endif // !_MULTISZ_HXX_
|
||||
#pragma warning( pop )
|
||||
|
||||
#endif // !_MULTISZ_HXX_
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 26451 )
|
||||
|
||||
template<typename T>
|
||||
class PER_CPU
|
||||
{
|
||||
|
|
@ -302,4 +305,6 @@ Return:
|
|||
*pCacheLineSize = SYSTEM_CACHE_ALIGNMENT_SIZE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
#include "macros.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
class STRA
|
||||
{
|
||||
|
||||
|
|
@ -513,3 +517,5 @@ CHAR* InitHelper(__out CHAR (&psz)[size])
|
|||
STRA name;
|
||||
|
||||
#define INLINE_STRA_INIT(name) name(InitHelper(__ach##name), sizeof(__ach##name))
|
||||
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma warning (disable : 4267)
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : 4267 ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
STRU::STRU(
|
||||
VOID
|
||||
) : m_cchLen( 0 )
|
||||
|
|
@ -1199,25 +1201,17 @@ STRU::ExpandEnvironmentVariables(
|
|||
__out STRU * pstrExpandedString
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Expand the environment variables in a string
|
||||
|
||||
Arguments:
|
||||
|
||||
pszString - String with environment variables to expand
|
||||
pstrExpandedString - Receives expanded string on success
|
||||
|
||||
Return Value:
|
||||
|
||||
HRESULT
|
||||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD cchNewSize = 0;
|
||||
|
||||
if ( pszString == NULL ||
|
||||
pstrExpandedString == NULL )
|
||||
{
|
||||
|
|
@ -1225,7 +1219,6 @@ Return Value:
|
|||
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
cchNewSize = ExpandEnvironmentStrings( pszString,
|
||||
pstrExpandedString->QueryStr(),
|
||||
pstrExpandedString->QuerySizeCCH() );
|
||||
|
|
@ -1234,7 +1227,6 @@ Return Value:
|
|||
hr = HRESULT_FROM_WIN32( GetLastError() );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( cchNewSize > pstrExpandedString->QuerySizeCCH() )
|
||||
{
|
||||
hr = pstrExpandedString->Resize(
|
||||
|
|
@ -1244,13 +1236,11 @@ Return Value:
|
|||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
cchNewSize = ExpandEnvironmentStrings(
|
||||
pszString,
|
||||
pstrExpandedString->QueryStr(),
|
||||
pstrExpandedString->QuerySizeCCH()
|
||||
);
|
||||
|
||||
if ( cchNewSize == 0 ||
|
||||
cchNewSize > pstrExpandedString->QuerySizeCCH() )
|
||||
{
|
||||
|
|
@ -1258,14 +1248,10 @@ Return Value:
|
|||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
pstrExpandedString->SyncWithBuffer();
|
||||
|
||||
hr = S_OK;
|
||||
|
||||
Exit:
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
#pragma warning(default:4267)
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "buffer.h"
|
||||
#include <CodeAnalysis/Warnings.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS )
|
||||
|
||||
class STRU
|
||||
{
|
||||
|
||||
|
|
@ -349,13 +353,12 @@ public:
|
|||
__in PCWSTR pwszFormatString,
|
||||
va_list argsList
|
||||
);
|
||||
|
||||
|
||||
static
|
||||
HRESULT ExpandEnvironmentVariables(
|
||||
__in PCWSTR pszString,
|
||||
__out STRU * pstrExpandedString
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
|
|
@ -425,3 +428,4 @@ MakePathCanonicalizationProof(
|
|||
IN PCWSTR pszName,
|
||||
OUT STRU * pstrPath
|
||||
);
|
||||
#pragma warning( pop )
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include "InProcessApplicationBase.h"
|
||||
|
||||
hostfxr_main_fn InProcessApplicationBase::s_fMainCallback = NULL;
|
||||
|
||||
InProcessApplicationBase::InProcessApplicationBase(
|
||||
IHttpServer& pHttpServer,
|
||||
IHttpApplication& pHttpApplication)
|
||||
|
|
@ -35,7 +33,21 @@ InProcessApplicationBase::StopInternal(bool fServerInitiated)
|
|||
}
|
||||
else
|
||||
{
|
||||
exit(0);
|
||||
// Send WM_QUIT to the main window to initiate graceful shutdown
|
||||
EnumWindows([](HWND hwnd, LPARAM) -> BOOL
|
||||
{
|
||||
DWORD processId;
|
||||
|
||||
if (GetWindowThreadProcessId(hwnd, &processId) &&
|
||||
processId == GetCurrentProcessId() &&
|
||||
GetConsoleWindow() != hwnd)
|
||||
{
|
||||
PostMessage(hwnd, WM_QUIT, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "application.h"
|
||||
#include "AppOfflineTrackingApplication.h"
|
||||
|
||||
typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]); // TODO these may need to be BSTRs
|
||||
|
|
@ -23,8 +22,5 @@ public:
|
|||
protected:
|
||||
BOOL m_fRecycleCalled;
|
||||
IHttpServer& m_pHttpServer;
|
||||
// Allows to override call to hostfxr_main with custome callback
|
||||
// used in testing
|
||||
static hostfxr_main_fn s_fMainCallback;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,41 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "InProcessOptions.h"
|
||||
#include "InvalidOperationException.h"
|
||||
#include "EventLog.h"
|
||||
|
||||
HRESULT InProcessOptions::Create(
|
||||
IHttpServer& pServer,
|
||||
IHttpApplication& pHttpApplication,
|
||||
std::unique_ptr<InProcessOptions>& options)
|
||||
{
|
||||
try
|
||||
{
|
||||
const WebConfigConfigurationSource configurationSource(pServer.GetAdminManager(), pHttpApplication);
|
||||
options = std::make_unique<InProcessOptions>(configurationSource);
|
||||
}
|
||||
catch (InvalidOperationException& ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR,
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR_MSG,
|
||||
ex.as_wstring().c_str());
|
||||
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR,
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR_MSG,
|
||||
GetUnexpectedExceptionMessage(ex).c_str());
|
||||
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSource) :
|
||||
m_fStdoutLogEnabled(false),
|
||||
|
|
@ -18,6 +53,8 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
|
|||
m_struStdoutLogFile = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
|
||||
m_fDisableStartUpErrorPage = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE);
|
||||
m_environmentVariables = aspNetCoreSection->GetKeyValuePairs(CS_ASPNETCORE_ENVIRONMENT_VARIABLES);
|
||||
m_dwStartupTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT) * 1000;
|
||||
m_dwShutdownTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT) * 1000;
|
||||
|
||||
const auto basicAuthSection = configurationSource.GetSection(CS_BASIC_AUTHENTICATION_SECTION);
|
||||
m_fBasicAuthEnabled = basicAuthSection && basicAuthSection->GetBool(CS_ENABLED).value_or(false);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <string>
|
||||
#include "ConfigurationSource.h"
|
||||
#include "WebConfigConfigurationSource.h"
|
||||
|
||||
class InProcessOptions: NonCopyable
|
||||
{
|
||||
|
|
@ -60,12 +61,22 @@ public:
|
|||
DWORD
|
||||
QueryStartupTimeLimitInMS() const
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return INFINITE;
|
||||
}
|
||||
|
||||
return m_dwStartupTimeLimitInMS;
|
||||
}
|
||||
|
||||
DWORD
|
||||
QueryShutdownTimeLimitInMS() const
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return INFINITE;
|
||||
}
|
||||
|
||||
return m_dwShutdownTimeLimitInMS;
|
||||
}
|
||||
|
||||
|
|
@ -76,6 +87,12 @@ public:
|
|||
}
|
||||
|
||||
InProcessOptions(const ConfigurationSource &configurationSource);
|
||||
|
||||
static
|
||||
HRESULT InProcessOptions::Create(
|
||||
IHttpServer& pServer,
|
||||
IHttpApplication& pHttpApplication,
|
||||
std::unique_ptr<InProcessOptions>& options);
|
||||
|
||||
private:
|
||||
std::wstring m_strArguments;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
HRESULT StartupExceptionApplication::CreateHandler(IHttpContext *pHttpContext, IREQUEST_HANDLER ** pRequestHandler)
|
||||
{
|
||||
*pRequestHandler = new StartupExceptionHandler(pHttpContext, m_disableLogs, this);
|
||||
*pRequestHandler = new StartupExceptionHandler(pHttpContext, m_disableLogs);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,29 +16,6 @@ public:
|
|||
: m_disableLogs(disableLogs),
|
||||
InProcessApplicationBase(pServer, pApplication)
|
||||
{
|
||||
html500Page = std::string("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> \
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\"> \
|
||||
<head> \
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" /> \
|
||||
<title> IIS 500.30 Error </title><style type=\"text/css\"></style></head> \
|
||||
<body> <div id = \"content\"> \
|
||||
<div class = \"content-container\"><h3> HTTP Error 500.30 - ANCM In-Process Start Failure </h3></div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset> <h4> Common causes of this issue: </h4> \
|
||||
<ul><li> The application failed to start </li> \
|
||||
<li> The application started but then stopped </li> \
|
||||
<li> The application started but threw an exception during startup </li></ul></fieldset> \
|
||||
</div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset><h4> Troubleshooting steps: </h4> \
|
||||
<ul><li> Check the system event log for error messages </li> \
|
||||
<li> Enable logging the application process' stdout messages </li> \
|
||||
<li> Attach a debugger to the application process and inspect </li></ul></fieldset> \
|
||||
<fieldset><h4> For more information visit: \
|
||||
<a href=\"https://go.microsoft.com/fwlink/?LinkID=808681\"> <cite> https://go.microsoft.com/fwlink/?LinkID=808681 </cite></a></h4> \
|
||||
</fieldset> \
|
||||
</div> \
|
||||
</div></body></html>");
|
||||
}
|
||||
|
||||
~StartupExceptionApplication() = default;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,30 @@
|
|||
#include "StartupExceptionApplication.h"
|
||||
#include "StartupExceptionHandler.h"
|
||||
|
||||
std::string StartupExceptionHandler::s_html500Page = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> \
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\"> \
|
||||
<head> \
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" /> \
|
||||
<title> IIS 500.30 Error </title><style type=\"text/css\"></style></head> \
|
||||
<body> <div id = \"content\"> \
|
||||
<div class = \"content-container\"><h3> HTTP Error 500.30 - ANCM In-Process Start Failure </h3></div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset> <h4> Common causes of this issue: </h4> \
|
||||
<ul><li> The application failed to start </li> \
|
||||
<li> The application started but then stopped </li> \
|
||||
<li> The application started but threw an exception during startup </li></ul></fieldset> \
|
||||
</div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset><h4> Troubleshooting steps: </h4> \
|
||||
<ul><li> Check the system event log for error messages </li> \
|
||||
<li> Enable logging the application process' stdout messages </li> \
|
||||
<li> Attach a debugger to the application process and inspect </li></ul></fieldset> \
|
||||
<fieldset><h4> For more information visit: \
|
||||
<a href=\"https://go.microsoft.com/fwlink/?LinkID=808681\"> <cite> https://go.microsoft.com/fwlink/?LinkID=808681 </cite></a></h4> \
|
||||
</fieldset> \
|
||||
</div> \
|
||||
</div></body></html>";
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS StartupExceptionHandler::OnExecuteRequestHandler()
|
||||
{
|
||||
if (!m_disableLogs)
|
||||
|
|
@ -16,11 +40,9 @@ REQUEST_NOTIFICATION_STATUS StartupExceptionHandler::OnExecuteRequestHandler()
|
|||
(USHORT)strlen("text/html"),
|
||||
FALSE
|
||||
);
|
||||
const std::string& html500Page = m_pApplication->GetStaticHtml500Content();
|
||||
|
||||
DataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||
DataChunk.FromMemory.pBuffer = (PVOID)html500Page.c_str();
|
||||
DataChunk.FromMemory.BufferLength = (ULONG)html500Page.size();
|
||||
DataChunk.FromMemory.pBuffer = (PVOID)s_html500Page.c_str();
|
||||
DataChunk.FromMemory.BufferLength = (ULONG)s_html500Page.size();
|
||||
pResponse->WriteEntityChunkByReference(&DataChunk);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "requesthandler.h"
|
||||
|
||||
class StartupExceptionApplication;
|
||||
|
|
@ -10,19 +11,23 @@ class StartupExceptionApplication;
|
|||
class StartupExceptionHandler : public REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
StartupExceptionHandler(IHttpContext* pContext, BOOL disableLogs, StartupExceptionApplication* pApplication)
|
||||
StartupExceptionHandler(IHttpContext* pContext, BOOL disableLogs)
|
||||
:
|
||||
m_pContext(pContext),
|
||||
m_disableLogs(disableLogs),
|
||||
m_pApplication(pApplication)
|
||||
m_disableLogs(disableLogs)
|
||||
{
|
||||
}
|
||||
|
||||
~StartupExceptionHandler()
|
||||
{
|
||||
|
||||
}
|
||||
REQUEST_NOTIFICATION_STATUS OnExecuteRequestHandler() override;
|
||||
|
||||
private:
|
||||
IHttpContext * m_pContext;
|
||||
BOOL m_disableLogs;
|
||||
StartupExceptionApplication* m_pApplication;
|
||||
|
||||
static
|
||||
std::string s_html500Page;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -110,39 +110,25 @@ CreateApplication(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
const WebConfigConfigurationSource configurationSource(pServer->GetAdminManager(), *pHttpApplication);
|
||||
auto pConfig = std::make_unique<InProcessOptions>(configurationSource);
|
||||
|
||||
BOOL disableStartupPage = pConfig->QueryDisableStartUpErrorPage();
|
||||
|
||||
auto pApplication = std::make_unique<IN_PROCESS_APPLICATION>(*pServer, *pHttpApplication, std::move(pConfig), pParameters, nParameters);
|
||||
|
||||
// never create two inprocess applications in one process
|
||||
g_fInProcessApplicationCreated = true;
|
||||
if (FAILED_LOG(pApplication->LoadManagedApplication()))
|
||||
|
||||
std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER> inProcessApplication;
|
||||
if (!FAILED_LOG(IN_PROCESS_APPLICATION::Start(*pServer, *pHttpApplication, pParameters, nParameters, inProcessApplication)))
|
||||
{
|
||||
*ppApplication = inProcessApplication.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<InProcessOptions> options;
|
||||
THROW_IF_FAILED(InProcessOptions::Create(*pServer, *pHttpApplication, options));
|
||||
// Set the currently running application to a fake application that returns startup exceptions.
|
||||
auto pErrorApplication = std::make_unique<StartupExceptionApplication>(*pServer, *pHttpApplication, disableStartupPage);
|
||||
auto pErrorApplication = std::make_unique<StartupExceptionApplication>(*pServer, *pHttpApplication, options->QueryDisableStartUpErrorPage());
|
||||
|
||||
RETURN_IF_FAILED(pErrorApplication->StartMonitoringAppOffline());
|
||||
*ppApplication = pErrorApplication.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_IF_FAILED(pApplication->StartMonitoringAppOffline());
|
||||
*ppApplication = pApplication.release();
|
||||
}
|
||||
}
|
||||
catch(ConfigurationLoadException &ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR,
|
||||
ASPNETCORE_CONFIGURATION_LOAD_ERROR_MSG,
|
||||
ex.get_message().c_str());
|
||||
|
||||
RETURN_HR(E_FAIL);
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,11 @@
|
|||
#include "hostfxroptions.h"
|
||||
#include "requesthandler_config.h"
|
||||
#include "environmentvariablehelpers.h"
|
||||
#include "SRWExclusiveLock.h"
|
||||
#include "exceptions.h"
|
||||
#include "LoggingHelpers.h"
|
||||
#include "resources.h"
|
||||
#include "EventLog.h"
|
||||
|
||||
const LPCSTR IN_PROCESS_APPLICATION::s_exeLocationParameterName = "InProcessExeLocation";
|
||||
#include "ModuleHelpers.h"
|
||||
|
||||
IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
|
||||
|
||||
|
|
@ -23,10 +21,9 @@ IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
|||
APPLICATION_PARAMETER *pParameters,
|
||||
DWORD nParameters) :
|
||||
InProcessApplicationBase(pHttpServer, pApplication),
|
||||
m_ProcessExitCode(0),
|
||||
m_fBlockCallbacksIntoManaged(FALSE),
|
||||
m_fShutdownCalledFromNative(FALSE),
|
||||
m_fShutdownCalledFromManaged(FALSE),
|
||||
m_Initialized(false),
|
||||
m_blockManagedCallbacks(true),
|
||||
m_waitForShutdown(true),
|
||||
m_pConfig(std::move(pConfig))
|
||||
{
|
||||
DBG_ASSERT(m_pConfig);
|
||||
|
|
@ -35,161 +32,54 @@ IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
|||
{
|
||||
if (_stricmp(pParameters[i].pzName, s_exeLocationParameterName) == 0)
|
||||
{
|
||||
m_struExeLocation.Copy(reinterpret_cast<PCWSTR>(pParameters[i].pValue));
|
||||
m_dotnetExeKnownLocation = reinterpret_cast<PCWSTR>(pParameters[i].pValue);
|
||||
}
|
||||
}
|
||||
|
||||
m_status = MANAGED_APPLICATION_STATUS::STARTING;
|
||||
}
|
||||
|
||||
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||
{
|
||||
s_Application = NULL;
|
||||
s_Application = nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
DWORD WINAPI
|
||||
IN_PROCESS_APPLICATION::DoShutDown(
|
||||
LPVOID lpParam
|
||||
)
|
||||
{
|
||||
IN_PROCESS_APPLICATION* pApplication = static_cast<IN_PROCESS_APPLICATION*>(lpParam);
|
||||
DBG_ASSERT(pApplication);
|
||||
pApplication->ShutDownInternal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
__override
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::StopInternal(bool fServerInitiated)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(fServerInitiated);
|
||||
HRESULT hr = S_OK;
|
||||
CHandle hThread;
|
||||
DWORD dwThreadStatus = 0;
|
||||
|
||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
dwTimeout = INFINITE;
|
||||
}
|
||||
|
||||
hThread.Attach(CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE)DoShutDown,
|
||||
this, // thread function arguments
|
||||
0, // default creation flags
|
||||
NULL)); // receive thread identifier
|
||||
|
||||
if ((HANDLE)hThread == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(hThread, dwTimeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// Calling back into managed at this point is prone to have AVs
|
||||
// Calling terminate thread here may be our best solution.
|
||||
TerminateThread(hThread, STATUS_CONTROL_C_EXIT);
|
||||
hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
EventLog::Warn(
|
||||
ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE,
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG,
|
||||
QueryConfigPath().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
EventLog::Info(
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL,
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL_MSG,
|
||||
QueryConfigPath().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
StopClr();
|
||||
InProcessApplicationBase::StopInternal(fServerInitiated);
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ShutDownInternal()
|
||||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||
IN_PROCESS_APPLICATION::StopClr()
|
||||
{
|
||||
LOG_INFO(L"Stopping CLR");
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
if (!m_blockManagedCallbacks)
|
||||
{
|
||||
dwTimeout = INFINITE;
|
||||
}
|
||||
// We cannot call into managed if the dll is detaching from the process.
|
||||
// Calling into managed code when the dll is detaching is strictly a bad idea,
|
||||
// and usually results in an AV saying "The string binding is invalid"
|
||||
const auto shutdownHandler = m_ShutdownHandler;
|
||||
|
||||
if (m_fShutdownCalledFromNative ||
|
||||
m_status == MANAGED_APPLICATION_STATUS::STARTING ||
|
||||
m_status == MANAGED_APPLICATION_STATUS::FAIL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
if (m_fShutdownCalledFromNative ||
|
||||
m_status == MANAGED_APPLICATION_STATUS::STARTING ||
|
||||
m_status == MANAGED_APPLICATION_STATUS::FAIL)
|
||||
if (!g_fProcessDetach && shutdownHandler != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to keep track of when both managed and native initiate shutdown
|
||||
// to avoid AVs. If shutdown has already been initiated in managed, we don't want to call into
|
||||
// managed. We still need to wait on main exiting no matter what. m_fShutdownCalledFromNative
|
||||
// is used for detecting redundant calls and blocking more requests to OnExecuteRequestHandler.
|
||||
m_fShutdownCalledFromNative = TRUE;
|
||||
m_status = MANAGED_APPLICATION_STATUS::SHUTDOWN;
|
||||
|
||||
if (!m_fShutdownCalledFromManaged)
|
||||
{
|
||||
// We cannot call into managed if the dll is detaching from the process.
|
||||
// Calling into managed code when the dll is detaching is strictly a bad idea,
|
||||
// and usually results in an AV saying "The string binding is invalid"
|
||||
if (!g_fProcessDetach)
|
||||
{
|
||||
m_ShutdownHandler(m_ShutdownHandlerContext);
|
||||
m_ShutdownHandler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Release the lock before we wait on the thread to exit.
|
||||
}
|
||||
|
||||
if (!m_fShutdownCalledFromManaged)
|
||||
{
|
||||
if (m_hThread != NULL &&
|
||||
GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 &&
|
||||
dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// wait for graceful shutdown, i.e., the exit of the background thread or timeout
|
||||
if (WaitForSingleObject(m_hThread, dwTimeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// Calling back into managed at this point is prone to have AVs
|
||||
// Calling terminate thread here may be our best solution.
|
||||
TerminateThread(m_hThread, STATUS_CONTROL_C_EXIT);
|
||||
}
|
||||
}
|
||||
shutdownHandler(m_ShutdownHandlerContext);
|
||||
}
|
||||
}
|
||||
|
||||
s_Application = NULL;
|
||||
// Signal shutdown
|
||||
if (m_pShutdownEvent != nullptr)
|
||||
{
|
||||
LOG_IF_FAILED(SetEvent(m_pShutdownEvent));
|
||||
}
|
||||
|
||||
if (m_workerThread.joinable())
|
||||
{
|
||||
// Worker thread would wait for clr to finish and log error if required
|
||||
m_workerThread.join();
|
||||
}
|
||||
|
||||
s_Application = nullptr;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
@ -201,169 +91,320 @@ IN_PROCESS_APPLICATION::SetCallbackHandles(
|
|||
_In_ VOID* pvShutdownHandlerContext
|
||||
)
|
||||
{
|
||||
LOG_INFO(L"In-process callbacks set");
|
||||
|
||||
m_RequestHandler = request_handler;
|
||||
m_RequestHandlerContext = pvRequstHandlerContext;
|
||||
m_ShutdownHandler = shutdown_handler;
|
||||
m_ShutdownHandlerContext = pvShutdownHandlerContext;
|
||||
m_AsyncCompletionHandler = async_completion_handler;
|
||||
|
||||
m_blockManagedCallbacks = false;
|
||||
m_Initialized = true;
|
||||
|
||||
// Can't check the std err handle as it isn't a critical error
|
||||
// Initialization complete
|
||||
EventLog::Info(
|
||||
ASPNETCORE_EVENT_INPROCESS_START_SUCCESS,
|
||||
ASPNETCORE_EVENT_INPROCESS_START_SUCCESS_MSG,
|
||||
QueryApplicationPhysicalPath().c_str());
|
||||
SetEvent(m_pInitalizeEvent);
|
||||
m_fInitialized = TRUE;
|
||||
|
||||
SetEvent(m_pInitializeEvent);
|
||||
}
|
||||
|
||||
// Will be called by the inprocesshandler
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::LoadManagedApplication
|
||||
(
|
||||
VOID
|
||||
)
|
||||
IN_PROCESS_APPLICATION::LoadManagedApplication()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD dwTimeout;
|
||||
DWORD dwResult;
|
||||
THROW_LAST_ERROR_IF_NULL(m_pInitializeEvent = CreateEvent(
|
||||
nullptr, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not set
|
||||
nullptr)); // name
|
||||
|
||||
ReferenceApplication();
|
||||
THROW_LAST_ERROR_IF_NULL(m_pShutdownEvent = CreateEvent(
|
||||
nullptr, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not set
|
||||
nullptr)); // name
|
||||
|
||||
if (m_status != MANAGED_APPLICATION_STATUS::STARTING)
|
||||
m_workerThread = std::thread([](std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER> application)
|
||||
{
|
||||
// Core CLR has already been loaded.
|
||||
// Cannot load more than once even there was a failure
|
||||
if (m_status == MANAGED_APPLICATION_STATUS::FAIL)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
}
|
||||
else if (m_status == MANAGED_APPLICATION_STATUS::SHUTDOWN)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IS_SCHEDULED);
|
||||
}
|
||||
LOG_INFO(L"Starting in-process worker thread");
|
||||
application->ExecuteApplication();
|
||||
LOG_INFO(L"Stopping in-process worker thread");
|
||||
}, ::ReferenceApplication(this));
|
||||
|
||||
goto Finished;
|
||||
LOG_INFO(L"Waiting for initialization");
|
||||
|
||||
const HANDLE waitHandles[2] = { m_pInitializeEvent, m_workerThread.native_handle() };
|
||||
|
||||
// Wait for shutdown request
|
||||
const auto waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, m_pConfig->QueryStartupTimeLimitInMS());
|
||||
THROW_LAST_ERROR_IF(waitResult == WAIT_FAILED);
|
||||
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
// If server wasn't initialized in time shut application down without waiting for CLR thread to exit
|
||||
m_waitForShutdown = false;
|
||||
StopClr();
|
||||
throw InvalidOperationException(format(L"Managed server didn't initialize after %u ms.", m_pConfig->QueryStartupTimeLimitInMS()));
|
||||
}
|
||||
|
||||
// WAIT_OBJECT_0 + 1 is the worker thead handle
|
||||
if (waitResult == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
SRWExclusiveLock lock(m_stateLock);
|
||||
// Worker thread exited stop
|
||||
StopClr();
|
||||
throw InvalidOperationException(format(L"CLR worker thread exited prematurely"));
|
||||
}
|
||||
|
||||
if (m_status != MANAGED_APPLICATION_STATUS::STARTING)
|
||||
THROW_IF_FAILED(StartMonitoringAppOffline());
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IN_PROCESS_APPLICATION::ExecuteApplication()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::unique_ptr<HOSTFXR_OPTIONS> hostFxrOptions;
|
||||
|
||||
auto context = std::make_shared<ExecuteClrContext>();
|
||||
|
||||
auto pProc = s_fMainCallback;
|
||||
if (pProc == nullptr)
|
||||
{
|
||||
if (m_status == MANAGED_APPLICATION_STATUS::FAIL)
|
||||
HMODULE hModule;
|
||||
// hostfxr should already be loaded by the shim. If not, then we will need
|
||||
// to load it ourselves by finding hostfxr again.
|
||||
THROW_LAST_ERROR_IF_NULL(hModule = GetModuleHandle(L"hostfxr.dll"));
|
||||
|
||||
// Get the entry point for main
|
||||
pProc = reinterpret_cast<hostfxr_main_fn>(GetProcAddress(hModule, "hostfxr_main"));
|
||||
THROW_LAST_ERROR_IF_NULL(pProc);
|
||||
|
||||
THROW_IF_FAILED(HOSTFXR_OPTIONS::Create(
|
||||
m_dotnetExeKnownLocation,
|
||||
m_pConfig->QueryProcessPath(),
|
||||
QueryApplicationPhysicalPath(),
|
||||
m_pConfig->QueryArguments(),
|
||||
hostFxrOptions
|
||||
));
|
||||
|
||||
hostFxrOptions->GetArguments(context->m_argc, context->m_argv);
|
||||
THROW_IF_FAILED(SetEnvironmentVariablesOnWorkerProcess());
|
||||
}
|
||||
context->m_pProc = pProc;
|
||||
|
||||
if (m_pLoggerProvider == nullptr)
|
||||
{
|
||||
THROW_IF_FAILED(LoggingHelpers::CreateLoggingProvider(
|
||||
m_pConfig->QueryStdoutLogEnabled(),
|
||||
!m_pHttpServer.IsCommandLineLaunch(),
|
||||
m_pConfig->QueryStdoutLogFile().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
m_pLoggerProvider));
|
||||
|
||||
LOG_IF_FAILED(m_pLoggerProvider->Start());
|
||||
}
|
||||
|
||||
// There can only ever be a single instance of .NET Core
|
||||
// loaded in the process but we need to get config information to boot it up in the
|
||||
// first place. This is happening in an execute request handler and everyone waits
|
||||
// until this initialization is done.
|
||||
// We set a static so that managed code can call back into this instance and
|
||||
// set the callbacks
|
||||
s_Application = this;
|
||||
|
||||
//Start CLR thread
|
||||
m_clrThread = std::thread(ClrThreadEntryPoint, context);
|
||||
|
||||
// Wait for thread exit or shutdown event
|
||||
const HANDLE waitHandles[2] = { m_pShutdownEvent, m_clrThread.native_handle() };
|
||||
|
||||
// Wait for shutdown request
|
||||
const auto waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
|
||||
THROW_LAST_ERROR_IF(waitResult == WAIT_FAILED);
|
||||
|
||||
LOG_INFOF(L"Starting shutdown sequence %d", waitResult);
|
||||
|
||||
bool clrThreadExited = waitResult == (WAIT_OBJECT_0 + 1);
|
||||
// shutdown was signaled
|
||||
// only wait for shutdown in case of successful startup
|
||||
if (m_waitForShutdown)
|
||||
{
|
||||
const auto clrWaitResult = WaitForSingleObject(m_clrThread.native_handle(), m_pConfig->QueryShutdownTimeLimitInMS());
|
||||
THROW_LAST_ERROR_IF(waitResult == WAIT_FAILED);
|
||||
|
||||
clrThreadExited = clrWaitResult != WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
LOG_INFOF(L"Clr thread wait ended: clrThreadExited: %d", clrThreadExited);
|
||||
|
||||
// At this point CLR thread either finished or timed out, abandon it.
|
||||
m_clrThread.detach();
|
||||
|
||||
LOG_IF_FAILED(m_pLoggerProvider->Stop());
|
||||
|
||||
if (m_fStopCalled)
|
||||
{
|
||||
if (clrThreadExited)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
EventLog::Info(
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL,
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL_MSG,
|
||||
QueryConfigPath().c_str());
|
||||
}
|
||||
else if (m_status == MANAGED_APPLICATION_STATUS::SHUTDOWN)
|
||||
else
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IS_SCHEDULED);
|
||||
EventLog::Warn(
|
||||
ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE,
|
||||
ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG,
|
||||
QueryConfigPath().c_str());
|
||||
}
|
||||
|
||||
goto Finished;
|
||||
}
|
||||
m_hThread = CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE)ExecuteAspNetCoreProcess,
|
||||
this, // thread function arguments
|
||||
0, // default creation flags
|
||||
NULL); // receive thread identifier
|
||||
|
||||
if (m_hThread == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_pInitalizeEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not set
|
||||
NULL); // name
|
||||
|
||||
if (m_pInitalizeEvent == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// If the debugger is attached, never timeout
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
dwTimeout = INFINITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwTimeout = m_pConfig->QueryStartupTimeLimitInMS();
|
||||
if (clrThreadExited)
|
||||
{
|
||||
UnexpectedThreadExit(*context);
|
||||
// If the inprocess server was initialized, we need to cause recycle to be called on the worker process.
|
||||
// in case when it was not initialized we need to keep server running to serve 502 page
|
||||
if (m_Initialized)
|
||||
{
|
||||
QueueStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const HANDLE pHandles[2]{ m_hThread, m_pInitalizeEvent };
|
||||
|
||||
// Wait on either the thread to complete or the event to be set
|
||||
dwResult = WaitForMultipleObjects(2, pHandles, FALSE, dwTimeout);
|
||||
|
||||
// It all timed out
|
||||
if (dwResult == WAIT_TIMEOUT)
|
||||
{
|
||||
// kill the backend thread as loading dotnet timedout
|
||||
TerminateThread(m_hThread, 0);
|
||||
hr = HRESULT_FROM_WIN32(dwResult);
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwResult == WAIT_FAILED)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// The thread ended it means that something failed
|
||||
if (dwResult == WAIT_OBJECT_0)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_status = MANAGED_APPLICATION_STATUS::RUNNING_MANAGED;
|
||||
}
|
||||
Finished:
|
||||
|
||||
if (FAILED(hr))
|
||||
catch (InvalidOperationException& ex)
|
||||
{
|
||||
m_status = MANAGED_APPLICATION_STATUS::FAIL;
|
||||
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
hr);
|
||||
}
|
||||
DereferenceApplication();
|
||||
ex.as_wstring().c_str());
|
||||
|
||||
return hr;
|
||||
OBSERVE_CAUGHT_EXCEPTION();
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
GetUnexpectedExceptionMessage(ex).c_str());
|
||||
|
||||
OBSERVE_CAUGHT_EXCEPTION();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
)
|
||||
void IN_PROCESS_APPLICATION::QueueStop()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
IN_PROCESS_APPLICATION *pApplication = (IN_PROCESS_APPLICATION*)pContext;
|
||||
DBG_ASSERT(pApplication != NULL);
|
||||
hr = pApplication->ExecuteApplication();
|
||||
//
|
||||
// no need to log the error here as if error happened, the thread will exit
|
||||
// the error will ba catched by caller LoadManagedApplication which will log an error
|
||||
//
|
||||
if (m_fStopCalled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(L"Queueing in-process stop thread");
|
||||
|
||||
std::thread stoppingThread([](std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER> application)
|
||||
{
|
||||
LOG_INFO(L"Starting in-process stop thread");
|
||||
application->Stop(false);
|
||||
LOG_INFO(L"Stopping in-process stop thread");
|
||||
}, ::ReferenceApplication(this));
|
||||
|
||||
stoppingThread.detach();
|
||||
}
|
||||
|
||||
HRESULT IN_PROCESS_APPLICATION::Start(
|
||||
IHttpServer& pServer,
|
||||
IHttpApplication& pHttpApplication,
|
||||
APPLICATION_PARAMETER* pParameters,
|
||||
DWORD nParameters,
|
||||
std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER>& application)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::unique_ptr<InProcessOptions> options;
|
||||
THROW_IF_FAILED(InProcessOptions::Create(pServer, pHttpApplication, options));
|
||||
application = std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER>(
|
||||
new IN_PROCESS_APPLICATION(pServer, pHttpApplication, std::move(options), pParameters, nParameters));
|
||||
THROW_IF_FAILED(application->LoadManagedApplication());
|
||||
return S_OK;
|
||||
}
|
||||
catch (InvalidOperationException& ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
pHttpApplication.GetApplicationId(),
|
||||
pHttpApplication.GetApplicationPhysicalPath(),
|
||||
ex.as_wstring().c_str());
|
||||
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
pHttpApplication.GetApplicationId(),
|
||||
pHttpApplication.GetApplicationPhysicalPath(),
|
||||
GetUnexpectedExceptionMessage(ex).c_str());
|
||||
|
||||
RETURN_CAUGHT_EXCEPTION();
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
|
||||
// Required because __try and objects with destructors can not be mixed
|
||||
void
|
||||
IN_PROCESS_APPLICATION::ExecuteClr(const std::shared_ptr<ExecuteClrContext>& context)
|
||||
{
|
||||
__try
|
||||
{
|
||||
auto const exitCode = context->m_pProc(context->m_argc, context->m_argv.get());
|
||||
|
||||
LOG_INFOF(L"Managed application exited with code %d", exitCode);
|
||||
|
||||
context->m_exitCode = exitCode;
|
||||
}
|
||||
__except(GetExceptionCode() != 0)
|
||||
{
|
||||
LOG_INFOF(L"Managed threw an exception %d", GetExceptionCode());
|
||||
|
||||
context->m_exceptionCode = GetExceptionCode();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calls hostfxr_main with the hostfxr and application as arguments.
|
||||
// This method should not access IN_PROCESS_APPLICATION instance as it may be already freed
|
||||
// in case of startup timeout
|
||||
//
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ClrThreadEntryPoint(const std::shared_ptr<ExecuteClrContext> &context)
|
||||
{
|
||||
LOG_INFO(L"Starting CLR thread");
|
||||
|
||||
// Keep aspnetcorev2_inprocess.dll loaded while this thread is running
|
||||
// this is required because thread might be abandoned
|
||||
HandleWrapper<ModuleHandleTraits> moduleHandle;
|
||||
ModuleHelpers::IncrementCurrentModuleRefCount(moduleHandle);
|
||||
|
||||
ExecuteClr(context);
|
||||
|
||||
FreeLibraryAndExitThread(moduleHandle.release(), 0);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::SetEnvironementVariablesOnWorkerProcess(
|
||||
VOID
|
||||
)
|
||||
IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess()
|
||||
{
|
||||
auto variables = m_pConfig->QueryEnvironmentVariables();
|
||||
auto inputTable = std::unique_ptr<ENVIRONMENT_VAR_HASH, ENVIRONMENT_VAR_HASH_DELETER>(new ENVIRONMENT_VAR_HASH());
|
||||
|
|
@ -397,128 +438,53 @@ IN_PROCESS_APPLICATION::SetEnvironementVariablesOnWorkerProcess(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::ExecuteApplication(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
HMODULE hModule = nullptr;
|
||||
hostfxr_main_fn pProc;
|
||||
std::unique_ptr<HOSTFXR_OPTIONS> hostFxrOptions = NULL;
|
||||
DWORD hostfxrArgc = 0;
|
||||
std::unique_ptr<PCWSTR[]> hostfxrArgv;
|
||||
DBG_ASSERT(m_status == MANAGED_APPLICATION_STATUS::STARTING);
|
||||
|
||||
pProc = s_fMainCallback;
|
||||
if (pProc == nullptr)
|
||||
{
|
||||
// hostfxr should already be loaded by the shim. If not, then we will need
|
||||
// to load it ourselves by finding hostfxr again.
|
||||
hModule = LoadLibraryW(L"hostfxr.dll");
|
||||
|
||||
if (hModule == NULL)
|
||||
{
|
||||
// .NET Core not installed (we can log a more detailed error message here)
|
||||
hr = LOG_IF_FAILED(ERROR_BAD_ENVIRONMENT);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Get the entry point for main
|
||||
pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main");
|
||||
if (pProc == NULL)
|
||||
{
|
||||
hr = LOG_IF_FAILED(ERROR_BAD_ENVIRONMENT);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
FINISHED_IF_FAILED(hr = HOSTFXR_OPTIONS::Create(
|
||||
m_struExeLocation.QueryStr(),
|
||||
m_pConfig->QueryProcessPath().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
m_pConfig->QueryArguments().c_str(),
|
||||
hostFxrOptions
|
||||
));
|
||||
hostFxrOptions->GetArguments(hostfxrArgc, hostfxrArgv);
|
||||
FINISHED_IF_FAILED(SetEnvironementVariablesOnWorkerProcess());
|
||||
}
|
||||
|
||||
LOG_INFO(L"Starting managed application");
|
||||
|
||||
if (m_pLoggerProvider == NULL)
|
||||
{
|
||||
FINISHED_IF_FAILED(hr = LoggingHelpers::CreateLoggingProvider(
|
||||
m_pConfig->QueryStdoutLogEnabled(),
|
||||
!m_pHttpServer.IsCommandLineLaunch(),
|
||||
m_pConfig->QueryStdoutLogFile().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
m_pLoggerProvider));
|
||||
|
||||
LOG_IF_FAILED(m_pLoggerProvider->Start());
|
||||
}
|
||||
|
||||
// There can only ever be a single instance of .NET Core
|
||||
// loaded in the process but we need to get config information to boot it up in the
|
||||
// first place. This is happening in an execute request handler and everyone waits
|
||||
// until this initialization is done.
|
||||
// We set a static so that managed code can call back into this instance and
|
||||
// set the callbacks
|
||||
s_Application = this;
|
||||
|
||||
hr = RunDotnetApplication(hostfxrArgc, hostfxrArgv.get(), pProc);
|
||||
|
||||
Finished:
|
||||
|
||||
//
|
||||
// this method is called by the background thread and should never exit unless shutdown
|
||||
// If main returned and shutdown was not called in managed, we want to block native from calling into
|
||||
// managed. To do this, we can say that shutdown was called from managed.
|
||||
// Don't bother locking here as there will always be a race between receiving a native shutdown
|
||||
// notification and unexpected managed exit.
|
||||
//
|
||||
m_status = MANAGED_APPLICATION_STATUS::SHUTDOWN;
|
||||
m_fShutdownCalledFromManaged = TRUE;
|
||||
|
||||
m_pLoggerProvider->Stop();
|
||||
|
||||
if (!m_fShutdownCalledFromNative)
|
||||
{
|
||||
LogErrorsOnMainExit(hr);
|
||||
if (m_fInitialized)
|
||||
{
|
||||
//
|
||||
// If the inprocess server was initialized, we need to cause recycle to be called on the worker process.
|
||||
//
|
||||
Stop(/*fServerInitiated*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
|
||||
HRESULT hr
|
||||
)
|
||||
IN_PROCESS_APPLICATION::UnexpectedThreadExit(const ExecuteClrContext& context) const
|
||||
{
|
||||
STRA straStdErrOutput;
|
||||
STRU struStdMsg;
|
||||
auto hasStdOut = m_pLoggerProvider->GetStdOutContent(&straStdErrOutput) &&
|
||||
SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()));
|
||||
|
||||
if (context.m_exceptionCode != 0)
|
||||
{
|
||||
if (hasStdOut)
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_STDOUT_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
context.m_exceptionCode,
|
||||
struStdMsg.QueryStr());
|
||||
}
|
||||
else
|
||||
{
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
context.m_exceptionCode
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Ungraceful shutdown, try to log an error message.
|
||||
// This will be a common place for errors as it means the hostfxr_main returned
|
||||
// or there was an exception.
|
||||
//
|
||||
STRA straStdErrOutput;
|
||||
STRU struStdMsg;
|
||||
if (m_pLoggerProvider->GetStdOutContent(&straStdErrOutput))
|
||||
if (hasStdOut)
|
||||
{
|
||||
if (SUCCEEDED(struStdMsg.CopyA(straStdErrOutput.QueryStr()))) {
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
hr,
|
||||
struStdMsg.QueryStr());
|
||||
}
|
||||
EventLog::Error(
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
context.m_exitCode,
|
||||
struStdMsg.QueryStr());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -527,53 +493,20 @@ IN_PROCESS_APPLICATION::LogErrorsOnMainExit(
|
|||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG,
|
||||
QueryApplicationId().c_str(),
|
||||
QueryApplicationPhysicalPath().c_str(),
|
||||
hr);
|
||||
context.m_exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Calls hostfxr_main with the hostfxr and application as arguments.
|
||||
//
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hostfxr_main_fn pProc)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
__try
|
||||
{
|
||||
m_ProcessExitCode = pProc(argc, argv);
|
||||
if (m_ProcessExitCode != 0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
LOG_INFOF(L"Managed application exited with code %d", m_ProcessExitCode);
|
||||
}
|
||||
__except(GetExceptionCode() != 0)
|
||||
{
|
||||
|
||||
LOG_INFOF(L"Managed threw an exception %d", GetExceptionCode());
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::CreateHandler(
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ IREQUEST_HANDLER **pRequestHandler)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
IREQUEST_HANDLER* pHandler = NULL;
|
||||
|
||||
pHandler = new IN_PROCESS_HANDLER(::ReferenceApplication(this), pHttpContext, m_RequestHandler, m_RequestHandlerContext, m_AsyncCompletionHandler);
|
||||
|
||||
if (pHandler == NULL)
|
||||
try
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||
*pRequestHandler = new IN_PROCESS_HANDLER(::ReferenceApplication(this), pHttpContext, m_RequestHandler, m_RequestHandlerContext, m_AsyncCompletionHandler);
|
||||
}
|
||||
|
||||
*pRequestHandler = pHandler;
|
||||
return hr;
|
||||
CATCH_RETURN();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include "InProcessApplicationBase.h"
|
||||
#include "IOutputManager.h"
|
||||
#include "InProcessOptions.h"
|
||||
|
|
@ -45,35 +46,26 @@ public:
|
|||
override;
|
||||
|
||||
// Executes the .NET Core process
|
||||
void
|
||||
ExecuteApplication();
|
||||
|
||||
HRESULT
|
||||
ExecuteApplication(
|
||||
VOID
|
||||
);
|
||||
LoadManagedApplication();
|
||||
|
||||
HRESULT
|
||||
LoadManagedApplication(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
LogErrorsOnMainExit(
|
||||
HRESULT hr
|
||||
);
|
||||
|
||||
VOID
|
||||
StopCallsIntoManaged(
|
||||
VOID
|
||||
)
|
||||
void
|
||||
QueueStop();
|
||||
|
||||
void
|
||||
StopIncomingRequests()
|
||||
{
|
||||
m_fBlockCallbacksIntoManaged = TRUE;
|
||||
QueueStop();
|
||||
}
|
||||
|
||||
VOID
|
||||
StopIncomingRequests(
|
||||
VOID
|
||||
)
|
||||
void
|
||||
StopCallsIntoManaged()
|
||||
{
|
||||
m_fShutdownCalledFromManaged = TRUE;
|
||||
m_blockManagedCallbacks = true;
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -84,44 +76,64 @@ public:
|
|||
|
||||
static
|
||||
IN_PROCESS_APPLICATION*
|
||||
GetInstance(
|
||||
VOID
|
||||
)
|
||||
GetInstance()
|
||||
{
|
||||
return s_Application;
|
||||
}
|
||||
|
||||
PCWSTR
|
||||
QueryExeLocation()
|
||||
const std::wstring&
|
||||
QueryExeLocation() const
|
||||
{
|
||||
return m_struExeLocation.QueryStr();
|
||||
return m_dotnetExeKnownLocation;
|
||||
}
|
||||
|
||||
const InProcessOptions&
|
||||
QueryConfig() const
|
||||
{
|
||||
return *m_pConfig.get();
|
||||
return *m_pConfig;
|
||||
}
|
||||
|
||||
bool
|
||||
QueryBlockCallbacksIntoManaged() const
|
||||
{
|
||||
return m_fBlockCallbacksIntoManaged;
|
||||
return m_blockManagedCallbacks;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT Start(
|
||||
IHttpServer& pServer,
|
||||
IHttpApplication& pHttpApplication,
|
||||
APPLICATION_PARAMETER* pParameters,
|
||||
DWORD nParameters,
|
||||
std::unique_ptr<IN_PROCESS_APPLICATION, IAPPLICATION_DELETER>& application);
|
||||
|
||||
private:
|
||||
|
||||
enum MANAGED_APPLICATION_STATUS
|
||||
struct ExecuteClrContext: std::enable_shared_from_this<ExecuteClrContext>
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
STARTING,
|
||||
RUNNING_MANAGED,
|
||||
SHUTDOWN,
|
||||
FAIL
|
||||
};
|
||||
ExecuteClrContext():
|
||||
m_argc(0),
|
||||
m_pProc(nullptr),
|
||||
m_exitCode(0),
|
||||
m_exceptionCode(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Thread executing the .NET Core process
|
||||
HandleWrapper<InvalidHandleTraits> m_hThread;
|
||||
DWORD m_argc;
|
||||
std::unique_ptr<PCWSTR[]> m_argv;
|
||||
hostfxr_main_fn m_pProc;
|
||||
|
||||
int m_exitCode;
|
||||
int m_exceptionCode;
|
||||
};
|
||||
|
||||
// Thread executing the .NET Core process this might be abandoned in timeout cases
|
||||
std::thread m_clrThread;
|
||||
// Thread tracking the CLR thread, this one is always joined on shutdown
|
||||
std::thread m_workerThread;
|
||||
// The event that gets triggered when managed initialization is complete
|
||||
HandleWrapper<NullHandleTraits> m_pInitializeEvent;
|
||||
// The event that gets triggered when worker thread should exit
|
||||
HandleWrapper<NullHandleTraits> m_pShutdownEvent;
|
||||
|
||||
// The request handler callback from managed code
|
||||
PFN_REQUEST_HANDLER m_RequestHandler;
|
||||
|
|
@ -133,53 +145,38 @@ private:
|
|||
|
||||
PFN_ASYNC_COMPLETION_HANDLER m_AsyncCompletionHandler;
|
||||
|
||||
// The event that gets triggered when managed initialization is complete
|
||||
HandleWrapper<InvalidHandleTraits> m_pInitalizeEvent;
|
||||
std::wstring m_dotnetExeKnownLocation;
|
||||
|
||||
STRU m_struExeLocation;
|
||||
std::atomic_bool m_blockManagedCallbacks;
|
||||
bool m_Initialized;
|
||||
bool m_waitForShutdown;
|
||||
|
||||
// The exit code of the .NET Core process
|
||||
INT m_ProcessExitCode;
|
||||
|
||||
volatile BOOL m_fBlockCallbacksIntoManaged;
|
||||
volatile BOOL m_fShutdownCalledFromNative;
|
||||
volatile BOOL m_fShutdownCalledFromManaged;
|
||||
BOOL m_fInitialized;
|
||||
MANAGED_APPLICATION_STATUS m_status;
|
||||
std::unique_ptr<InProcessOptions> m_pConfig;
|
||||
|
||||
static IN_PROCESS_APPLICATION* s_Application;
|
||||
|
||||
std::unique_ptr<IOutputManager> m_pLoggerProvider;
|
||||
|
||||
static const LPCSTR s_exeLocationParameterName;
|
||||
|
||||
static
|
||||
VOID
|
||||
ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
);
|
||||
|
||||
HRESULT
|
||||
SetEnvironementVariablesOnWorkerProcess(
|
||||
VOID
|
||||
);
|
||||
|
||||
HRESULT
|
||||
RunDotnetApplication(
|
||||
DWORD argc,
|
||||
CONST PCWSTR* argv,
|
||||
hostfxr_main_fn pProc
|
||||
);
|
||||
|
||||
static
|
||||
DWORD WINAPI
|
||||
DoShutDown(
|
||||
LPVOID lpParam
|
||||
);
|
||||
inline static const LPCSTR s_exeLocationParameterName = "InProcessExeLocation";
|
||||
|
||||
VOID
|
||||
ShutDownInternal(
|
||||
VOID
|
||||
);
|
||||
UnexpectedThreadExit(const ExecuteClrContext& context) const;
|
||||
|
||||
HRESULT
|
||||
SetEnvironmentVariablesOnWorkerProcess();
|
||||
|
||||
void
|
||||
StopClr();
|
||||
|
||||
static
|
||||
void
|
||||
ClrThreadEntryPoint(const std::shared_ptr<ExecuteClrContext> &context);
|
||||
|
||||
static
|
||||
void
|
||||
ExecuteClr(const std::shared_ptr<ExecuteClrContext> &context);
|
||||
|
||||
// Allows to override call to hostfxr_main with custom callback
|
||||
// used in testing
|
||||
inline static hostfxr_main_fn s_fMainCallback = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,9 +40,7 @@ public:
|
|||
) override;
|
||||
|
||||
IHttpContext*
|
||||
QueryHttpContext(
|
||||
VOID
|
||||
) const
|
||||
QueryHttpContext() const
|
||||
{
|
||||
return m_pW3Context;
|
||||
}
|
||||
|
|
@ -53,9 +51,7 @@ public:
|
|||
);
|
||||
|
||||
VOID
|
||||
IndicateManagedRequestComplete(
|
||||
VOID
|
||||
);
|
||||
IndicateManagedRequestComplete();
|
||||
|
||||
VOID
|
||||
SetAsyncCompletionStatus(
|
||||
|
|
@ -68,11 +64,11 @@ public:
|
|||
|
||||
static
|
||||
HRESULT
|
||||
StaticInitialize(VOID);
|
||||
StaticInitialize();
|
||||
|
||||
static
|
||||
void
|
||||
StaticTerminate(VOID);
|
||||
StaticTerminate();
|
||||
|
||||
private:
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ http_get_application_properties(
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
auto pConfiguration = pInProcessApplication->QueryConfig();
|
||||
const auto& pConfiguration = pInProcessApplication->QueryConfig();
|
||||
|
||||
pIISCofigurationData->pInProcessApplication = pInProcessApplication;
|
||||
pIISCofigurationData->pwzFullApplicationPath = SysAllocString(pInProcessApplication->QueryApplicationPhysicalPath().c_str());
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ Finished:
|
|||
// Global initialization routine for OutOfProcess
|
||||
//
|
||||
HRESULT
|
||||
EnsureOutOfProcessInitializtion()
|
||||
EnsureOutOfProcessInitializtion(IHttpApplication *pHttpApplication)
|
||||
{
|
||||
|
||||
DBG_ASSERT(g_pHttpServer);
|
||||
|
|
@ -202,6 +202,8 @@ EnsureOutOfProcessInitializtion()
|
|||
FINISHED_IF_FAILED(ALLOC_CACHE_HANDLER::StaticInitialize());
|
||||
FINISHED_IF_FAILED(FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
|
||||
FINISHED_IF_FAILED(WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing));
|
||||
|
||||
DebugInitializeFromConfig(*g_pHttpServer, *pHttpApplication);
|
||||
}
|
||||
Finished:
|
||||
if (FAILED(hr))
|
||||
|
|
@ -255,7 +257,7 @@ CreateApplication(
|
|||
RETURN_IF_FAILED(REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(pServer, pHttpApplication, &pConfig));
|
||||
std::unique_ptr<REQUESTHANDLER_CONFIG> pRequestHandlerConfig(pConfig);
|
||||
|
||||
RETURN_IF_FAILED(EnsureOutOfProcessInitializtion());
|
||||
RETURN_IF_FAILED(EnsureOutOfProcessInitializtion(pHttpApplication));
|
||||
|
||||
std::unique_ptr<OUT_OF_PROCESS_APPLICATION> pApplication = std::make_unique<OUT_OF_PROCESS_APPLICATION>(*pHttpApplication, std::move(pRequestHandlerConfig));
|
||||
|
||||
|
|
|
|||
|
|
@ -48,10 +48,7 @@ FORWARDING_HANDLER::FORWARDING_HANDLER(
|
|||
m_pW3Context(pW3Context),
|
||||
m_pApplication(pApplication)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::FORWARDING_HANDLER");
|
||||
#endif
|
||||
LOG_TRACE(L"FORWARDING_HANDLER::FORWARDING_HANDLER");
|
||||
|
||||
m_fWebSocketSupported = m_pApplication->QueryWebsocketStatus();
|
||||
InitializeSRWLock(&m_RequestLock);
|
||||
|
|
@ -65,10 +62,8 @@ FORWARDING_HANDLER::~FORWARDING_HANDLER(
|
|||
//
|
||||
m_Signature = FORWARDING_HANDLER_SIGNATURE_FREE;
|
||||
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::~FORWARDING_HANDLER");
|
||||
#endif
|
||||
LOG_TRACE(L"FORWARDING_HANDLER::~FORWARDING_HANDLER");
|
||||
|
||||
//
|
||||
// RemoveRequest() should already have been called and m_pDisconnect
|
||||
// has been freed or m_pDisconnect was never initialized.
|
||||
|
|
@ -309,10 +304,9 @@ FORWARDING_HANDLER::OnExecuteRequestHandler()
|
|||
reinterpret_cast<DWORD_PTR>(static_cast<PVOID>(this))))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::OnExecuteRequestHandler, Send request failed");
|
||||
#endif
|
||||
|
||||
LOG_TRACE(L"FORWARDING_HANDLER::OnExecuteRequestHandler, Send request failed");
|
||||
|
||||
// FREB log
|
||||
if (ANCMEvents::ANCM_REQUEST_FORWARD_FAIL::IsEnabled(m_pW3Context->GetTraceContext()))
|
||||
{
|
||||
|
|
@ -460,10 +454,8 @@ REQUEST_NOTIFICATION_STATUS
|
|||
|
||||
if (m_RequestStatus == FORWARDER_RECEIVED_WEBSOCKET_RESPONSE)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::OnAsyncCompletion, Send completed for 101 response");
|
||||
#endif
|
||||
LOG_TRACE(L"FORWARDING_HANDLER::OnAsyncCompletion, Send completed for 101 response");
|
||||
|
||||
//
|
||||
// This should be the write completion of the 101 response.
|
||||
//
|
||||
|
|
@ -696,10 +688,7 @@ Finished:
|
|||
//
|
||||
// Do not use this object after dereferencing it, it may be gone.
|
||||
//
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::OnAsyncCompletion Done %d", retVal);
|
||||
#endif
|
||||
LOG_TRACEF(L"FORWARDING_HANDLER::OnAsyncCompletion Done %d", retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
@ -1336,10 +1325,8 @@ None
|
|||
dwInternetStatus);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::OnWinHttpCompletionInternal %x -- %d --%p\n", dwInternetStatus, GetCurrentThreadId(), m_pW3Context);
|
||||
#endif
|
||||
LOG_TRACEF(L"FORWARDING_HANDLER::OnWinHttpCompletionInternal %x -- %d --%p\n", dwInternetStatus, GetCurrentThreadId(), m_pW3Context);
|
||||
|
||||
//
|
||||
// Exclusive lock on the winhttp handle to protect from a client disconnect/
|
||||
// server stop closing the handle while we are using it.
|
||||
|
|
@ -2751,10 +2738,7 @@ FORWARDING_HANDLER::TerminateRequest(
|
|||
// a winhttp callback on the same thread and we donot want to
|
||||
// acquire the lock again
|
||||
|
||||
#ifdef DEBUG
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"FORWARDING_HANDLER::TerminateRequest %d --%p\n", GetCurrentThreadId(), m_pW3Context);
|
||||
#endif // DEBUG
|
||||
LOG_TRACEF(L"FORWARDING_HANDLER::TerminateRequest %d --%p\n", GetCurrentThreadId(), m_pW3Context);
|
||||
|
||||
if (!m_fHttpHandleInClose)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ WEBSOCKET_HANDLER::WEBSOCKET_HANDLER() :
|
|||
_fHandleClosed(FALSE),
|
||||
_fReceivedCloseMsg(FALSE)
|
||||
{
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::WEBSOCKET_HANDLER");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::WEBSOCKET_HANDLER");
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&_RequestLock, 1000);
|
||||
InsertRequest();
|
||||
|
|
@ -58,7 +58,7 @@ WEBSOCKET_HANDLER::Terminate(
|
|||
VOID
|
||||
)
|
||||
{
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::Terminate");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::Terminate");
|
||||
if (!_fHandleClosed)
|
||||
{
|
||||
RemoveRequest();
|
||||
|
|
@ -212,8 +212,7 @@ WEBSOCKET_HANDLER::IndicateCompletionToIIS(
|
|||
|
||||
--*/
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::IndicateCompletionToIIS called %d", _dwOutstandingIo);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::IndicateCompletionToIIS called %d", _dwOutstandingIo);
|
||||
|
||||
//
|
||||
// close Websocket handle. This will triger a WinHttp callback
|
||||
|
|
@ -223,8 +222,7 @@ WEBSOCKET_HANDLER::IndicateCompletionToIIS(
|
|||
//
|
||||
if (_hWebSocketRequest != NULL && _dwOutstandingIo == 0)
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::IndicateCompletionToIIS");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::IndicateCompletionToIIS");
|
||||
|
||||
_pHandler->SetStatus(FORWARDER_DONE);
|
||||
_fHandleClosed = TRUE;
|
||||
|
|
@ -262,8 +260,7 @@ Routine Description:
|
|||
_pHandler = pHandler;
|
||||
|
||||
EnterCriticalSection(&_RequestLock);
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::ProcessRequest");
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::ProcessRequest");
|
||||
|
||||
//
|
||||
// Cache the points to IHttpContext3
|
||||
|
|
@ -359,8 +356,7 @@ Finished:
|
|||
|
||||
if (FAILED_LOG(hr))
|
||||
{
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"Process Request Failed with HR=%08x", hr);
|
||||
LOG_ERRORF(L"Process Request Failed with HR=%08x", hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
|
@ -385,8 +381,7 @@ Routine Description:
|
|||
BOOL fFinalFragment;
|
||||
BOOL fClose;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoIisWebSocketReceive");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::DoIisWebSocketReceive");
|
||||
|
||||
IncrementOutstandingIo();
|
||||
|
||||
|
|
@ -403,8 +398,7 @@ Routine Description:
|
|||
if (FAILED_LOG(hr))
|
||||
{
|
||||
DecrementOutstandingIo();
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoIisWebSocketSend failed with %08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::DoIisWebSocketSend failed with %08x", hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
|
@ -426,8 +420,7 @@ Routine Description:
|
|||
HRESULT hr = S_OK;
|
||||
DWORD dwError = NO_ERROR;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinHttpWebSocketReceive");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::DoWinHttpWebSocketReceive");
|
||||
|
||||
IncrementOutstandingIo();
|
||||
|
||||
|
|
@ -442,8 +435,7 @@ Routine Description:
|
|||
{
|
||||
DecrementOutstandingIo();
|
||||
hr = HRESULT_FROM_WIN32(dwError);
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoWinHttpWebSocketReceive failed with %08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::DoWinHttpWebSocketReceive failed with %08x", hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
|
@ -467,8 +459,7 @@ Routine Description:
|
|||
BOOL fFinalFragment = FALSE;
|
||||
BOOL fClose = FALSE;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoIisWebSocketSend %d", eBufferType);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::DoIisWebSocketSend %d", eBufferType);
|
||||
|
||||
if (eBufferType == WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE)
|
||||
{
|
||||
|
|
@ -558,8 +549,7 @@ Routine Description:
|
|||
Finished:
|
||||
if (FAILED_LOG(hr))
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoIisWebSocketSend failed with %08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::DoIisWebSocketSend failed with %08x", hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
|
@ -581,8 +571,7 @@ Routine Description:
|
|||
DWORD dwError = NO_ERROR;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinHttpWebSocketSend, %d", eBufferType);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::DoWinHttpWebSocketSend, %d", eBufferType);
|
||||
|
||||
if (eBufferType == WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE)
|
||||
{
|
||||
|
|
@ -627,8 +616,7 @@ Routine Description:
|
|||
// Call will complete asynchronously, return.
|
||||
// ignore error.
|
||||
//
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend IO_PENDING");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend IO_PENDING");
|
||||
|
||||
dwError = NO_ERROR;
|
||||
}
|
||||
|
|
@ -639,8 +627,7 @@ Routine Description:
|
|||
//
|
||||
// Call completed synchronously.
|
||||
//
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend Shutdown successful.");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend Shutdown successful.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -666,8 +653,7 @@ Routine Description:
|
|||
Finished:
|
||||
if (FAILED_LOG(hr))
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoWinHttpWebSocketSend failed with %08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::DoWinHttpWebSocketSend failed with %08x", hr);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
|
@ -755,8 +741,7 @@ Routine Description:
|
|||
BOOL fLocked = FALSE;
|
||||
CleanupReason cleanupReason = CleanupReasonUnknown;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::OnWinHttpSendComplete");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::OnWinHttpSendComplete");
|
||||
|
||||
if (_fCleanupInProgress)
|
||||
{
|
||||
|
|
@ -792,8 +777,7 @@ Finished:
|
|||
{
|
||||
Cleanup (cleanupReason);
|
||||
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::OnWinsockSendComplete failed with HR=%08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::OnWinsockSendComplete failed with HR=%08x", hr);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -810,8 +794,7 @@ WEBSOCKET_HANDLER::OnWinHttpShutdownComplete(
|
|||
VOID
|
||||
)
|
||||
{
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::OnWinHttpShutdownComplete --%p", _pHandler);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::OnWinHttpShutdownComplete --%p", _pHandler);
|
||||
|
||||
DecrementOutstandingIo();
|
||||
|
||||
|
|
@ -825,8 +808,7 @@ WEBSOCKET_HANDLER::OnWinHttpIoError(
|
|||
{
|
||||
HRESULT hr = HRESULT_FROM_WIN32(pCompletionStatus->AsyncResult.dwError);
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::OnWinHttpIoError HR = %08x, Operation = %d",
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::OnWinHttpIoError HR = %08x, Operation = %d",
|
||||
hr, pCompletionStatus->AsyncResult.dwResult);
|
||||
|
||||
Cleanup(ServerDisconnect);
|
||||
|
|
@ -858,8 +840,7 @@ Routine Description:
|
|||
BOOL fLocked = FALSE;
|
||||
CleanupReason cleanupReason = CleanupReasonUnknown;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::OnWinHttpReceiveComplete --%p", _pHandler);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::OnWinHttpReceiveComplete --%p", _pHandler);
|
||||
|
||||
if (_fCleanupInProgress)
|
||||
{
|
||||
|
|
@ -893,8 +874,7 @@ Finished:
|
|||
{
|
||||
Cleanup (cleanupReason);
|
||||
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::OnWinsockReceiveComplete failed with HR=%08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::OnWinsockReceiveComplete failed with HR=%08x", hr);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -929,7 +909,7 @@ Routine Description:
|
|||
|
||||
UNREFERENCED_PARAMETER(cbIo);
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::OnIisSendComplete");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::OnIisSendComplete");
|
||||
|
||||
if (FAILED_LOG(hrCompletion))
|
||||
{
|
||||
|
|
@ -974,8 +954,7 @@ Finished:
|
|||
{
|
||||
Cleanup (cleanupReason);
|
||||
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::OnIisSendComplete failed with HR=%08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::OnIisSendComplete failed with HR=%08x", hr);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1014,8 +993,7 @@ Routine Description:
|
|||
CleanupReason cleanupReason = CleanupReasonUnknown;
|
||||
WINHTTP_WEB_SOCKET_BUFFER_TYPE BufferType;
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::OnIisReceiveComplete");
|
||||
LOG_TRACE(L"WEBSOCKET_HANDLER::OnIisReceiveComplete");
|
||||
|
||||
if (FAILED_LOG(hrCompletion))
|
||||
{
|
||||
|
|
@ -1065,8 +1043,7 @@ Finished:
|
|||
{
|
||||
Cleanup (cleanupReason);
|
||||
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::OnIisReceiveComplete failed with HR=%08x", hr);
|
||||
LOG_ERRORF(L"WEBSOCKET_HANDLER::OnIisReceiveComplete failed with HR=%08x", hr);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1097,8 +1074,7 @@ Arguments:
|
|||
--*/
|
||||
{
|
||||
BOOL fLocked = FALSE;
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::Cleanup Initiated with reason %d", reason);
|
||||
LOG_TRACEF(L"WEBSOCKET_HANDLER::Cleanup Initiated with reason %d", reason);
|
||||
|
||||
if (_fCleanupInProgress)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ HRESULT AppOfflineTrackingApplication::StartMonitoringAppOflineImpl()
|
|||
{
|
||||
if (m_fileWatcher)
|
||||
{
|
||||
RETURN_IF_FAILED(E_UNEXPECTED);
|
||||
RETURN_HR(E_UNEXPECTED);
|
||||
}
|
||||
|
||||
m_fileWatcher = std::make_unique<FILE_WATCHER>();
|
||||
|
|
|
|||
|
|
@ -72,16 +72,20 @@
|
|||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\AspNetCoreModule\src\IISLib;$(IncludePath)</IncludePath>
|
||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
LANGUAGE 0x9,0x1
|
||||
1 11 "MSG00001.bin"
|
||||
|
|
@ -55,8 +55,6 @@ REQUESTHANDLER_CONFIG::CreateRequestHandlerConfig(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"REQUESTHANDLER_CONFIG::GetConfig, set config to ModuleContext");
|
||||
// set appliction info here instead of inside Populate()
|
||||
// as the destructor will delete the backend process
|
||||
hr = pRequestHandlerConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
{
|
||||
private const string WebSocketVersionString = "WEBSOCKET_VERSION";
|
||||
|
||||
private static NativeMethods.PFN_REQUEST_HANDLER _requestHandler = HandleRequest;
|
||||
private static NativeMethods.PFN_SHUTDOWN_HANDLER _shutdownHandler = HandleShutdown;
|
||||
private static NativeMethods.PFN_ASYNC_COMPLETION _onAsyncCompletion = OnAsyncCompletion;
|
||||
private static readonly NativeMethods.PFN_REQUEST_HANDLER _requestHandler = HandleRequest;
|
||||
private static readonly NativeMethods.PFN_SHUTDOWN_HANDLER _shutdownHandler = HandleShutdown;
|
||||
private static readonly NativeMethods.PFN_ASYNC_COMPLETION _onAsyncCompletion = OnAsyncCompletion;
|
||||
|
||||
private IISContextFactory _iisContextFactory;
|
||||
private readonly MemoryPool<byte> _memoryPool = new SlabMemoryPool();
|
||||
|
|
@ -147,15 +147,24 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
|
||||
private static NativeMethods.REQUEST_NOTIFICATION_STATUS HandleRequest(IntPtr pInProcessHandler, IntPtr pvRequestContext)
|
||||
{
|
||||
// Unwrap the server so we can create an http context and process the request
|
||||
var server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target;
|
||||
Interlocked.Increment(ref server._outstandingRequests);
|
||||
IISHttpServer server = null;
|
||||
try
|
||||
{
|
||||
// Unwrap the server so we can create an http context and process the request
|
||||
server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target;
|
||||
Interlocked.Increment(ref server._outstandingRequests);
|
||||
|
||||
var context = server._iisContextFactory.CreateHttpContext(pInProcessHandler);
|
||||
var context = server._iisContextFactory.CreateHttpContext(pInProcessHandler);
|
||||
|
||||
ThreadPool.QueueUserWorkItem(state => _ = HandleRequest((IISHttpContext)state), context);
|
||||
ThreadPool.QueueUserWorkItem(state => _ = HandleRequest((IISHttpContext)state), context);
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
server?._logger.LogError(0, ex, $"Unexpected exception in static {nameof(IISHttpServer)}.{nameof(HandleRequest)}.");
|
||||
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task HandleRequest(IISHttpContext context)
|
||||
|
|
@ -167,7 +176,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.Server._logger.LogError("Exception in ProcessRequestAsync", ex);
|
||||
context.Server._logger.LogError(0, ex, $"Unexpected exception in {nameof(IISHttpServer)}.{nameof(HandleRequest)}.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -177,16 +186,34 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
|
||||
private static bool HandleShutdown(IntPtr pvRequestContext)
|
||||
{
|
||||
var server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target;
|
||||
server._applicationLifetime.StopApplication();
|
||||
IISHttpServer server = null;
|
||||
try
|
||||
{
|
||||
server = (IISHttpServer)GCHandle.FromIntPtr(pvRequestContext).Target;
|
||||
server._applicationLifetime.StopApplication();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
server?._logger.LogError(0, ex, $"Unexpected exception in {nameof(IISHttpServer)}.{nameof(HandleShutdown)}.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static NativeMethods.REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(IntPtr pvManagedHttpContext, int hr, int bytes)
|
||||
{
|
||||
var context = (IISHttpContext)GCHandle.FromIntPtr(pvManagedHttpContext).Target;
|
||||
context.OnAsyncCompletion(hr, bytes);
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
|
||||
IISHttpContext context = null;
|
||||
try
|
||||
{
|
||||
context = (IISHttpContext)GCHandle.FromIntPtr(pvManagedHttpContext).Target;
|
||||
context.OnAsyncCompletion(hr, bytes);
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context?.Server._logger.LogError(0, ex, $"Unexpected exception in {nameof(IISHttpServer)}.{nameof(OnAsyncCompletion)}.");
|
||||
|
||||
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CompleteRequest(IISHttpContext context, bool result)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.IO;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks.Sources;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IIS.Core.IO
|
||||
{
|
||||
|
|
@ -103,7 +104,8 @@ namespace Microsoft.AspNetCore.Server.IIS.Core.IO
|
|||
_result = bytes;
|
||||
if (hr != NativeMethods.HR_OK)
|
||||
{
|
||||
_exception = new IOException("Native IO operation failed", Marshal.GetExceptionForHR(hr));
|
||||
// Treat all errors as the client disconnect
|
||||
_exception = new ConnectionResetException("The client has disconnected", Marshal.GetExceptionForHR(hr));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="$(MicrosoftAspNetCoreAuthenticationCorePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="$(MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(VCTargetsPath)' != ''">
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
!IISDeploymentParameters.HandlerSettings.ContainsKey("debugFile"))
|
||||
{
|
||||
_debugLogFile = Path.GetTempFileName();
|
||||
IISDeploymentParameters.HandlerSettings["debugLevel"] = "4";
|
||||
IISDeploymentParameters.HandlerSettings["debugLevel"] = "file";
|
||||
IISDeploymentParameters.HandlerSettings["debugFile"] = _debugLogFile;
|
||||
}
|
||||
|
||||
|
|
@ -254,6 +254,11 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
}
|
||||
|
||||
HostProcess = Process.GetProcessById(workerProcess.ProcessId);
|
||||
|
||||
// Ensure w3wp.exe is killed if test process termination is non-graceful.
|
||||
// Prevents locked files when stop debugging unit test.
|
||||
ProcessTracker.Add(HostProcess);
|
||||
|
||||
// cache the process start time for verifying log file name.
|
||||
var _ = HostProcess.StartTime;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
{
|
||||
public static void AddDebugLogToWebConfig(this IISDeploymentParameters parameters, string filename)
|
||||
{
|
||||
parameters.HandlerSettings["debugLevel"] = "4";
|
||||
parameters.HandlerSettings["debugLevel"] = "file";
|
||||
parameters.HandlerSettings["debugFile"] = filename;
|
||||
}
|
||||
|
||||
|
|
@ -60,5 +60,25 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
deploymentParameters.WebConfigActionList.Add(
|
||||
WebConfigHelpers.AddOrModifyAspNetCoreSection("stdoutLogFile", Path.Combine(path, "std")));
|
||||
}
|
||||
|
||||
public static void TransformPath(this IISDeploymentParameters parameters, Func<string, string, string> transformation)
|
||||
{
|
||||
parameters.WebConfigActionList.Add(
|
||||
(config, contentRoot) =>
|
||||
{
|
||||
var aspNetCoreElement = config.Descendants("aspNetCore").Single();
|
||||
aspNetCoreElement.SetAttributeValue("processPath", transformation((string)aspNetCoreElement.Attribute("processPath"), contentRoot));
|
||||
});
|
||||
}
|
||||
|
||||
public static void TransformArguments(this IISDeploymentParameters parameters, Func<string, string, string> transformation)
|
||||
{
|
||||
parameters.WebConfigActionList.Add(
|
||||
(config, contentRoot) =>
|
||||
{
|
||||
var aspNetCoreElement = config.Descendants("aspNetCore").Single();
|
||||
aspNetCoreElement.SetAttributeValue("arguments", transformation((string)aspNetCoreElement.Attribute("arguments"), contentRoot));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,8 +249,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
else
|
||||
{
|
||||
_hostProcess = process;
|
||||
|
||||
// Ensure iisexpress.exe is killed if test process termination is non-graceful.
|
||||
// Prevents locked files when stop debugging unit test.
|
||||
ProcessTracker.Add(_hostProcess);
|
||||
|
||||
// cache the process start time for verifying log file name.
|
||||
var _ = _hostProcess.StartTime;
|
||||
|
||||
Logger.LogInformation("Started iisexpress successfully. Process Id : {processId}, Port: {port}", _hostProcess.Id, port);
|
||||
return (url: url, hostExitToken: hostExitTokenSource.Token);
|
||||
}
|
||||
|
|
@ -483,7 +489,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"iisexpress Process {hostProcess.Id} crashed before shutdown was triggered.");
|
||||
throw new InvalidOperationException($"iisexpress Process {hostProcess?.Id} crashed before shutdown was triggered.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
|
||||
{
|
||||
// Uses Windows Job Objects to ensure external processes are killed if the current process is terminated non-gracefully.
|
||||
internal static class ProcessTracker
|
||||
{
|
||||
private static readonly IntPtr _jobHandle;
|
||||
|
||||
static ProcessTracker()
|
||||
{
|
||||
// Requires Win8 or later
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || Environment.OSVersion.Version < new Version(6, 2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Job name is optional but helps with diagnostics. Job name must be unique if non-null.
|
||||
_jobHandle = CreateJobObject(IntPtr.Zero, name: $"ProcessTracker{Process.GetCurrentProcess().Id}");
|
||||
|
||||
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
|
||||
{
|
||||
BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
|
||||
{
|
||||
LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
|
||||
}
|
||||
};
|
||||
|
||||
var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
var extendedInfoPtr = Marshal.AllocHGlobal(length);
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
|
||||
|
||||
if (!SetInformationJobObject(_jobHandle, JobObjectInfoType.ExtendedLimitInformation,
|
||||
extendedInfoPtr, (uint)length))
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(extendedInfoPtr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Add(Process process)
|
||||
{
|
||||
if (_jobHandle != IntPtr.Zero)
|
||||
{
|
||||
var success = AssignProcessToJobObject(_jobHandle, process.Handle);
|
||||
if (!success && !process.HasExited)
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern bool SetInformationJobObject(IntPtr job, JobObjectInfoType infoType,
|
||||
IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
|
||||
|
||||
private enum JobObjectInfoType
|
||||
{
|
||||
AssociateCompletionPortInformation = 7,
|
||||
BasicLimitInformation = 2,
|
||||
BasicUIRestrictions = 4,
|
||||
EndOfJobTimeInformation = 6,
|
||||
ExtendedLimitInformation = 9,
|
||||
SecurityLimitInformation = 5,
|
||||
GroupInformation = 11
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct JOBOBJECT_BASIC_LIMIT_INFORMATION
|
||||
{
|
||||
public Int64 PerProcessUserTimeLimit;
|
||||
public Int64 PerJobUserTimeLimit;
|
||||
public JOBOBJECTLIMIT LimitFlags;
|
||||
public UIntPtr MinimumWorkingSetSize;
|
||||
public UIntPtr MaximumWorkingSetSize;
|
||||
public UInt32 ActiveProcessLimit;
|
||||
public Int64 Affinity;
|
||||
public UInt32 PriorityClass;
|
||||
public UInt32 SchedulingClass;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum JOBOBJECTLIMIT : uint
|
||||
{
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct IO_COUNTERS
|
||||
{
|
||||
public UInt64 ReadOperationCount;
|
||||
public UInt64 WriteOperationCount;
|
||||
public UInt64 OtherOperationCount;
|
||||
public UInt64 ReadTransferCount;
|
||||
public UInt64 WriteTransferCount;
|
||||
public UInt64 OtherTransferCount;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
|
||||
{
|
||||
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
|
||||
public IO_COUNTERS IoInfo;
|
||||
public UIntPtr ProcessMemoryLimit;
|
||||
public UIntPtr JobMemoryLimit;
|
||||
public UIntPtr PeakProcessMemoryUsed;
|
||||
public UIntPtr PeakJobMemoryUsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
await deploymentResult.HttpClient.RetryRequestAsync("/HelloWorld", r => r.StatusCode == HttpStatusCode.InternalServerError);
|
||||
|
||||
StopServer();
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Could not find the assembly 'aspnetcorev2_inprocess.dll'");
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Could not find the assembly 'aspnetcorev2_inprocess.dll'");
|
||||
}
|
||||
|
||||
[ConditionalTheory]
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
|
||||
StopServer();
|
||||
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Application '.+' started the coreclr in-process successfully.");
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Application '.+' started the coreclr in-process successfully.");
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
|
||||
StopServer();
|
||||
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Application '.+' has shutdown.");
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, "Application '.+' has shutdown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,17 +200,44 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
private static void AssertLogs(string logPath)
|
||||
[ConditionalFact]
|
||||
public async Task DebugLogsAreWrittenToEventLog()
|
||||
{
|
||||
var deploymentParameters = _fixture.GetBaseDeploymentParameters(publish: true);
|
||||
deploymentParameters.HandlerSettings["debugLevel"] = "file,eventlog";
|
||||
var deploymentResult = await StartAsync(deploymentParameters);
|
||||
StopServer();
|
||||
EventLogHelpers.VerifyEventLogEvent(deploymentResult, @"\[aspnetcorev2.dll\] Initializing logs for .*?Description: IIS ASP.NET Core Module V2");
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task OutOfProcessReadsLogConfiguration()
|
||||
{
|
||||
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel:HostingModel.OutOfProcess, publish: true);
|
||||
deploymentParameters.HandlerSettings["debugLevel"] = "file,trace";
|
||||
deploymentParameters.HandlerSettings["debugFile"] = "";
|
||||
var deploymentResult = await StartAsync(deploymentParameters);
|
||||
|
||||
var logContents = ReadLogs(Path.Combine(deploymentResult.ContentRoot, "aspnetcore-debug.log"));
|
||||
Assert.Contains("FORWARDING_HANDLER::", logContents);
|
||||
}
|
||||
|
||||
private static string ReadLogs(string logPath)
|
||||
{
|
||||
using (var stream = File.Open(logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
var logContents = streamReader.ReadToEnd();
|
||||
Assert.Contains("[aspnetcorev2.dll]", logContents);
|
||||
Assert.Contains("[aspnetcorev2_inprocess.dll]", logContents);
|
||||
Assert.Contains("Description: IIS ASP.NET Core Module V2. Commit:", logContents);
|
||||
Assert.Contains("Description: IIS ASP.NET Core Module V2 Request Handler. Commit:", logContents);
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertLogs(string logPath)
|
||||
{
|
||||
var logContents = ReadLogs(logPath);
|
||||
Assert.Contains("[aspnetcorev2.dll]", logContents);
|
||||
Assert.Contains("[aspnetcorev2_inprocess.dll]", logContents);
|
||||
Assert.Contains("Description: IIS ASP.NET Core Module V2. Commit:", logContents);
|
||||
Assert.Contains("Description: IIS ASP.NET Core Module V2 Request Handler. Commit:", logContents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue