From 21b1febf2ba41f39074016ca94fcfdec2ac3b626 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Wed, 21 Feb 2018 12:36:39 -0800 Subject: [PATCH] Adds environment variable feature for inprocess (#583) --- src/CommonLib/environmentvariablehash.h | 326 +++++++++++++++++- src/CommonLib/stdafx.h | 1 + .../inprocess/inprocessapplication.cpp | 29 +- .../inprocess/inprocessapplication.h | 5 + .../outofprocess/serverprocess.cxx | 181 +--------- .../outofprocess/serverprocess.h | 13 - .../EnvironmentVariableTests.cs | 51 +++ test/IISTestSite/Startup.cs | 40 +++ test/IISTestSite/web.config | 9 +- 9 files changed, 462 insertions(+), 193 deletions(-) create mode 100644 test/IISIntegration.IISServerFunctionalTests/EnvironmentVariableTests.cs diff --git a/src/CommonLib/environmentvariablehash.h b/src/CommonLib/environmentvariablehash.h index 797c63c21c..dace338f5d 100644 --- a/src/CommonLib/environmentvariablehash.h +++ b/src/CommonLib/environmentvariablehash.h @@ -3,6 +3,15 @@ #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_AUTH_WINDOWS L"windows;" +#define ASPNETCORE_IIS_AUTH_BASIC L"basic;" +#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;" +#define ASPNETCORE_IIS_AUTH_NONE L"none" + // // The key used for hash-table lookups, consists of the port on which the http process is created. // @@ -69,13 +78,14 @@ private: class ENVIRONMENT_VAR_HASH : public HASH_TABLE { public: - ENVIRONMENT_VAR_HASH() - {} + ENVIRONMENT_VAR_HASH() + { + } PWSTR ExtractKey( ENVIRONMENT_VAR_ENTRY * pEntry - ) + ) { return pEntry->QueryName(); } @@ -138,7 +148,7 @@ public: { // best effort copy, ignore the failure ENVIRONMENT_VAR_ENTRY * pNewEntry = new ENVIRONMENT_VAR_ENTRY(); - if (pNewEntry != NULL) + if (pNewEntry != NULL) { pNewEntry->Initialize(pEntry->QueryName(), pEntry->QueryValue()); ENVIRONMENT_VAR_HASH *pHash = static_cast(pvData); @@ -149,6 +159,314 @@ public: } } + static + VOID + AppendEnvironmentVariables + ( + ENVIRONMENT_VAR_ENTRY * pEntry, + PVOID pvData + ) + { + UNREFERENCED_PARAMETER(pvData); + + HRESULT hr = S_OK; + DWORD dwResult = 0; + DWORD dwError = 0; + STRU struNameBuffer; + STACK_STRU(struValueBuffer, 300); + BOOL fFound = FALSE; + + // 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 (struValueBuffer.IsEmpty()) + { + hr = E_UNEXPECTED; + 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: + // TODO besides calling SetLastError, is there anyway to propagate failures to set the environment variable? + return; + } + + static + VOID + SetEnvironmentVariables + ( + ENVIRONMENT_VAR_ENTRY * pEntry, + PVOID pvData + ) + { + UNREFERENCED_PARAMETER(pvData); + HRESULT hr = S_OK; + DWORD dwResult = 0; + STRU struNameBuffer; + + // 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: + return; + } + + static + HRESULT + InitEnvironmentVariablesTable + ( + _In_ ENVIRONMENT_VAR_HASH* pInEnvironmentVarTable, + BOOL fWindowsAuthEnabled, + BOOL fBasicAuthEnabled, + BOOL fAnonymousAuthEnabled, + ENVIRONMENT_VAR_HASH** ppEnvironmentVarTable + ) + { + 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_HASH* pEnvironmentVarTable = NULL; + + pEnvironmentVarTable = new ENVIRONMENT_VAR_HASH(); + if (pEnvironmentVarTable == NULL) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + + // + // few environment variables expected, small bucket size for hash table + // + if (FAILED(hr = pEnvironmentVarTable->Initialize(37 /*prime*/))) + { + goto Finished; + } + + // copy the envirable hash table (from configuration) to a temp one as we may need to remove elements + pInEnvironmentVarTable->Apply(ENVIRONMENT_VAR_HASH::CopyToTable, pEnvironmentVarTable); + if (pEnvironmentVarTable->Count() != pInEnvironmentVarTable->Count()) + { + // hash table copy failed + hr = E_UNEXPECTED; + 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); + } + + if (fWindowsAuthEnabled) + { + strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_WINDOWS); + } + + if (fBasicAuthEnabled) + { + strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_BASIC); + } + + if (fAnonymousAuthEnabled) + { + strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_ANONYMOUS); + } + + if (strIisAuthEnvValue.IsEmpty()) + { + strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_NONE); + } + + pIISAuthEntry = new ENVIRONMENT_VAR_ENTRY(); + if (pIISAuthEntry == NULL) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + if (FAILED(hr = pIISAuthEntry->Initialize(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue.QueryStr())) || + FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISAuthEntry))) + { + goto Finished; + } + + // 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) + { + hr = HRESULT_FROM_WIN32(dwError); + goto Finished; + } + } + 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 (strStartupAssemblyEnv.IsEmpty()) + { + hr = E_UNEXPECTED; + goto Finished; + } + fFound = TRUE; + } + else + { + fFound = TRUE; + } + + strStartupAssemblyEnv.SyncWithBuffer(); + if (fFound) + { + strStartupAssemblyEnv.Append(L";"); + } + strStartupAssemblyEnv.Append(HOSTING_STARTUP_ASSEMBLIES_VALUE); + + // the environment variable was not defined, create it and add to hashtable + pHostingEntry = new ENVIRONMENT_VAR_ENTRY(); + if (pHostingEntry == NULL) + { + hr = E_OUTOFMEMORY; + goto Finished; + } + 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; + } + private: ENVIRONMENT_VAR_HASH(const ENVIRONMENT_VAR_HASH &); void operator=(const ENVIRONMENT_VAR_HASH &); diff --git a/src/CommonLib/stdafx.h b/src/CommonLib/stdafx.h index 119a9690ca..4f8b6d27d4 100644 --- a/src/CommonLib/stdafx.h +++ b/src/CommonLib/stdafx.h @@ -30,3 +30,4 @@ #include "hostfxr_utility.h" #include "resources.h" #include "aspnetcore_msg.h" + diff --git a/src/RequestHandler/inprocess/inprocessapplication.cpp b/src/RequestHandler/inprocess/inprocessapplication.cpp index 075c65fb14..5a737474b5 100644 --- a/src/RequestHandler/inprocess/inprocessapplication.cpp +++ b/src/RequestHandler/inprocess/inprocessapplication.cpp @@ -615,6 +615,29 @@ IN_PROCESS_APPLICATION::ExecuteAspNetCoreProcess( } +HRESULT +IN_PROCESS_APPLICATION::SetEnvironementVariablesOnWorkerProcess( + VOID +) +{ + HRESULT hr = S_OK; + ENVIRONMENT_VAR_HASH* pHashTable = NULL; + if (FAILED(hr = ENVIRONMENT_VAR_HASH::InitEnvironmentVariablesTable( + m_pConfig->QueryEnvironmentVariables(), + m_pConfig->QueryWindowsAuthEnabled(), + m_pConfig->QueryBasicAuthEnabled(), + m_pConfig->QueryAnonymousAuthEnabled(), + &pHashTable))) + { + goto Finished; + } + + pHashTable->Apply(ENVIRONMENT_VAR_HASH::AppendEnvironmentVariables, NULL); + pHashTable->Apply(ENVIRONMENT_VAR_HASH::SetEnvironmentVariables, NULL); +Finished: + return hr; +} + HRESULT IN_PROCESS_APPLICATION::ExecuteApplication( VOID @@ -634,7 +657,7 @@ IN_PROCESS_APPLICATION::ExecuteApplication( hr = ERROR_BAD_ENVIRONMENT; goto Finished; } - + // Get the entry point for main pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main"); if (pProc == NULL) @@ -647,6 +670,10 @@ IN_PROCESS_APPLICATION::ExecuteApplication( // loaded in the process but we need to get config information to boot it up in the // first place. This is happening in an execute request handler and everyone waits // until this initialization is done. + if (FAILED(hr = SetEnvironementVariablesOnWorkerProcess())) + { + goto Finished; + } // We set a static so that managed code can call back into this instance and // set the callbacks diff --git a/src/RequestHandler/inprocess/inprocessapplication.h b/src/RequestHandler/inprocess/inprocessapplication.h index b32547b234..c72dba2943 100644 --- a/src/RequestHandler/inprocess/inprocessapplication.h +++ b/src/RequestHandler/inprocess/inprocessapplication.h @@ -137,6 +137,11 @@ private: _In_ LPVOID pContext ); + HRESULT + SetEnvironementVariablesOnWorkerProcess( + VOID + ); + static INT FilterException(unsigned int code, struct _EXCEPTION_POINTERS *ep); diff --git a/src/RequestHandler/outofprocess/serverprocess.cxx b/src/RequestHandler/outofprocess/serverprocess.cxx index 9ed0e997e2..431cc41a3f 100644 --- a/src/RequestHandler/outofprocess/serverprocess.cxx +++ b/src/RequestHandler/outofprocess/serverprocess.cxx @@ -333,178 +333,6 @@ Finished: return hr; } - -HRESULT -SERVER_PROCESS::InitEnvironmentVariablesTable( - ENVIRONMENT_VAR_HASH** ppEnvironmentVarTable -) -{ - 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_HASH* pEnvironmentVarTable = NULL; - - pEnvironmentVarTable = new ENVIRONMENT_VAR_HASH(); - if (pEnvironmentVarTable == NULL) - { - hr = E_OUTOFMEMORY; - goto Finished; - } - - // - // few environment variables expected, small bucket size for hash table - // - if (FAILED(hr = pEnvironmentVarTable->Initialize(37 /*prime*/))) - { - goto Finished; - } - - // copy the envirable hash table (from configuration) to a temp one as we may need to remove elements - m_pEnvironmentVarTable->Apply(ENVIRONMENT_VAR_HASH::CopyToTable, pEnvironmentVarTable); - if (pEnvironmentVarTable->Count() != m_pEnvironmentVarTable->Count()) - { - // hash table copy failed - hr = E_UNEXPECTED; - goto Finished; - } - - pEnvironmentVarTable->FindKey(ASPNETCORE_IIS_AUTH_ENV_STR, &pIISAuthEntry); - if (pIISAuthEntry != NULL) - { - // user defined ASPNETCORE_IIS_HTTPAUTH in configuration, wipe it off - pIISAuthEntry->Dereference(); - pEnvironmentVarTable->DeleteKey(ASPNETCORE_IIS_AUTH_ENV_STR); - } - - if (m_fWindowsAuthEnabled) - { - strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_WINDOWS); - } - - if (m_fBasicAuthEnabled) - { - strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_BASIC); - } - - if (m_fAnonymousAuthEnabled) - { - strIisAuthEnvValue.Append(ASPNETCORE_IIS_AUTH_ANONYMOUS); - } - - if (strIisAuthEnvValue.IsEmpty()) - { - strIisAuthEnvValue.Copy(ASPNETCORE_IIS_AUTH_NONE); - } - - pIISAuthEntry = new ENVIRONMENT_VAR_ENTRY(); - if (pIISAuthEntry == NULL) - { - hr = E_OUTOFMEMORY; - goto Finished; - } - if (FAILED(hr = pIISAuthEntry->Initialize(ASPNETCORE_IIS_AUTH_ENV_STR, strIisAuthEnvValue.QueryStr())) || - FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISAuthEntry))) - { - goto Finished; - } - - - pEnvironmentVarTable->FindKey(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); - goto Finished; - } - } - 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 (strStartupAssemblyEnv.IsEmpty()) - { - hr = E_UNEXPECTED; - goto Finished; - } - fFound = TRUE; - } - else - { - fFound = TRUE; - } - - strStartupAssemblyEnv.SyncWithBuffer(); - if (fFound) - { - strStartupAssemblyEnv.Append(L";"); - } - strStartupAssemblyEnv.Append(HOSTING_STARTUP_ASSEMBLIES_VALUE); - - // the environment variable was not defined, create it and add to hashtable - pHostingEntry = new ENVIRONMENT_VAR_ENTRY(); - if (pHostingEntry == NULL) - { - hr = E_OUTOFMEMORY; - goto Finished; - } - 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; -} - HRESULT SERVER_PROCESS::OutputEnvironmentVariables ( @@ -923,11 +751,16 @@ SERVER_PROCESS::StartProcess( // if (FAILED(hr = SetupCommandLine(&m_struCommandLine))) { - pStrStage = L"SetupCommanLine"; + pStrStage = L"SetupCommandLine"; goto Failure; } - if (FAILED(hr = InitEnvironmentVariablesTable(&pHashTable))) + if (FAILED(hr = ENVIRONMENT_VAR_HASH::InitEnvironmentVariablesTable( + m_pEnvironmentVarTable, + m_fWindowsAuthEnabled, + m_fBasicAuthEnabled, + m_fAnonymousAuthEnabled, + &pHashTable))) { pStrStage = L"InitEnvironmentVariablesTable"; goto Failure; diff --git a/src/RequestHandler/outofprocess/serverprocess.h b/src/RequestHandler/outofprocess/serverprocess.h index e0998c160e..567ff3fde3 100644 --- a/src/RequestHandler/outofprocess/serverprocess.h +++ b/src/RequestHandler/outofprocess/serverprocess.h @@ -13,14 +13,6 @@ #define ASPNETCORE_APP_PATH_ENV_STR L"ASPNETCORE_APPL_PATH=" #define ASPNETCORE_APP_TOKEN_ENV_STR L"ASPNETCORE_TOKEN=" #define ASPNETCORE_APP_PATH_ENV_STR L"ASPNETCORE_APPL_PATH=" -#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_AUTH_WINDOWS L"windows;" -#define ASPNETCORE_IIS_AUTH_BASIC L"basic;" -#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;" -#define ASPNETCORE_IIS_AUTH_NONE L"none" class PROCESS_MANAGER; @@ -182,11 +174,6 @@ private: ENVIRONMENT_VAR_HASH* pEnvironmentVarTable ); - HRESULT - InitEnvironmentVariablesTable( - ENVIRONMENT_VAR_HASH** pEnvironmentVarTable - ); - HRESULT OutputEnvironmentVariables( MULTISZ* pmszOutput, diff --git a/test/IISIntegration.IISServerFunctionalTests/EnvironmentVariableTests.cs b/test/IISIntegration.IISServerFunctionalTests/EnvironmentVariableTests.cs new file mode 100644 index 0000000000..95de23f9e6 --- /dev/null +++ b/test/IISIntegration.IISServerFunctionalTests/EnvironmentVariableTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing.xunit; +using Xunit; + +namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests +{ + [Collection(IISTestSiteCollection.Name)] + public class EnvironmentVariableTests + { + private readonly IISTestSiteFixture _fixture; + + public EnvironmentVariableTests(IISTestSiteFixture fixture) + { + _fixture = fixture; + } + + [ConditionalFact] + public async Task GetUniqueEnvironmentVariable() + { + Assert.Equal("foobar", await _fixture.Client.GetStringAsync("/CheckEnvironmentVariable")); + } + + [ConditionalFact] + public async Task GetLongEnvironmentVariable() + { + Assert.Equal( + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative" + + "AReallyLongValueThatIsGreaterThan300CharactersToForceResizeInNative", + await _fixture.Client.GetStringAsync("/CheckEnvironmentLongValueVariable")); + } + + [ConditionalFact] + public async Task GetExistingEnvironmentVariable() + { + Assert.Contains(";foobarbaz", await _fixture.Client.GetStringAsync("/CheckAppendedEnvironmentVariable")); + } + + [ConditionalFact] + public async Task AuthHeaderEnvironmentVariableRemoved() + { + Assert.DoesNotContain("shouldberemoved", await _fixture.Client.GetStringAsync("/CheckRemoveAuthEnvironmentVariable")); + } + } +} diff --git a/test/IISTestSite/Startup.cs b/test/IISTestSite/Startup.cs index e1af0a9bf9..f9e0051105 100644 --- a/test/IISTestSite/Startup.cs +++ b/test/IISTestSite/Startup.cs @@ -31,6 +31,10 @@ namespace IISTestSite app.Map("/LargeResponseBody", LargeResponseBody); app.Map("/ResponseHeaders", ResponseHeaders); app.Map("/ResponseInvalidOrdering", ResponseInvalidOrdering); + app.Map("/CheckEnvironmentVariable", CheckEnvironmentVariable); + app.Map("/CheckEnvironmentLongValueVariable", CheckEnvironmentLongValueVariable); + app.Map("/CheckAppendedEnvironmentVariable", CheckAppendedEnvironmentVariable); + app.Map("/CheckRemoveAuthEnvironmentVariable", CheckRemoveAuthEnvironmentVariable); } private void ServerVariable(IApplicationBuilder app) @@ -285,5 +289,41 @@ namespace IISTestSite } }); } + + private void CheckEnvironmentVariable(IApplicationBuilder app) + { + app.Run(async context => + { + var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_VALUE"); + await context.Response.WriteAsync(variable); + }); + } + + private void CheckEnvironmentLongValueVariable(IApplicationBuilder app) + { + app.Run(async context => + { + var variable = Environment.GetEnvironmentVariable("ASPNETCORE_INPROCESS_TESTING_LONG_VALUE"); + await context.Response.WriteAsync(variable); + }); + } + + private void CheckAppendedEnvironmentVariable(IApplicationBuilder app) + { + app.Run(async context => + { + var variable = Environment.GetEnvironmentVariable("ProgramFiles"); + await context.Response.WriteAsync(variable); + }); + } + + private void CheckRemoveAuthEnvironmentVariable(IApplicationBuilder app) + { + app.Run(async context => + { + var variable = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH"); + await context.Response.WriteAsync(variable); + }); + } } } diff --git a/test/IISTestSite/web.config b/test/IISTestSite/web.config index 74aa96b21f..8ba96a4e9e 100644 --- a/test/IISTestSite/web.config +++ b/test/IISTestSite/web.config @@ -4,6 +4,13 @@ - + + + + + + + +