Fix ANCM environment variables bugs (#6083)

This commit is contained in:
Pavel Krymets 2018-12-28 15:48:20 -08:00 committed by GitHub
parent a25c7d95e3
commit a7b783724e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 246 additions and 592 deletions

View File

@ -37,7 +37,7 @@ jobs:
- template: jobs/iisintegration-job.yml
parameters:
TestGroupName: IISExpress
skipArgs: "/p:SkipIISBackwardsCompatibilityTests=false /p:SkipIISTests=true /p:SkipIISExpressTests=false /p:SkipIISForwardsCompatibilityTests=true"
skipArgs: "/p:SkipIISBackwardsCompatibilityTests=true /p:SkipIISTests=true /p:SkipIISExpressTests=false /p:SkipIISForwardsCompatibilityTests=true"
- template: jobs/iisintegration-job.yml
parameters:
TestGroupName: IISForwardCompat

View File

@ -5,6 +5,7 @@
#include "StringHelpers.h"
#include "ConfigurationLoadException.h"
#include <map>
std::wstring ConfigurationSection::GetRequiredString(const std::wstring& name) const
{
@ -63,6 +64,17 @@ std::vector<std::pair<std::wstring, std::wstring>> ConfigurationSection::GetKeyV
return pairs;
}
std::map<std::wstring, std::wstring, ignore_case_comparer> ConfigurationSection::GetMap(const std::wstring& name) const
{
std::map<std::wstring, std::wstring, ignore_case_comparer> pairs;
for (auto const element : GetRequiredSection(name)->GetCollection())
{
pairs.insert_or_assign(element->GetRequiredString(CS_ASPNETCORE_COLLECTION_ITEM_NAME), element->GetString(CS_ASPNETCORE_COLLECTION_ITEM_VALUE).value_or(L""));
}
return pairs;
}
std::shared_ptr<ConfigurationSection> ConfigurationSection::GetRequiredSection(const std::wstring& name) const
{
auto section = GetSection(name);

View File

@ -6,8 +6,10 @@
#include <string>
#include <optional>
#include <vector>
#include <map>
#include "NonCopyable.h"
#include "StringHelpers.h"
#define CS_ASPNETCORE_COLLECTION_ITEM_NAME L"name"
#define CS_ASPNETCORE_COLLECTION_ITEM_VALUE L"value"
@ -46,6 +48,7 @@ public:
DWORD GetRequiredTimespan(const std::wstring& name) const;
virtual std::vector<std::pair<std::wstring, std::wstring>> GetKeyValuePairs(const std::wstring& name) const;
virtual std::map<std::wstring, std::wstring, ignore_case_comparer> GetMap(const std::wstring& name) const;
virtual std::shared_ptr<ConfigurationSection> GetRequiredSection(const std::wstring & name) const;

View File

@ -17,13 +17,18 @@ bool ends_with(const std::wstring &source, const std::wstring &suffix, bool igno
bool equals_ignore_case(const std::wstring& s1, const std::wstring& s2)
{
return CSTR_EQUAL == CompareStringOrdinal(s1.c_str(), static_cast<int>(s1.length()), s2.c_str(), static_cast<int>(s2.length()), true);
return compare_ignore_case(s1, s2) == 0;
}
int compare_ignore_case(const std::wstring& s1, const std::wstring& s2)
{
return CompareStringOrdinal(s1.c_str(), static_cast<int>(s1.length()), s2.c_str(), static_cast<int>(s2.length()), true) - CSTR_EQUAL;
}
std::wstring to_wide_string(const std::string &source, const unsigned int codePage)
{
// MultiByteToWideChar returns 0 on failure, which is also the same return value
// for empty strings. Preemptive return.
// for empty strings. Preemptive return.
if (source.length() == 0)
{
return L"";

View File

@ -11,6 +11,9 @@ bool ends_with(const std::wstring &source, const std::wstring &suffix, bool igno
[[nodiscard]]
bool equals_ignore_case(const std::wstring& s1, const std::wstring& s2);
[[nodiscard]]
int compare_ignore_case(const std::wstring& s1, const std::wstring& s2);
[[nodiscard]]
std::wstring to_wide_string(const std::string &source, const unsigned int codePage);
@ -48,3 +51,9 @@ std::string format(const std::string& format, Args ... args)
return result;
}
struct ignore_case_comparer
{
bool operator() (const std::wstring & s1, const std::wstring & s2) const {
return compare_ignore_case(s1, s2) == -1;
}
};

View File

@ -134,6 +134,12 @@ private:
return condition;
}
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const InvalidOperationException& exception)
{
TraceException(LOCATION_CALL exception);
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "InvalidOperationException '%ls' caught at " LOCATION_FORMAT, exception.as_wstring().c_str(), LOCATION_CALL_ONLY);
}
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const std::exception& exception)
{
TraceException(LOCATION_CALL exception);
@ -165,6 +171,11 @@ __declspec(noinline) inline HRESULT CaughtExceptionHResult(LOCATION_ARGUMENTS_ON
ReportException(LOCATION_CALL exception);
return exception.GetResult();
}
catch (const InvalidOperationException& exception)
{
ReportException(LOCATION_CALL exception);
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
}
catch (const std::exception& exception)
{
ReportException(LOCATION_CALL exception);

View File

@ -53,7 +53,7 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
m_fStdoutLogEnabled = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);
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_environmentVariables = aspNetCoreSection->GetMap(CS_ASPNETCORE_ENVIRONMENT_VARIABLES);
const auto handlerSettings = aspNetCoreSection->GetKeyValuePairs(CS_ASPNETCORE_HANDLER_SETTINGS);
m_fSetCurrentDirectory = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_HANDLER_SET_CURRENT_DIRECTORY).value_or(L"true"), L"true");

