Fix ANCM environment variables bugs (#6083)
This commit is contained in:
parent
a25c7d95e3
commit
a7b783724e
|
|
@ -37,7 +37,7 @@ jobs:
|
||||||
- template: jobs/iisintegration-job.yml
|
- template: jobs/iisintegration-job.yml
|
||||||
parameters:
|
parameters:
|
||||||
TestGroupName: IISExpress
|
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
|
- template: jobs/iisintegration-job.yml
|
||||||
parameters:
|
parameters:
|
||||||
TestGroupName: IISForwardCompat
|
TestGroupName: IISForwardCompat
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "StringHelpers.h"
|
#include "StringHelpers.h"
|
||||||
#include "ConfigurationLoadException.h"
|
#include "ConfigurationLoadException.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
std::wstring ConfigurationSection::GetRequiredString(const std::wstring& name) const
|
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;
|
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
|
std::shared_ptr<ConfigurationSection> ConfigurationSection::GetRequiredSection(const std::wstring& name) const
|
||||||
{
|
{
|
||||||
auto section = GetSection(name);
|
auto section = GetSection(name);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "NonCopyable.h"
|
#include "NonCopyable.h"
|
||||||
|
#include "StringHelpers.h"
|
||||||
|
|
||||||
#define CS_ASPNETCORE_COLLECTION_ITEM_NAME L"name"
|
#define CS_ASPNETCORE_COLLECTION_ITEM_NAME L"name"
|
||||||
#define CS_ASPNETCORE_COLLECTION_ITEM_VALUE L"value"
|
#define CS_ASPNETCORE_COLLECTION_ITEM_VALUE L"value"
|
||||||
|
|
@ -46,6 +48,7 @@ public:
|
||||||
DWORD GetRequiredTimespan(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;
|
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;
|
virtual std::shared_ptr<ConfigurationSection> GetRequiredSection(const std::wstring & name) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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)
|
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
|
// 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)
|
if (source.length() == 0)
|
||||||
{
|
{
|
||||||
return L"";
|
return L"";
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ bool ends_with(const std::wstring &source, const std::wstring &suffix, bool igno
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool equals_ignore_case(const std::wstring& s1, const std::wstring& s2);
|
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]]
|
[[nodiscard]]
|
||||||
std::wstring to_wide_string(const std::string &source, const unsigned int codePage);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ignore_case_comparer
|
||||||
|
{
|
||||||
|
bool operator() (const std::wstring & s1, const std::wstring & s2) const {
|
||||||
|
return compare_ignore_case(s1, s2) == -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,12 @@ private:
|
||||||
return condition;
|
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)
|
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const std::exception& exception)
|
||||||
{
|
{
|
||||||
TraceException(LOCATION_CALL exception);
|
TraceException(LOCATION_CALL exception);
|
||||||
|
|
@ -165,6 +171,11 @@ __declspec(noinline) inline HRESULT CaughtExceptionHResult(LOCATION_ARGUMENTS_ON
|
||||||
ReportException(LOCATION_CALL exception);
|
ReportException(LOCATION_CALL exception);
|
||||||
return exception.GetResult();
|
return exception.GetResult();
|
||||||
}
|
}
|
||||||
|
catch (const InvalidOperationException& exception)
|
||||||
|
{
|
||||||
|
ReportException(LOCATION_CALL exception);
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||||
|
}
|
||||||
catch (const std::exception& exception)
|
catch (const std::exception& exception)
|
||||||
{
|
{
|
||||||
ReportException(LOCATION_CALL exception);
|
ReportException(LOCATION_CALL exception);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
|
||||||
m_fStdoutLogEnabled = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);
|
m_fStdoutLogEnabled = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);
|
||||||
m_struStdoutLogFile = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
|
m_struStdoutLogFile = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
|
||||||
m_fDisableStartUpErrorPage = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE);
|
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);
|
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");
|
m_fSetCurrentDirectory = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_HANDLER_SET_CURRENT_DIRECTORY).value_or(L"true"), L"true");
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "BindingInformation.h"
|
#include "BindingInformation.h"
|
||||||
#include "ConfigurationSource.h"
|
#include "ConfigurationSource.h"
|
||||||
#include "WebConfigConfigurationSource.h"
|
#include "WebConfigConfigurationSource.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class InProcessOptions: NonCopyable
|
class InProcessOptions: NonCopyable
|
||||||
{
|
{
|
||||||
|
|
@ -87,7 +88,7 @@ public:
|
||||||
return m_dwShutdownTimeLimitInMS;
|
return m_dwShutdownTimeLimitInMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<std::wstring, std::wstring>>&
|
const std::map<std::wstring, std::wstring, ignore_case_comparer>&
|
||||||
QueryEnvironmentVariables() const
|
QueryEnvironmentVariables() const
|
||||||
{
|
{
|
||||||
return m_environmentVariables;
|
return m_environmentVariables;
|
||||||
|
|
@ -120,7 +121,7 @@ private:
|
||||||
bool m_fAnonymousAuthEnabled;
|
bool m_fAnonymousAuthEnabled;
|
||||||
DWORD m_dwStartupTimeLimitInMS;
|
DWORD m_dwStartupTimeLimitInMS;
|
||||||
DWORD m_dwShutdownTimeLimitInMS;
|
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;
|
std::vector<BindingInformation> m_bindingInformation;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -425,37 +425,20 @@ IN_PROCESS_APPLICATION::ClrThreadEntryPoint(const std::shared_ptr<ExecuteClrCont
|
||||||
HRESULT
|
HRESULT
|
||||||
IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess()
|
IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess()
|
||||||
{
|
{
|
||||||
auto variables = m_pConfig->QueryEnvironmentVariables();
|
auto variables = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
|
||||||
|
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(),
|
|
||||||
m_pConfig->QueryWindowsAuthEnabled(),
|
m_pConfig->QueryWindowsAuthEnabled(),
|
||||||
m_pConfig->QueryBasicAuthEnabled(),
|
m_pConfig->QueryBasicAuthEnabled(),
|
||||||
m_pConfig->QueryAnonymousAuthEnabled(),
|
m_pConfig->QueryAnonymousAuthEnabled(),
|
||||||
|
false, // fAddHostingStartup
|
||||||
QueryApplicationPhysicalPath().c_str(),
|
QueryApplicationPhysicalPath().c_str(),
|
||||||
nullptr, /* pHttpsPort */
|
nullptr);
|
||||||
&pHashTable));
|
|
||||||
|
|
||||||
table.reset(pHashTable);
|
for (const auto & variable : variables)
|
||||||
|
{
|
||||||
HRESULT hr = S_OK;
|
LOG_INFOF(L"Setting environment variable %ls=%ls", variable.first.c_str(), variable.second.c_str());
|
||||||
table->Apply(ENVIRONMENT_VAR_HELPERS::AppendEnvironmentVariables, &hr);
|
SetEnvironmentVariable(variable.first.c_str(), variable.second.c_str());
|
||||||
RETURN_IF_FAILED(hr);
|
}
|
||||||
|
|
||||||
table->Apply(ENVIRONMENT_VAR_HELPERS::SetEnvironmentVariables, &hr);
|
|
||||||
RETURN_IF_FAILED(hr);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ SERVER_PROCESS::Initialize(
|
||||||
BOOL fWindowsAuthEnabled,
|
BOOL fWindowsAuthEnabled,
|
||||||
BOOL fBasicAuthEnabled,
|
BOOL fBasicAuthEnabled,
|
||||||
BOOL fAnonymousAuthEnabled,
|
BOOL fAnonymousAuthEnabled,
|
||||||
ENVIRONMENT_VAR_HASH *pEnvironmentVariables,
|
std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
|
||||||
BOOL fStdoutLogEnabled,
|
BOOL fStdoutLogEnabled,
|
||||||
BOOL fWebSocketSupported,
|
BOOL fWebSocketSupported,
|
||||||
STRU *pstruStdoutLogFile,
|
STRU *pstruStdoutLogFile,
|
||||||
|
|
@ -761,6 +761,8 @@ SERVER_PROCESS::StartProcess(
|
||||||
ENVIRONMENT_VAR_HASH *pHashTable = NULL;
|
ENVIRONMENT_VAR_HASH *pHashTable = NULL;
|
||||||
PWSTR pStrStage = NULL;
|
PWSTR pStrStage = NULL;
|
||||||
BOOL fCriticalError = FALSE;
|
BOOL fCriticalError = FALSE;
|
||||||
|
std::map<std::wstring, std::wstring, ignore_case_comparer> variables;
|
||||||
|
|
||||||
GetStartupInfoW(&startupInfo);
|
GetStartupInfoW(&startupInfo);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -782,27 +784,30 @@ SERVER_PROCESS::StartProcess(
|
||||||
goto Failure;
|
goto Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED_LOG(hr = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
|
try
|
||||||
m_pEnvironmentVarTable,
|
|
||||||
m_fWindowsAuthEnabled,
|
|
||||||
m_fBasicAuthEnabled,
|
|
||||||
m_fAnonymousAuthEnabled,
|
|
||||||
m_struAppFullPath.QueryStr(),
|
|
||||||
m_struHttpsPort.QueryStr(),
|
|
||||||
&pHashTable)))
|
|
||||||
{
|
{
|
||||||
pStrStage = L"InitEnvironmentVariablesTable";
|
variables = ENVIRONMENT_VAR_HELPERS::InitEnvironmentVariablesTable(
|
||||||
goto Failure;
|
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,
|
pHashTable = new ENVIRONMENT_VAR_HASH();
|
||||||
m_fWebSocketSupported
|
RETURN_IF_FAILED(pHashTable->Initialize(37 /*prime*/));
|
||||||
)))
|
// Copy environment variables to old style hash table
|
||||||
|
for (auto & variable : variables)
|
||||||
{
|
{
|
||||||
pStrStage = L"AddWebsocketEnabledToEnvironmentVariables";
|
auto pNewEntry = std::unique_ptr<ENVIRONMENT_VAR_ENTRY, ENVIRONMENT_VAR_ENTRY_DELETER>(new ENVIRONMENT_VAR_ENTRY());
|
||||||
goto Failure;
|
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();
|
CleanUp();
|
||||||
|
|
||||||
m_pEnvironmentVarTable = NULL;
|
|
||||||
// no need to free m_pEnvironmentVarTable, as it references to
|
// no need to free m_pEnvironmentVarTable, as it references to
|
||||||
// the same hash table hold by configuration.
|
// the same hash table hold by configuration.
|
||||||
// the hashtable memory will be freed once onfiguration got recycled
|
// the hashtable memory will be freed once onfiguration got recycled
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#define MIN_PORT 1025
|
#define MIN_PORT 1025
|
||||||
#define MAX_PORT 48000
|
#define MAX_PORT 48000
|
||||||
|
|
@ -33,7 +34,7 @@ public:
|
||||||
_In_ BOOL fWindowsAuthEnabled,
|
_In_ BOOL fWindowsAuthEnabled,
|
||||||
_In_ BOOL fBasicAuthEnabled,
|
_In_ BOOL fBasicAuthEnabled,
|
||||||
_In_ BOOL fAnonymousAuthEnabled,
|
_In_ BOOL fAnonymousAuthEnabled,
|
||||||
_In_ ENVIRONMENT_VAR_HASH* pEnvironmentVariables,
|
_In_ std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
|
||||||
_In_ BOOL fStdoutLogEnabled,
|
_In_ BOOL fStdoutLogEnabled,
|
||||||
_In_ BOOL fWebSocketSupported,
|
_In_ BOOL fWebSocketSupported,
|
||||||
_In_ STRU *pstruStdoutLogFile,
|
_In_ STRU *pstruStdoutLogFile,
|
||||||
|
|
@ -290,5 +291,5 @@ private:
|
||||||
HANDLE m_hChildProcessWaitHandles[MAX_ACTIVE_CHILD_PROCESSES];
|
HANDLE m_hChildProcessWaitHandles[MAX_ACTIVE_CHILD_PROCESSES];
|
||||||
|
|
||||||
PROCESS_MANAGER *m_pProcessManager;
|
PROCESS_MANAGER *m_pProcessManager;
|
||||||
ENVIRONMENT_VAR_HASH *m_pEnvironmentVarTable ;
|
std::map<std::wstring, std::wstring, ignore_case_comparer> m_pEnvironmentVarTable;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define HOSTING_STARTUP_ASSEMBLIES_ENV_STR L"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"
|
#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 HOSTING_STARTUP_ASSEMBLIES_VALUE L"Microsoft.AspNetCore.Server.IISIntegration"
|
||||||
#define ASPNETCORE_IIS_AUTH_ENV_STR L"ASPNETCORE_IIS_HTTPAUTH="
|
#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_WEBSOCKETS_SUPPORTED_ENV_STR L"ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED"
|
||||||
#define ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR L"ASPNETCORE_IIS_PHYSICAL_PATH="
|
#define ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR L"ASPNETCORE_IIS_PHYSICAL_PATH"
|
||||||
#define ASPNETCORE_HTTPS_PORT_ENV_STR L"ASPNETCORE_HTTPS_PORT="
|
#define ASPNETCORE_HTTPS_PORT_ENV_STR L"ASPNETCORE_HTTPS_PORT"
|
||||||
#define ASPNETCORE_IIS_AUTH_WINDOWS L"windows;"
|
#define ASPNETCORE_IIS_AUTH_WINDOWS L"windows;"
|
||||||
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
|
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
|
||||||
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"
|
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <map>
|
||||||
|
#include "Environment.h"
|
||||||
|
|
||||||
class ENVIRONMENT_VAR_HELPERS
|
class ENVIRONMENT_VAR_HELPERS
|
||||||
{
|
{
|
||||||
|
|
@ -24,422 +26,77 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
std::map<std::wstring, std::wstring, ignore_case_comparer>
|
||||||
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
|
|
||||||
InitEnvironmentVariablesTable
|
InitEnvironmentVariablesTable
|
||||||
(
|
(
|
||||||
_In_ ENVIRONMENT_VAR_HASH* pInEnvironmentVarTable,
|
_In_ const std::map<std::wstring, std::wstring, ignore_case_comparer>& pInEnvironmentVarTable,
|
||||||
_In_ BOOL fWindowsAuthEnabled,
|
_In_ BOOL fWindowsAuthEnabled,
|
||||||
_In_ BOOL fBasicAuthEnabled,
|
_In_ BOOL fBasicAuthEnabled,
|
||||||
_In_ BOOL fAnonymousAuthEnabled,
|
_In_ BOOL fAnonymousAuthEnabled,
|
||||||
|
_In_ BOOL fAddHostingStartup,
|
||||||
_In_ PCWSTR pApplicationPhysicalPath,
|
_In_ PCWSTR pApplicationPhysicalPath,
|
||||||
_In_ PCWSTR pHttpsPort,
|
_In_ PCWSTR pHttpsPort
|
||||||
_Out_ ENVIRONMENT_VAR_HASH** ppEnvironmentVarTable
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
std::map<std::wstring, std::wstring, ignore_case_comparer> environmentVariables = pInEnvironmentVarTable;
|
||||||
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;
|
|
||||||
|
|
||||||
pEnvironmentVarTable = new ENVIRONMENT_VAR_HASH();
|
environmentVariables.insert_or_assign(ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, pApplicationPhysicalPath);
|
||||||
|
if (pHttpsPort)
|
||||||
//
|
|
||||||
// few environment variables expected, small bucket size for hash table
|
|
||||||
//
|
|
||||||
if (FAILED(hr = pEnvironmentVarTable->Initialize(37 /*prime*/)))
|
|
||||||
{
|
{
|
||||||
goto Finished;
|
environmentVariables.try_emplace(ASPNETCORE_HTTPS_PORT_ENV_STR, pHttpsPort);
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring strIisAuthEnvValue;
|
||||||
if (fWindowsAuthEnabled)
|
if (fWindowsAuthEnabled)
|
||||||
{
|
{
|
||||||
strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_WINDOWS);
|
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_WINDOWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fBasicAuthEnabled)
|
if (fBasicAuthEnabled)
|
||||||
{
|
{
|
||||||
strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_BASIC);
|
strIisAuthEnvValue.append(ASPNETCORE_IIS_AUTH_BASIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAnonymousAuthEnabled)
|
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())
|
environmentVariables.insert_or_assign(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue);
|
||||||
{
|
|
||||||
strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
pIISAuthEntry = new ENVIRONMENT_VAR_ENTRY();
|
if (fAddHostingStartup && environmentVariables.count(HOSTING_STARTUP_ASSEMBLIES_ENV_STR) == 0)
|
||||||
|
|
||||||
if (FAILED(hr = pIISAuthEntry->Initialize(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue.QueryStr())) ||
|
|
||||||
FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISAuthEntry)))
|
|
||||||
{
|
{
|
||||||
goto Finished;
|
auto hostingStartupValues = Environment::GetEnvironmentVariableValue(HOSTING_STARTUP_ASSEMBLIES_ENV_STR).value_or(L"");
|
||||||
}
|
|
||||||
|
|
||||||
// Compiler is complaining about conversion between PCWSTR and PWSTR here.
|
if (hostingStartupValues.find(HOSTING_STARTUP_ASSEMBLIES_ENV_STR) == std::wstring::npos)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
hr = HRESULT_FROM_WIN32(dwError);
|
hostingStartupValues += std::wstring(L";") + HOSTING_STARTUP_ASSEMBLIES_VALUE;
|
||||||
goto Finished;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (dwResult > strStartupAssemblyEnv.QuerySizeCCH())
|
environmentVariables.insert_or_assign(HOSTING_STARTUP_ASSEMBLIES_ENV_STR, hostingStartupValues);
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strStartupAssemblyEnv.SyncWithBuffer();
|
for (auto& environmentVariable : environmentVariables)
|
||||||
if (strStartupAssemblyEnv.IndexOf(HOSTING_STARTUP_ASSEMBLIES_VALUE) == -1)
|
|
||||||
{
|
{
|
||||||
if (fFound)
|
environmentVariable.second = Environment::ExpandEnvironmentVariables(environmentVariable.second);
|
||||||
{
|
|
||||||
strStartupAssemblyEnv.Append(L";");
|
|
||||||
}
|
|
||||||
strStartupAssemblyEnv.Append(HOSTING_STARTUP_ASSEMBLIES_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the environment variable was not defined, create it and add to hashtable
|
return environmentVariables;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
HRESULT
|
std::map<std::wstring, std::wstring, ignore_case_comparer>
|
||||||
AddWebsocketEnabledToEnvironmentVariables
|
AddWebsocketEnabledToEnvironmentVariables
|
||||||
(
|
(
|
||||||
_Inout_ ENVIRONMENT_VAR_HASH* pInEnvironmentVarTable,
|
_Inout_ const std::map<std::wstring, std::wstring, ignore_case_comparer>& pInEnvironmentVarTable,
|
||||||
_In_ BOOL fWebsocketsEnabled
|
_In_ BOOL fWebsocketsEnabled
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
std::map<std::wstring, std::wstring, ignore_case_comparer> environmentVariables = pInEnvironmentVarTable;
|
||||||
ENVIRONMENT_VAR_ENTRY* pIISWebsocketEntry = NULL;
|
environmentVariables.insert_or_assign(ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR, fWebsocketsEnabled ? L"true" : L"false");
|
||||||
STACK_STRU(strIISWebsocketEnvValue, 40);
|
return environmentVariables;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
ENVIRONMENT_VAR_HELPERS();
|
|
||||||
~ENVIRONMENT_VAR_HELPERS();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,6 @@ REQUESTHANDLER_CONFIG::~REQUESTHANDLER_CONFIG()
|
||||||
delete[] m_ppStrArguments;
|
delete[] m_ppStrArguments;
|
||||||
m_ppStrArguments = NULL;
|
m_ppStrArguments = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pEnvironmentVariables != NULL)
|
|
||||||
{
|
|
||||||
m_pEnvironmentVariables->Clear();
|
|
||||||
delete m_pEnvironmentVariables;
|
|
||||||
m_pEnvironmentVariables = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
@ -100,12 +93,7 @@ REQUESTHANDLER_CONFIG::Populate(
|
||||||
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
||||||
IAppHostElement *pBasicAuthenticationElement = NULL;
|
IAppHostElement *pBasicAuthenticationElement = NULL;
|
||||||
IAppHostElement *pAnonymousAuthenticationElement = NULL;
|
IAppHostElement *pAnonymousAuthenticationElement = NULL;
|
||||||
IAppHostElement *pEnvVarList = NULL;
|
|
||||||
IAppHostElement *pEnvVar = NULL;
|
|
||||||
IAppHostElementCollection *pEnvVarCollection = NULL;
|
|
||||||
ULONGLONG ullRawTimeSpan = 0;
|
ULONGLONG ullRawTimeSpan = 0;
|
||||||
ENUM_INDEX index;
|
|
||||||
ENVIRONMENT_VAR_ENTRY* pEntry = NULL;
|
|
||||||
DWORD dwCounter = 0;
|
DWORD dwCounter = 0;
|
||||||
DWORD dwPosition = 0;
|
DWORD dwPosition = 0;
|
||||||
WCHAR* pszPath = NULL;
|
WCHAR* pszPath = NULL;
|
||||||
|
|
@ -114,26 +102,20 @@ REQUESTHANDLER_CONFIG::Populate(
|
||||||
BSTR bstrAnonymousAuthSection = NULL;
|
BSTR bstrAnonymousAuthSection = NULL;
|
||||||
BSTR bstrAspNetCoreSection = 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();
|
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());
|
m_struHttpsPort.Copy(BindingInformation::GetHttpsPort(BindingInformation::Load(source, *pSite)).c_str());
|
||||||
}
|
}
|
||||||
catch (...)
|
|
||||||
{
|
m_pEnvironmentVariables = source.GetSection(CS_ASPNETCORE_SECTION)->GetMap(CS_ASPNETCORE_ENVIRONMENT_VARIABLES);
|
||||||
FINISHED_IF_FAILED(OBSERVE_CAUGHT_EXCEPTION());
|
}
|
||||||
}
|
catch (...)
|
||||||
|
{
|
||||||
|
FINISHED_IF_FAILED(OBSERVE_CAUGHT_EXCEPTION());
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = m_struConfigPath.Copy(pHttpApplication->GetAppConfigPath());
|
hr = m_struConfigPath.Copy(pHttpApplication->GetAppConfigPath());
|
||||||
|
|
@ -397,58 +379,6 @@ REQUESTHANDLER_CONFIG::Populate(
|
||||||
goto Finished;
|
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:
|
Finished:
|
||||||
|
|
||||||
if (pAspNetCoreElement != NULL)
|
if (pAspNetCoreElement != NULL)
|
||||||
|
|
@ -475,29 +405,5 @@ Finished:
|
||||||
pBasicAuthenticationElement = NULL;
|
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;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public:
|
||||||
_Out_ REQUESTHANDLER_CONFIG **ppAspNetCoreConfig
|
_Out_ REQUESTHANDLER_CONFIG **ppAspNetCoreConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
ENVIRONMENT_VAR_HASH*
|
std::map<std::wstring, std::wstring, ignore_case_comparer>&
|
||||||
QueryEnvironmentVariables(
|
QueryEnvironmentVariables(
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
|
|
@ -225,7 +225,6 @@ protected:
|
||||||
//
|
//
|
||||||
REQUESTHANDLER_CONFIG() :
|
REQUESTHANDLER_CONFIG() :
|
||||||
m_fStdoutLogEnabled(FALSE),
|
m_fStdoutLogEnabled(FALSE),
|
||||||
m_pEnvironmentVariables(NULL),
|
|
||||||
m_hostingModel(HOSTING_UNKNOWN),
|
m_hostingModel(HOSTING_UNKNOWN),
|
||||||
m_ppStrArguments(NULL)
|
m_ppStrArguments(NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -257,7 +256,7 @@ protected:
|
||||||
BOOL m_fBasicAuthEnabled;
|
BOOL m_fBasicAuthEnabled;
|
||||||
BOOL m_fAnonymousAuthEnabled;
|
BOOL m_fAnonymousAuthEnabled;
|
||||||
APP_HOSTING_MODEL m_hostingModel;
|
APP_HOSTING_MODEL m_hostingModel;
|
||||||
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
std::map<std::wstring, std::wstring, ignore_case_comparer> m_pEnvironmentVariables;
|
||||||
STRU m_struHostFxrLocation;
|
STRU m_struHostFxrLocation;
|
||||||
PWSTR* m_ppStrArguments;
|
PWSTR* m_ppStrArguments;
|
||||||
DWORD m_dwArgc;
|
DWORD m_dwArgc;
|
||||||
|
|
|
||||||
|
|
@ -2,50 +2,132 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
|
||||||
{
|
{
|
||||||
[Collection(IISTestSiteCollection.Name)]
|
[Collection(PublishedSitesCollection.Name)]
|
||||||
public class EnvironmentVariableTests: FixtureLoggedTest
|
|
||||||
{
|
|
||||||
private readonly IISTestSiteFixture _fixture;
|
|
||||||
|
|
||||||
public EnvironmentVariableTests(IISTestSiteFixture fixture): base(fixture)
|
public class EnvironmentVariableTests: IISFunctionalTestBase
|
||||||
|
{
|
||||||
|
private readonly PublishedSitesFixture _fixture;
|
||||||
|
|
||||||
|
public EnvironmentVariableTests(PublishedSitesFixture fixture)
|
||||||
{
|
{
|
||||||
_fixture = fixture;
|
_fixture = fixture;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact]
|
[ConditionalTheory]
|
||||||
public async Task GetUniqueEnvironmentVariable()
|
[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(
|
Assert.Equal(
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
|
expectedValue,
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
|
await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_INPROCESS_TESTING_LONG_VALUE"));
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
|
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
|
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" +
|
|
||||||
"AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative",
|
|
||||||
await _fixture.Client.GetStringAsync("/CheckEnvironmentLongValueVariable"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact]
|
[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]
|
[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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,12 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
|
||||||
return result;
|
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()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
StopServer(false);
|
StopServer(false);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
private async Task ReadAndWriteSynchronously(HttpContext ctx)
|
||||||
{
|
{
|
||||||
var t2 = Task.Run(() => WriteManyTimesToResponseBody(ctx));
|
var t2 = Task.Run(() => WriteManyTimesToResponseBody(ctx));
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,6 @@
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||||
</handlers>
|
</handlers>
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" hostingModel="inprocess">
|
<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>
|
</aspNetCore>
|
||||||
</system.webServer>
|
</system.webServer>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
||||||
|
|
@ -134,5 +134,10 @@ namespace TestSite
|
||||||
GetDllDirectory(1024, builder);
|
GetDllDirectory(1024, builder);
|
||||||
await context.Response.WriteAsync(builder.ToString());
|
await context.Response.WriteAsync(builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task GetEnvironmentVariable(HttpContext ctx)
|
||||||
|
{
|
||||||
|
await ctx.Response.WriteAsync(Environment.GetEnvironmentVariable(ctx.Request.Query["name"].ToString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue