607 lines
16 KiB
C++
607 lines
16 KiB
C++
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
|
|
#include "stdafx.h"
|
|
#include "aspnetcoreconfig.h"
|
|
|
|
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
|
{
|
|
if (m_ppStrArguments != NULL)
|
|
{
|
|
delete[] m_ppStrArguments;
|
|
m_ppStrArguments = NULL;
|
|
}
|
|
|
|
if (m_pEnvironmentVariables != NULL)
|
|
{
|
|
m_pEnvironmentVariables->Clear();
|
|
delete m_pEnvironmentVariables;
|
|
m_pEnvironmentVariables = NULL;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ASPNETCORE_CONFIG::ReferenceConfiguration(
|
|
VOID
|
|
) const
|
|
{
|
|
InterlockedIncrement(&m_cRefs);
|
|
}
|
|
|
|
VOID
|
|
ASPNETCORE_CONFIG::DereferenceConfiguration(
|
|
VOID
|
|
) const
|
|
{
|
|
DBG_ASSERT(m_cRefs != 0);
|
|
LONG cRefs = 0;
|
|
if ((cRefs = InterlockedDecrement(&m_cRefs)) == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
ASPNETCORE_CONFIG::GetConfig(
|
|
_In_ IHttpServer *pHttpServer,
|
|
_In_ HTTP_MODULE_ID pModuleId,
|
|
_In_ IHttpContext *pHttpContext,
|
|
_In_ HANDLE hEventLog,
|
|
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IHttpApplication *pHttpApplication = pHttpContext->GetApplication();
|
|
ASPNETCORE_CONFIG *pAspNetCoreConfig = NULL;
|
|
STRU struHostFxrDllLocation;
|
|
PWSTR* pwzArgv;
|
|
DWORD dwArgCount;
|
|
|
|
if (ppAspNetCoreConfig == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Finished;
|
|
}
|
|
|
|
*ppAspNetCoreConfig = NULL;
|
|
|
|
// potential bug if user sepcific config at virtual dir level
|
|
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)
|
|
pHttpApplication->GetModuleContextContainer()->GetModuleContext(pModuleId);
|
|
|
|
if (pAspNetCoreConfig != NULL)
|
|
{
|
|
*ppAspNetCoreConfig = pAspNetCoreConfig;
|
|
pAspNetCoreConfig = NULL;
|
|
goto Finished;
|
|
}
|
|
|
|
pAspNetCoreConfig = new ASPNETCORE_CONFIG;
|
|
if (pAspNetCoreConfig == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
|
|
hr = pAspNetCoreConfig->Populate(pHttpServer, pHttpContext);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
// Modify config for inprocess.
|
|
if (pAspNetCoreConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
|
{
|
|
if (FAILED(hr = HOSTFXR_UTILITY::GetHostFxrParameters(
|
|
hEventLog,
|
|
pAspNetCoreConfig->QueryProcessPath()->QueryStr(),
|
|
pAspNetCoreConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
|
pAspNetCoreConfig->QueryArguments()->QueryStr(),
|
|
&struHostFxrDllLocation,
|
|
&dwArgCount,
|
|
&pwzArgv)))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
if (FAILED(hr = pAspNetCoreConfig->SetHostFxrFullPath(struHostFxrDllLocation.QueryStr())))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
pAspNetCoreConfig->SetHostFxrArguments(dwArgCount, pwzArgv);
|
|
}
|
|
|
|
hr = pHttpApplication->GetModuleContextContainer()->
|
|
SetModuleContext(pAspNetCoreConfig, pModuleId);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_ASSIGNED))
|
|
{
|
|
delete pAspNetCoreConfig;
|
|
|
|
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)pHttpApplication->
|
|
GetModuleContextContainer()->
|
|
GetModuleContext(pModuleId);
|
|
|
|
_ASSERT(pAspNetCoreConfig != NULL);
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// set appliction info here instead of inside Populate()
|
|
// as the destructor will delete the backend process
|
|
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
|
|
*ppAspNetCoreConfig = pAspNetCoreConfig;
|
|
pAspNetCoreConfig = NULL;
|
|
|
|
Finished:
|
|
|
|
if (pAspNetCoreConfig != NULL)
|
|
{
|
|
delete pAspNetCoreConfig;
|
|
pAspNetCoreConfig = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
ASPNETCORE_CONFIG::Populate(
|
|
IHttpServer *pHttpServer,
|
|
IHttpContext *pHttpContext
|
|
)
|
|
{
|
|
STACK_STRU(strHostingModel, 300);
|
|
HRESULT hr = S_OK;
|
|
STRU strEnvName;
|
|
STRU strEnvValue;
|
|
STRU strExpandedEnvValue;
|
|
STRU strApplicationFullPath;
|
|
IAppHostAdminManager *pAdminManager = NULL;
|
|
IAppHostElement *pAspNetCoreElement = NULL;
|
|
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
|
IAppHostElement *pBasicAuthenticationElement = NULL;
|
|
IAppHostElement *pAnonymousAuthenticationElement = NULL;
|
|
IAppHostElement *pWebSocketElement = NULL;
|
|
IAppHostElement *pEnvVarList = NULL;
|
|
IAppHostElement *pEnvVar = NULL;
|
|
IAppHostElementCollection *pEnvVarCollection = NULL;
|
|
ULONGLONG ullRawTimeSpan = 0;
|
|
ENUM_INDEX index;
|
|
ENVIRONMENT_VAR_ENTRY* pEntry = NULL;
|
|
DWORD dwCounter = 0;
|
|
DWORD dwPosition = 0;
|
|
WCHAR* pszPath = NULL;
|
|
BSTR bstrWindowAuthSection = NULL;
|
|
BSTR bstrBasicAuthSection = NULL;
|
|
BSTR bstrAnonymousAuthSection = NULL;
|
|
BSTR bstrAspNetCoreSection = NULL;
|
|
BSTR bstrWebsocketSection = NULL;
|
|
|
|
m_pEnvironmentVariables = new ENVIRONMENT_VAR_HASH();
|
|
if (m_pEnvironmentVariables == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
if (FAILED(hr = m_pEnvironmentVariables->Initialize(37 /*prime*/)))
|
|
{
|
|
delete m_pEnvironmentVariables;
|
|
m_pEnvironmentVariables = NULL;
|
|
goto Finished;
|
|
}
|
|
|
|
pAdminManager = pHttpServer->GetAdminManager();
|
|
hr = m_struConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = m_struApplicationPhysicalPath.Copy(pHttpContext->GetApplication()->GetApplicationPhysicalPath());
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
pszPath = m_struConfigPath.QueryStr();
|
|
while (pszPath[dwPosition] != NULL)
|
|
{
|
|
if (pszPath[dwPosition] == '/')
|
|
{
|
|
dwCounter++;
|
|
if (dwCounter == 4)
|
|
break;
|
|
}
|
|
dwPosition++;
|
|
}
|
|
|
|
if (dwCounter == 4)
|
|
{
|
|
hr = m_struApplicationVirtualPath.Copy(pszPath + dwPosition);
|
|
}
|
|
else
|
|
{
|
|
hr = m_struApplicationVirtualPath.Copy(L"/");
|
|
}
|
|
|
|
// Will setup the application virtual path.
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
bstrWindowAuthSection = SysAllocString(CS_WINDOWS_AUTHENTICATION_SECTION);
|
|
if (bstrWindowAuthSection == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
|
|
hr = pAdminManager->GetAdminSection(bstrWindowAuthSection,
|
|
m_struConfigPath.QueryStr(),
|
|
&pWindowsAuthenticationElement);
|
|
if (FAILED(hr))
|
|
{
|
|
// assume the corresponding authen was not enabled
|
|
// as the section may get deleted by user in some HWC case
|
|
// ToDo: log a warning to event log
|
|
m_fWindowsAuthEnabled = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = GetElementBoolProperty(pWindowsAuthenticationElement,
|
|
CS_ENABLED,
|
|
&m_fWindowsAuthEnabled);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
|
|
bstrBasicAuthSection = SysAllocString(CS_BASIC_AUTHENTICATION_SECTION);
|
|
if (bstrBasicAuthSection == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
hr = pAdminManager->GetAdminSection(bstrBasicAuthSection,
|
|
m_struConfigPath.QueryStr(),
|
|
&pBasicAuthenticationElement);
|
|
if (FAILED(hr))
|
|
{
|
|
m_fBasicAuthEnabled = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = GetElementBoolProperty(pBasicAuthenticationElement,
|
|
CS_ENABLED,
|
|
&m_fBasicAuthEnabled);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
bstrAnonymousAuthSection = SysAllocString(CS_ANONYMOUS_AUTHENTICATION_SECTION);
|
|
if (bstrAnonymousAuthSection == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
hr = pAdminManager->GetAdminSection(bstrAnonymousAuthSection,
|
|
m_struConfigPath.QueryStr(),
|
|
&pAnonymousAuthenticationElement);
|
|
if (FAILED(hr))
|
|
{
|
|
m_fAnonymousAuthEnabled = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = GetElementBoolProperty(pAnonymousAuthenticationElement,
|
|
CS_ENABLED,
|
|
&m_fAnonymousAuthEnabled);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
|
|
bstrWebsocketSection = SysAllocString(CS_WEBSOCKET_SECTION);
|
|
if (bstrWebsocketSection == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
|
|
hr = pAdminManager->GetAdminSection(bstrWebsocketSection,
|
|
m_struConfigPath.QueryStr(),
|
|
&pWebSocketElement);
|
|
if (FAILED(hr))
|
|
{
|
|
m_fWebSocketEnabled = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = GetElementBoolProperty(pWebSocketElement,
|
|
CS_ENABLED,
|
|
&m_fWebSocketEnabled);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
|
|
bstrAspNetCoreSection = SysAllocString(CS_ASPNETCORE_SECTION);
|
|
if (bstrAspNetCoreSection == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
hr = pAdminManager->GetAdminSection(bstrAspNetCoreSection,
|
|
m_struConfigPath.QueryStr(),
|
|
&pAspNetCoreElement);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_PROCESS_EXE_PATH,
|
|
&m_struProcessPath);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_HOSTING_MODEL,
|
|
&strHostingModel);
|
|
if (FAILED(hr))
|
|
{
|
|
// Swallow this error for backward compatability
|
|
// Use default behavior for empty string
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (strHostingModel.IsEmpty() || strHostingModel.Equals(L"outofprocess", TRUE))
|
|
{
|
|
m_hostingModel = HOSTING_OUT_PROCESS;
|
|
}
|
|
else if (strHostingModel.Equals(L"inprocess", TRUE))
|
|
{
|
|
m_hostingModel = HOSTING_IN_PROCESS;
|
|
}
|
|
else
|
|
{
|
|
// block unknown hosting value
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_PROCESS_ARGUMENTS,
|
|
&m_struArguments);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementDWORDProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_RAPID_FAILS_PER_MINUTE,
|
|
&m_dwRapidFailsPerMinute);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
//
|
|
// rapidFailsPerMinute cannot be greater than 100.
|
|
//
|
|
if (m_dwRapidFailsPerMinute > MAX_RAPID_FAILS_PER_MINUTE)
|
|
{
|
|
m_dwRapidFailsPerMinute = MAX_RAPID_FAILS_PER_MINUTE;
|
|
}
|
|
|
|
hr = GetElementDWORDProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_PROCESSES_PER_APPLICATION,
|
|
&m_dwProcessesPerApplication);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementDWORDProperty(
|
|
pAspNetCoreElement,
|
|
CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT,
|
|
&m_dwStartupTimeLimitInMS
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
m_dwStartupTimeLimitInMS *= MILLISECONDS_IN_ONE_SECOND;
|
|
|
|
hr = GetElementDWORDProperty(
|
|
pAspNetCoreElement,
|
|
CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT,
|
|
&m_dwShutdownTimeLimitInMS
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
m_dwShutdownTimeLimitInMS *= MILLISECONDS_IN_ONE_SECOND;
|
|
|
|
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_FORWARD_WINDOWS_AUTH_TOKEN,
|
|
&m_fForwardWindowsAuthToken);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE,
|
|
&m_fDisableStartUpErrorPage);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementRawTimeSpanProperty(
|
|
pAspNetCoreElement,
|
|
CS_ASPNETCORE_WINHTTP_REQUEST_TIMEOUT,
|
|
&ullRawTimeSpan
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
m_dwRequestTimeoutInMS = (DWORD)TIMESPAN_IN_MILLISECONDS(ullRawTimeSpan);
|
|
|
|
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_STDOUT_LOG_ENABLED,
|
|
&m_fStdoutLogEnabled);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
CS_ASPNETCORE_STDOUT_LOG_FILE,
|
|
&m_struStdoutLogFile);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = GetElementChildByName(pAspNetCoreElement,
|
|
CS_ASPNETCORE_ENVIRONMENT_VARIABLES,
|
|
&pEnvVarList);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
hr = pEnvVarList->get_Collection(&pEnvVarCollection);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
for (hr = FindFirstElement(pEnvVarCollection, &index, &pEnvVar);
|
|
SUCCEEDED(hr);
|
|
hr = FindNextElement(pEnvVarCollection, &index, &pEnvVar))
|
|
{
|
|
if (hr == S_FALSE)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr = GetElementStringProperty(pEnvVar,
|
|
CS_ASPNETCORE_ENVIRONMENT_VARIABLE_NAME,
|
|
&strEnvName)) ||
|
|
FAILED(hr = GetElementStringProperty(pEnvVar,
|
|
CS_ASPNETCORE_ENVIRONMENT_VARIABLE_VALUE,
|
|
&strEnvValue)) ||
|
|
FAILED(hr = strEnvName.Append(L"=")) ||
|
|
FAILED(hr = STRU::ExpandEnvironmentVariables(strEnvValue.QueryStr(), &strExpandedEnvValue)))
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
pEntry = new ENVIRONMENT_VAR_ENTRY();
|
|
if (pEntry == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Finished;
|
|
}
|
|
|
|
if (FAILED(hr = pEntry->Initialize(strEnvName.QueryStr(), strExpandedEnvValue.QueryStr())) ||
|
|
FAILED(hr = m_pEnvironmentVariables->InsertRecord(pEntry)))
|
|
{
|
|
goto Finished;
|
|
}
|
|
strEnvName.Reset();
|
|
strEnvValue.Reset();
|
|
strExpandedEnvValue.Reset();
|
|
pEnvVar->Release();
|
|
pEnvVar = NULL;
|
|
pEntry->Dereference();
|
|
pEntry = NULL;
|
|
}
|
|
|
|
Finished:
|
|
|
|
if (pAspNetCoreElement != NULL)
|
|
{
|
|
pAspNetCoreElement->Release();
|
|
pAspNetCoreElement = NULL;
|
|
}
|
|
|
|
if (pWebSocketElement != NULL)
|
|
{
|
|
pWebSocketElement->Release();
|
|
pWebSocketElement = NULL;
|
|
}
|
|
|
|
if (pWindowsAuthenticationElement != NULL)
|
|
{
|
|
pWindowsAuthenticationElement->Release();
|
|
pWindowsAuthenticationElement = NULL;
|
|
}
|
|
|
|
if (pAnonymousAuthenticationElement != NULL)
|
|
{
|
|
pAnonymousAuthenticationElement->Release();
|
|
pAnonymousAuthenticationElement = NULL;
|
|
}
|
|
|
|
if (pBasicAuthenticationElement != NULL)
|
|
{
|
|
pBasicAuthenticationElement->Release();
|
|
pBasicAuthenticationElement = NULL;
|
|
}
|
|
|
|
if (pEnvVarList != NULL)
|
|
{
|
|
pEnvVarList->Release();
|
|
pEnvVarList = NULL;
|
|
}
|
|
|
|
if (pEnvVar != NULL)
|
|
{
|
|
pEnvVar->Release();
|
|
pEnvVar = NULL;
|
|
}
|
|
|
|
if (pEnvVarCollection != NULL)
|
|
{
|
|
pEnvVarCollection->Release();
|
|
pEnvVarCollection = NULL;
|
|
}
|
|
|
|
if (pEntry != NULL)
|
|
{
|
|
pEntry->Dereference();
|
|
pEntry = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|