View File

@ -7,6 +7,7 @@
#include "BindingInformation.h"
#include "ConfigurationSource.h"
#include "WebConfigConfigurationSource.h"
#include <map>
class InProcessOptions: NonCopyable
{
@ -87,7 +88,7 @@ public:
return m_dwShutdownTimeLimitInMS;
}
const std::vector<std::pair<std::wstring, std::wstring>>&
const std::map<std::wstring, std::wstring, ignore_case_comparer>&
QueryEnvironmentVariables() const
{
return m_environmentVariables;
@ -120,7 +121,7 @@ private:
bool m_fAnonymousAuthEnabled;
DWORD m_dwStartupTimeLimitInMS;
DWORD m_dwShutdownTimeLimitInMS;
std::vector<std::pair<std::wstring, std::wstring>> m_environmentVariables;
std::map<std::wstring, std::wstring, ignore_case_comparer> m_environmentVariables;
std::vector<BindingInformation> m_bindingInformation;
protected:

View File

@ -425,37 +425,20 @@ IN_PROCESS_APPLICATION::ClrThreadEntryPoint(const std::shared_ptr<ExecuteClrCont
HRESULT
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());
RETURN_IF_FAILED(inputTable->Initialize(37 /*prime*/));
// Copy environment variables to old style hash table
for (auto & variable : variables)
{
auto pNewEntry = std::unique_ptr<ENVIRONMENT_VAR_ENTRY, ENVIRONMENT_VAR_ENTRY_DELETER>(new ENVIRONMENT_VAR_ENTRY());
RETURN_IF_FAILED(pNewEntry->Initialize((variable.first + L"=").c_str(), variable.second.c_str()));
RETURN_IF_FAILED(inputTable->InsertRecord(pNewEntry.get()));
}
ENVIRONMENT_VAR_HASH* pHashTable = NULL;
std::unique_ptr<ENVIRONMENT_VAR_HASH, ENVIRONMENT_VAR_HASH_DELETER> table;
RETURN_IF_FAILED(ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
inputTable.get(),
auto variables = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
m_pConfig->QueryEnvironmentVariables(),
m_pConfig->QueryWindowsAuthEnabled(),
m_pConfig->QueryBasicAuthEnabled(),
m_pConfig->QueryAnonymousAuthEnabled(),
false, // fAddHostingStartup
QueryApplicationPhysicalPath().c_str(),
nullptr, /* pHttpsPort */
&pHashTable));
nullptr);
table.reset(pHashTable);
HRESULT hr = S_OK;
table->Apply(ENVIRONMENT_VAR_HELPERS::AppendEnvironmentVariables, &hr);
RETURN_IF_FAILED(hr);
table->Apply(ENVIRONMENT_VAR_HELPERS::SetEnvironmentVariables, &hr);
RETURN_IF_FAILED(hr);
for (const auto & variable : variables)
{
LOG_INFOF(L"Setting environment variable %ls=%ls", variable.first.c_str(), variable.second.c_str());
SetEnvironmentVariable(variable.first.c_str(), variable.second.c_str());
}
return S_OK;
}

View File

@ -24,7 +24,7 @@ SERVER_PROCESS::Initialize(
BOOL fWindowsAuthEnabled,
BOOL fBasicAuthEnabled,
BOOL fAnonymousAuthEnabled,
ENVIRONMENT_VAR_HASH *pEnvironmentVariables,
std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
BOOL fStdoutLogEnabled,
BOOL fWebSocketSupported,
STRU *pstruStdoutLogFile,
@ -761,6 +761,8 @@ SERVER_PROCESS::StartProcess(
ENVIRONMENT_VAR_HASH *pHashTable = NULL;
PWSTR pStrStage = NULL;
BOOL fCriticalError = FALSE;
std::map<std::wstring, std::wstring, ignore_case_comparer> variables;
GetStartupInfoW(&startupInfo);
//
@ -782,27 +784,30 @@ SERVER_PROCESS::StartProcess(
goto Failure;
}
if (FAILED_LOG(hr = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
m_pEnvironmentVarTable,
m_fWindowsAuthEnabled,
m_fBasicAuthEnabled,
m_fAnonymousAuthEnabled,
m_struAppFullPath.QueryStr(),
m_struHttpsPort.QueryStr(),
&pHashTable)))
try
{
pStrStage = L"InitEnvironmentVariablesTable";
goto Failure;
variables = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
m_pEnvironmentVarTable,
m_fWindowsAuthEnabled,
m_fBasicAuthEnabled,
m_fAnonymousAuthEnabled,
true, // fAddHostingStartup
m_struAppFullPath.QueryStr(),
m_struHttpsPort.QueryStr());
variables = ENVIRONMENT_VAR_HELPERS::AddWebsocketEnabledToEnvironmentVariables(variables, m_fWebSocketSupported);
}
CATCH_RETURN();
if (FAILED_LOG(hr = ENVIRONMENT_VAR_HELPERS::AddWebsocketEnabledToEnvironmentVariables(
pHashTable,
m_fWebSocketSupported
)))
pHashTable = new ENVIRONMENT_VAR_HASH();
RETURN_IF_FAILED(pHashTable->Initialize(37 /*prime*/));
// Copy environment variables to old style hash table
for (auto & variable : variables)
{
pStrStage = L"AddWebsocketEnabledToEnvironmentVariables";
goto Failure;
auto pNewEntry = std::unique_ptr<ENVIRONMENT_VAR_ENTRY, ENVIRONMENT_VAR_ENTRY_DELETER>(new ENVIRONMENT_VAR_ENTRY());
RETURN_IF_FAILED(pNewEntry->Initialize((variable.first + L"=").c_str(), variable.second.c_str()));
RETURN_IF_FAILED(pHashTable->InsertRecord(pNewEntry.get()));
}
//
@ -1793,7 +1798,6 @@ SERVER_PROCESS::~SERVER_PROCESS()
CleanUp();
m_pEnvironmentVarTable = NULL;
// no need to free m_pEnvironmentVarTable, as it references to
// the same hash table hold by configuration.
// the hashtable memory will be freed once onfiguration got recycled

View File

@ -4,6 +4,7 @@
#pragma once
#include <random>
#include <map>
#define MIN_PORT 1025
#define MAX_PORT 48000
@ -33,7 +34,7 @@ public:
_In_ BOOL fWindowsAuthEnabled,
_In_ BOOL fBasicAuthEnabled,
_In_ BOOL fAnonymousAuthEnabled,
_In_ ENVIRONMENT_VAR_HASH* pEnvironmentVariables,
_In_ std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
_In_ BOOL fStdoutLogEnabled,
_In_ BOOL fWebSocketSupported,
_In_ STRU *pstruStdoutLogFile,
@ -290,5 +291,5 @@ private:
HANDLE m_hChildProcessWaitHandles[MAX_ACTIVE_CHILD_PROCESSES];
PROCESS_MANAGER *m_pProcessManager;
ENVIRONMENT_VAR_HASH *m_pEnvironmentVarTable ;
std::map<std::wstring, std::wstring, ignore_case_comparer> m_pEnvironmentVarTable;
};

View File

@ -4,12 +4,11 @@
#pragma once
#define HOSTING_STARTUP_ASSEMBLIES_ENV_STR L"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"
#define HOSTING_STARTUP_ASSEMBLIES_NAME L"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="
#define HOSTING_STARTUP_ASSEMBLIES_VALUE L"Microsoft.AspNetCore.Server.IISIntegration"
#define ASPNETCORE_IIS_AUTH_ENV_STR L"ASPNETCORE_IIS_HTTPAUTH="
#define ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR L"ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED="
#define ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR L"ASPNETCORE_IIS_PHYSICAL_PATH="
#define ASPNETCORE_HTTPS_PORT_ENV_STR L"ASPNETCORE_HTTPS_PORT="
#define ASPNETCORE_IIS_AUTH_ENV_STR L"ASPNETCORE_IIS_HTTPAUTH"
#define ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR L"ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED"
#define ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR L"ASPNETCORE_IIS_PHYSICAL_PATH"
#define ASPNETCORE_HTTPS_PORT_ENV_STR L"ASPNETCORE_HTTPS_PORT"
#define ASPNETCORE_IIS_AUTH_WINDOWS L"windows;"
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"

View File

@ -2,6 +2,8 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
#pragma once
#include <map>
#include "Environment.h"
class ENVIRONMENT_VAR_HELPERS
{
@ -24,422 +26,77 @@ public:
}
static
VOID
CopyToTable(
ENVIRONMENT_VAR_ENTRY * pEntry,
PVOID pvData
)
{
// best effort copy, ignore the failure
ENVIRONMENT_VAR_ENTRY * pNewEntry = new ENVIRONMENT_VAR_ENTRY();
if (pNewEntry != NULL)
{
pNewEntry->Initialize(pEntry->QueryName(), pEntry->QueryValue());
ENVIRONMENT_VAR_HASH *pHash = static_cast<ENVIRONMENT_VAR_HASH *>(pvData);
DBG_ASSERT(pHash);
pHash->InsertRecord(pNewEntry);
// Need to dereference as InsertRecord references it now
pNewEntry->Dereference();
}
}
static
VOID
AppendEnvironmentVariables
(
ENVIRONMENT_VAR_ENTRY * pEntry,
PVOID pvData
)
{
HRESULT hr = S_OK;
DWORD dwResult = 0;
DWORD dwError = 0;
STRU struNameBuffer;
STACK_STRU(struValueBuffer, 300);
BOOL fFound = FALSE;
HRESULT* pHr = static_cast<HRESULT*>(pvData);
// pEntry->QueryName includes the trailing =, remove it before calling stru
if (FAILED(hr = struNameBuffer.Copy(pEntry->QueryName())))
{
goto Finished;
}
dwResult = struNameBuffer.LastIndexOf(L'=');
if (dwResult != -1)
{
struNameBuffer.QueryStr()[dwResult] = L'\0';
if (FAILED(hr = struNameBuffer.SyncWithBuffer()))
{
goto Finished;
}
}
dwResult = GetEnvironmentVariable(struNameBuffer.QueryStr(), struValueBuffer.QueryStr(), struValueBuffer.QuerySizeCCH());
if (dwResult == 0)
{
dwError = GetLastError();
// Windows API (e.g., CreateProcess) allows variable with empty string value
// in such case dwResult will be 0 and dwError will also be 0
// As UI and CMD does not allow empty value, ignore this environment var
if (dwError != ERROR_ENVVAR_NOT_FOUND && dwError != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwError);
goto Finished;
}
}
else if (dwResult > struValueBuffer.QuerySizeCCH())
{
// have to increase the buffer and try get environment var again
struValueBuffer.Reset();
struValueBuffer.Resize(dwResult + (DWORD)wcslen(pEntry->QueryValue()) + 2); // for null char and semicolon
dwResult = GetEnvironmentVariable(struNameBuffer.QueryStr(),
struValueBuffer.QueryStr(),
struValueBuffer.QuerySizeCCH());
if (dwResult <= 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Finished;
}
fFound = TRUE;
}
else
{
fFound = TRUE;
}
if (FAILED(hr = struValueBuffer.SyncWithBuffer()))
{
goto Finished;
}
if (fFound)
{
if (FAILED(hr = struValueBuffer.Append(L";")))
{
goto Finished;
}
}
if (FAILED(hr = struValueBuffer.Append(pEntry->QueryValue())))
{
goto Finished;
}
if (FAILED(hr = pEntry->Initialize(pEntry->QueryName(), struValueBuffer.QueryStr())))
{
goto Finished;
}
Finished:
if (FAILED(hr))
{
*pHr = hr;
}
return;
}
static
VOID
SetEnvironmentVariables
(
ENVIRONMENT_VAR_ENTRY * pEntry,
PVOID pvData
)
{
UNREFERENCED_PARAMETER(pvData);
HRESULT hr = S_OK;
DWORD dwResult = 0;
STRU struNameBuffer;
HRESULT* pHr = static_cast<HRESULT*>(pvData);
// pEntry->QueryName includes the trailing =, remove it before calling SetEnvironmentVariable.
if (FAILED(hr = struNameBuffer.Copy(pEntry->QueryName())))
{
goto Finished;
}
dwResult = struNameBuffer.LastIndexOf(L'=');
if (dwResult != -1)
{
struNameBuffer.QueryStr()[dwResult] = L'\0';
if (FAILED(hr = struNameBuffer.SyncWithBuffer()))
{
goto Finished;
}
}
dwResult = SetEnvironmentVariable(struNameBuffer.QueryStr(), pEntry->QueryValue());
if (dwResult == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
Finished:
if (FAILED(hr))
{
*pHr = hr;
}
return;
}
static
HRESULT
std::map<std::wstring, std::wstring, ignore_case_comparer>
InitEnvironmentVariablesTable
(
_In_ ENVIRONMENT_VAR_HASH* pInEnvironmentVarTable,
_In_ const std::map<std::wstring, std::wstring, ignore_case_comparer>& pInEnvironmentVarTable,
_In_ BOOL fWindowsAuthEnabled,
_In_ BOOL fBasicAuthEnabled,
_In_ BOOL fAnonymousAuthEnabled,
_In_ BOOL fAddHostingStartup,
_In_ PCWSTR pApplicationPhysicalPath,
_In_ PCWSTR pHttpsPort,
_Out_ ENVIRONMENT_VAR_HASH** ppEnvironmentVarTable
_In_ PCWSTR pHttpsPort
)
{
HRESULT hr = S_OK;
BOOL fFound = FALSE;
DWORD dwResult, dwError;
STRU strIisAuthEnvValue;
STACK_STRU(strStartupAssemblyEnv, 1024);
ENVIRONMENT_VAR_ENTRY* pHostingEntry = NULL;
ENVIRONMENT_VAR_ENTRY* pIISAuthEntry = NULL;
ENVIRONMENT_VAR_ENTRY* pIISPathEntry = NULL;
ENVIRONMENT_VAR_ENTRY* pIISHttpsPort = NULL;
ENVIRONMENT_VAR_HASH* pEnvironmentVarTable = NULL;
std::map<std::wstring, std::wstring, ignore_case_comparer> environmentVariables = pInEnvironmentVarTable;
pEnvironmentVarTable = new ENVIRONMENT_VAR_HASH();
//
// few environment variables expected, small bucket size for hash table
//
if (FAILED(hr = pEnvironmentVarTable->Initialize(37 /*prime*/)))
environmentVariables.insert_or_assign(ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, pApplicationPhysicalPath);
if (pHttpsPort)
{
goto Finished;
}
// copy the envirable hash table (from configuration) to a temp one as we may need to remove elements
pInEnvironmentVarTable->Apply(ENVIRONMENT_VAR_HELPERS::CopyToTable, pEnvironmentVarTable);
if (pEnvironmentVarTable->Count() != pInEnvironmentVarTable->Count())
{
// hash table copy failed
hr = E_UNEXPECTED;
goto Finished;
}
pEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, &pIISPathEntry);
if (pIISPathEntry != NULL)
{
// user defined ASPNETCORE_IIS_PHYSICAL_PATH in configuration, wipe it off
pIISPathEntry->Dereference();
pEnvironmentVarTable->DeleteKey((PWSTR)ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR);
}
pIISPathEntry = new ENVIRONMENT_VAR_ENTRY();
if (FAILED(hr = pIISPathEntry->Initialize(ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, pApplicationPhysicalPath)) ||
FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISPathEntry)))
{
goto Finished;
}
if (pHttpsPort != nullptr)
{
pEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_HTTPS_PORT_ENV_STR, &pIISHttpsPort);
if (pIISHttpsPort != NULL)
{
// user defined ASPNETCORE_HTTPS_PORT in configuration, don't override it
pIISHttpsPort->Dereference();
}
else
{
pIISHttpsPort = new ENVIRONMENT_VAR_ENTRY();
if (FAILED(hr = pIISHttpsPort->Initialize(ASPNETCORE_HTTPS_PORT_ENV_STR, pHttpsPort)) ||
FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISHttpsPort)))
{
goto Finished;
}
}
}
pEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_IIS_AUTH_ENV_STR, &pIISAuthEntry);
if (pIISAuthEntry != NULL)
{
// user defined ASPNETCORE_IIS_HTTPAUTH in configuration, wipe it off
pIISAuthEntry->Dereference();
pEnvironmentVarTable->DeleteKey((PWSTR)ASPNETCORE_IIS_AUTH_ENV_STR);
environmentVariables.try_emplace(ASPNETCORE_HTTPS_PORT_ENV_STR, pHttpsPort);
}
std::wstring strIisAuthEnvValue;
if (fWindowsAuthEnabled)
{
strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_WINDOWS);
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_WINDOWS);
}
if (fBasicAuthEnabled)
{
strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_BASIC);
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_BASIC);
}
if (fAnonymousAuthEnabled)
{
strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_ANONYMOUS);
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_ANONYMOUS);
}
if (strIisAuthEnvValue.empty())
{
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_NONE);
}
if (strIisAuthEnvValue.IsEmpty())
{
strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_NONE);
}
environmentVariables.insert_or_assign(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue);
pIISAuthEntry = new ENVIRONMENT_VAR_ENTRY();
if (FAILED(hr = pIISAuthEntry->Initialize(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue.QueryStr())) ||
FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISAuthEntry)))
if (fAddHostingStartup && environmentVariables.count(HOSTING_STARTUP_ASSEMBLIES_ENV_STR) == 0)
{
goto Finished;
}
auto hostingStartupValues = Environment::GetEnvironmentVariableValue(HOSTING_STARTUP_ASSEMBLIES_ENV_STR).value_or(L"");
// Compiler is complaining about conversion between PCWSTR and PWSTR here.
// Explictly casting.
pEnvironmentVarTable->FindKey((PWSTR)HOSTING_STARTUP_ASSEMBLIES_NAME, &pHostingEntry);
if (pHostingEntry != NULL)
{
// user defined ASPNETCORE_HOSTINGSTARTUPASSEMBLIES in configuration
// the value will be used in OutputEnvironmentVariables. Do nothing here
pHostingEntry->Dereference();
pHostingEntry = NULL;
goto Skipped;
}
//check whether ASPNETCORE_HOSTINGSTARTUPASSEMBLIES is defined in system
dwResult = GetEnvironmentVariable(HOSTING_STARTUP_ASSEMBLIES_ENV_STR,
strStartupAssemblyEnv.QueryStr(),
strStartupAssemblyEnv.QuerySizeCCH());
if (dwResult == 0)
{
dwError = GetLastError();
// Windows API (e.g., CreateProcess) allows variable with empty string value
// in such case dwResult will be 0 and dwError will also be 0
// As UI and CMD does not allow empty value, ignore this environment var
if (dwError != ERROR_ENVVAR_NOT_FOUND && dwError != ERROR_SUCCESS)
if (hostingStartupValues.find(HOSTING_STARTUP_ASSEMBLIES_ENV_STR) == std::wstring::npos)
{
hr = HRESULT_FROM_WIN32(dwError);
goto Finished;
hostingStartupValues += std::wstring(L";") + HOSTING_STARTUP_ASSEMBLIES_VALUE;
}
}
else if (dwResult > strStartupAssemblyEnv.QuerySizeCCH())
{
// have to increase the buffer and try get environment var again
strStartupAssemblyEnv.Reset();
strStartupAssemblyEnv.Resize(dwResult + (DWORD)wcslen(HOSTING_STARTUP_ASSEMBLIES_VALUE) + 1);
dwResult = GetEnvironmentVariable(HOSTING_STARTUP_ASSEMBLIES_ENV_STR,
strStartupAssemblyEnv.QueryStr(),
strStartupAssemblyEnv.QuerySizeCCH());
if (dwResult <= 0)
{
hr = E_UNEXPECTED;
goto Finished;
}
fFound = TRUE;
}
else
{
fFound = TRUE;
environmentVariables.insert_or_assign(HOSTING_STARTUP_ASSEMBLIES_ENV_STR, hostingStartupValues);
}
strStartupAssemblyEnv.SyncWithBuffer();
if (strStartupAssemblyEnv.IndexOf(HOSTING_STARTUP_ASSEMBLIES_VALUE) == -1)
for (auto& environmentVariable : environmentVariables)
{
if (fFound)
{
strStartupAssemblyEnv.Append(L";");
}
strStartupAssemblyEnv.Append(HOSTING_STARTUP_ASSEMBLIES_VALUE);
environmentVariable.second = Environment::ExpandEnvironmentVariables(environmentVariable.second);
}
// the environment variable was not defined, create it and add to hashtable
pHostingEntry = new ENVIRONMENT_VAR_ENTRY();
if (FAILED(hr = pHostingEntry->Initialize(HOSTING_STARTUP_ASSEMBLIES_NAME, strStartupAssemblyEnv.QueryStr())) ||
FAILED(hr = pEnvironmentVarTable->InsertRecord(pHostingEntry)))
{
goto Finished;
}
Skipped:
*ppEnvironmentVarTable = pEnvironmentVarTable;
pEnvironmentVarTable = NULL;
Finished:
if (pHostingEntry != NULL)
{
pHostingEntry->Dereference();
pHostingEntry = NULL;
}
if (pIISAuthEntry != NULL)
{
pIISAuthEntry->Dereference();
pIISAuthEntry = NULL;
}
if (pEnvironmentVarTable != NULL)
{
pEnvironmentVarTable->Clear();
delete pEnvironmentVarTable;
pEnvironmentVarTable = NULL;
}
return hr;
return environmentVariables;
}
static
HRESULT
std::map<std::wstring, std::wstring, ignore_case_comparer>
AddWebsocketEnabledToEnvironmentVariables
(
_Inout_ ENVIRONMENT_VAR_HASH* pInEnvironmentVarTable,
_Inout_ const std::map<std::wstring, std::wstring, ignore_case_comparer>& pInEnvironmentVarTable,
_In_ BOOL fWebsocketsEnabled
)
{
HRESULT hr = S_OK;
ENVIRONMENT_VAR_ENTRY* pIISWebsocketEntry = NULL;
STACK_STRU(strIISWebsocketEnvValue, 40);
// We only need to set the WEBSOCKET_SUPPORTED environment variable for out of process
pInEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR, &pIISWebsocketEntry);
if (pIISWebsocketEntry != NULL)
{
// user defined ASPNETCORE_IIS_WEBSOCKETS in configuration, wipe it off
pIISWebsocketEntry->Dereference();
pInEnvironmentVarTable->DeleteKey((PWSTR)ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR);
}
// Set either true or false for the WebsocketEnvValue.
if (fWebsocketsEnabled)
{
if (FAILED(hr = strIISWebsocketEnvValue.Copy(L"true")))
{
goto Finished;
}
}
else
{
if (FAILED(hr = strIISWebsocketEnvValue.Copy(L"false")))
{
goto Finished;
}
}
pIISWebsocketEntry = new ENVIRONMENT_VAR_ENTRY();
if (FAILED(hr = pIISWebsocketEntry->Initialize(ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR, strIISWebsocketEnvValue.QueryStr())) ||
FAILED(hr = pInEnvironmentVarTable->InsertRecord(pIISWebsocketEntry)))
{
goto Finished;
}
Finished:
return hr;
std::map<std::wstring, std::wstring, ignore_case_comparer> environmentVariables = pInEnvironmentVarTable;
environmentVariables.insert_or_assign(ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR, fWebsocketsEnabled ? L"true" : L"false");
return environmentVariables;
}
public:
ENVIRONMENT_VAR_HELPERS();
~ENVIRONMENT_VAR_HELPERS();
};

View File

@ -15,13 +15,6 @@ REQUESTHANDLER_CONFIG::~REQUESTHANDLER_CONFIG()
delete[] m_ppStrArguments;
m_ppStrArguments = NULL;
}
if (m_pEnvironmentVariables != NULL)
{
m_pEnvironmentVariables->Clear();
delete m_pEnvironmentVariables;
m_pEnvironmentVariables = NULL;
}
}
HRESULT
@ -100,12 +93,7 @@ REQUESTHANDLER_CONFIG::Populate(
IAppHostElement *pWindowsAuthenticationElement = NULL;
IAppHostElement *pBasicAuthenticationElement = NULL;
IAppHostElement *pAnonymousAuthenticationElement = 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;
@ -114,26 +102,20 @@ REQUESTHANDLER_CONFIG::Populate(
BSTR bstrAnonymousAuthSection = NULL;
BSTR bstrAspNetCoreSection = NULL;
m_pEnvironmentVariables = new ENVIRONMENT_VAR_HASH();
if (FAILED(hr = m_pEnvironmentVariables->Initialize(37 /*prime*/)))
{
delete m_pEnvironmentVariables;
m_pEnvironmentVariables = NULL;
goto Finished;
}
pAdminManager = pHttpServer->GetAdminManager();
if (pSite != nullptr)
try
{
try
WebConfigConfigurationSource source(pAdminManager, *pHttpApplication);
if (pSite != nullptr)
{
WebConfigConfigurationSource source(pAdminManager, *pHttpApplication);
m_struHttpsPort.Copy(BindingInformation::GetHttpsPort(BindingInformation::Load(source, *pSite)).c_str());
}
catch (...)
{
FINISHED_IF_FAILED(OBSERVE_CAUGHT_EXCEPTION());
}
m_pEnvironmentVariables = source.GetSection(CS_ASPNETCORE_SECTION)->GetMap(CS_ASPNETCORE_ENVIRONMENT_VARIABLES);
}
catch (...)
{
FINISHED_IF_FAILED(OBSERVE_CAUGHT_EXCEPTION());
}
hr = m_struConfigPath.Copy(pHttpApplication->GetAppConfigPath());
@ -397,58 +379,6 @@ REQUESTHANDLER_CONFIG::Populate(
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 (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)
@ -475,29 +405,5 @@ Finished:
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;
}

View File

@ -68,7 +68,7 @@ public:
_Out_ REQUESTHANDLER_CONFIG **ppAspNetCoreConfig
);
ENVIRONMENT_VAR_HASH*
std::map<std::wstring, std::wstring, ignore_case_comparer>&
QueryEnvironmentVariables(
VOID
)
@ -225,7 +225,6 @@ protected:
//
REQUESTHANDLER_CONFIG() :
m_fStdoutLogEnabled(FALSE),
m_pEnvironmentVariables(NULL),
m_hostingModel(HOSTING_UNKNOWN),
m_ppStrArguments(NULL)
{
@ -257,7 +256,7 @@ protected:
BOOL m_fBasicAuthEnabled;
BOOL m_fAnonymousAuthEnabled;
APP_HOSTING_MODEL m_hostingModel;
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
std::map<std::wstring, std::wstring, ignore_case_comparer> m_pEnvironmentVariables;
STRU m_struHostFxrLocation;
PWSTR* m_ppStrArguments;
DWORD m_dwArgc;

View File

@ -2,50 +2,132 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
[Collection(IISTestSiteCollection.Name)]
public class EnvironmentVariableTests: FixtureLoggedTest
{
private readonly IISTestSiteFixture _fixture;
[Collection(PublishedSitesCollection.Name)]
public EnvironmentVariableTests(IISTestSiteFixture fixture): base(fixture)
public class EnvironmentVariableTests: IISFunctionalTestBase
{
private readonly PublishedSitesFixture _fixture;
public EnvironmentVariableTests(PublishedSitesFixture fixture)
{
_fixture = fixture;
}
[ConditionalFact]
public async Task GetUniqueEnvironmentVariable()
[ConditionalTheory]
[InlineData(HostingModel.InProcess)]
[InlineData(HostingModel.OutOfProcess)]
public async Task GetLongEnvironmentVariable(HostingModel hostingModel)
{
Assert.Equal("foobar", await _fixture.Client.GetStringAsync("/CheckEnvironmentVariable"));
}
var expectedValue = "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative";
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_INPROCESS_TESTING_LONG_VALUE"] = expectedValue;
[ConditionalFact]
public async Task GetLongEnvironmentVariable()
{
Assert.Equal(
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative",
await _fixture.Client.GetStringAsync("/CheckEnvironmentLongValueVariable"));
expectedValue,
await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_INPROCESS_TESTING_LONG_VALUE"));
}
[ConditionalFact]
public async Task GetExistingEnvironmentVariable()
[RequiresNewHandler]
public Task AuthHeaderEnvironmentVariableRemoved_InProcess() => AuthHeaderEnvironmentVariableRemoved(HostingModel.InProcess);
[ConditionalFact]
public Task AuthHeaderEnvironmentVariableRemoved_OutOfProcess() => AuthHeaderEnvironmentVariableRemoved(HostingModel.OutOfProcess);
private async Task AuthHeaderEnvironmentVariableRemoved(HostingModel hostingModel)
{
Assert.Contains(";foobarbaz", await _fixture.Client.GetStringAsync("/CheckAppendedEnvironmentVariable"));
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_IIS_HTTPAUTH"] = "shouldberemoved";
Assert.DoesNotContain("shouldberemoved", await GetStringAsync(deploymentParameters,"/GetEnvironmentVariable?name=ASPNETCORE_IIS_HTTPAUTH"));
}
[ConditionalFact]
public async Task AuthHeaderEnvironmentVariableRemoved()
[RequiresNewHandler]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigOverridesGlobalEnvironmentVariables_InProcess() => WebConfigOverridesGlobalEnvironmentVariables(HostingModel.InProcess);
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigOverridesGlobalEnvironmentVariables_OutOfProcess() => WebConfigOverridesGlobalEnvironmentVariables(HostingModel.OutOfProcess);
private async Task WebConfigOverridesGlobalEnvironmentVariables(HostingModel hostingModel)
{
Assert.DoesNotContain("shouldberemoved", await _fixture.Client.GetStringAsync("/CheckRemoveAuthEnvironmentVariable"));
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.EnvironmentVariables["ASPNETCORE_ENVIRONMENT"] = "Development";
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_ENVIRONMENT"] = "Production";
Assert.Equal("Production", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_ENVIRONMENT"));
}
[ConditionalFact]
[RequiresNewHandler]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigAppendsHostingStartup_InProcess() => WebConfigAppendsHostingStartup(HostingModel.InProcess);
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigAppendsHostingStartup_OutOfProcess() => WebConfigAppendsHostingStartup(HostingModel.OutOfProcess);
private async Task WebConfigAppendsHostingStartup(HostingModel hostingModel)
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.EnvironmentVariables["ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"] = "Asm1";
if (hostingModel == HostingModel.InProcess)
{
Assert.Equal("Asm1", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"));
}
else
{
Assert.Equal("Asm1;Microsoft.AspNetCore.Server.IISIntegration", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"));
}
}
[ConditionalFact]
[RequiresNewHandler]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigOverridesHostingStartup_InProcess() => WebConfigOverridesHostingStartup(HostingModel.InProcess);
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigOverridesHostingStartup_OutOfProcess() => WebConfigOverridesHostingStartup(HostingModel.OutOfProcess);
private async Task WebConfigOverridesHostingStartup(HostingModel hostingModel)
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.EnvironmentVariables["ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"] = "Asm1";
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"] = "Asm2";
Assert.Equal("Asm2", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"));
}
[ConditionalFact]
[RequiresNewHandler]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigExpandsVariables_InProcess() => WebConfigExpandsVariables(HostingModel.InProcess);
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
public Task WebConfigExpandsVariables_OutOfProcess() => WebConfigExpandsVariables(HostingModel.OutOfProcess);
private async Task WebConfigExpandsVariables(HostingModel hostingModel)
{
var deploymentParameters = _fixture.GetBaseDeploymentParameters(hostingModel, publish: true);
deploymentParameters.EnvironmentVariables["TestVariable"] = "World";
deploymentParameters.WebConfigBasedEnvironmentVariables["OtherVariable"] = "%TestVariable%;Hello";
Assert.Equal("World;Hello", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=OtherVariable"));
}
}
}

View File

@ -45,6 +45,12 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
return result;
}
protected virtual async Task<string> GetStringAsync(IISDeploymentParameters parameters, string path)
{
var result = await DeployAsync(parameters);
return await result.HttpClient.GetStringAsync(path);
}
public override void Dispose()
{
StopServer(false);

View File

@ -266,29 +266,6 @@ namespace TestSite
}
}
private async Task CheckEnvironmentVariable(HttpContext ctx)
{
var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_VALUE");
await ctx.Response.WriteAsync(variable);
}
private async Task CheckEnvironmentLongValueVariable(HttpContext ctx)
{
var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_LONG_VALUE");
await ctx.Response.WriteAsync(variable);
}
private async Task CheckAppendedEnvironmentVariable(HttpContext ctx)
{
var variable = Environment.GetEnvironmentVariable("ProgramFiles");
await ctx.Response.WriteAsync(variable);
}
private async Task CheckRemoveAuthEnvironmentVariable(HttpContext ctx)
{
var variable = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH");
await ctx.Response.WriteAsync(variable);
}
private async Task ReadAndWriteSynchronously(HttpContext ctx)
{
var t2 = Task.Run(() => WriteManyTimesToResponseBody(ctx));

View File

@ -5,12 +5,6 @@
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_INPROCESS_TESTING_VALUE" value="foobar" />
<environmentVariable name="ASPNETCORE_INPROCESS_TESTING_LONG_VALUE" value="AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNativeAReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" />
<environmentVariable name="ProgramFiles" value="foobarbaz" />
<environmentVariable name="ASPNETCORE_IIS_HTTPAUTH" value="shouldberemoved" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>

View File

@ -134,5 +134,10 @@ namespace TestSite
GetDllDirectory(1024, builder);
await context.Response.WriteAsync(builder.ToString());
}
private async Task GetEnvironmentVariable(HttpContext ctx)
{
await ctx.Response.WriteAsync(Environment.GetEnvironmentVariable(ctx.Request.Query["name"].ToString()));
}
}
}