Skip to content

Commit 5fd9435

Browse files
authored
Port ANCM current directory changes to 2.2 (#6150)
1 parent 38c0d5a commit 5fd9435

File tree

20 files changed

+183
-29
lines changed

20 files changed

+183
-29
lines changed

src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ConfigurationSection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define CS_ASPNETCORE_HOSTING_MODEL_INPROCESS L"inprocess"
2424
#define CS_ASPNETCORE_HOSTING_MODEL L"hostingModel"
2525
#define CS_ASPNETCORE_HANDLER_SETTINGS L"handlerSettings"
26+
#define CS_ASPNETCORE_HANDLER_SET_CURRENT_DIRECTORY L"setCurrentDirectory"
2627
#define CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE L"disableStartUpErrorPage"
2728
#define CS_ENABLED L"enabled"
2829

src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,63 @@ Environment::GetEnvironmentVariableValue(const std::wstring & str)
6060

6161
return expandedStr;
6262
}
63+
64+
std::wstring Environment::GetCurrentDirectoryValue()
65+
{
66+
DWORD requestedSize = GetCurrentDirectory(0, nullptr);
67+
if (requestedSize == 0)
68+
{
69+
throw std::system_error(GetLastError(), std::system_category(), "GetCurrentDirectory");
70+
}
71+
72+
std::wstring expandedStr;
73+
do
74+
{
75+
expandedStr.resize(requestedSize);
76+
requestedSize = GetCurrentDirectory(requestedSize, expandedStr.data());
77+
if (requestedSize == 0)
78+
{
79+
throw std::system_error(GetLastError(), std::system_category(), "GetCurrentDirectory");
80+
}
81+
} while (expandedStr.size() != requestedSize + 1);
82+
83+
expandedStr.resize(requestedSize);
84+
85+
return expandedStr;
86+
}
87+
88+
std::wstring Environment::GetDllDirectoryValue()
89+
{
90+
// GetDllDirectory can return 0 in both the success case and the failure case, and it only sets last error when it fails.
91+
// This requires you to set the last error to ERROR_SUCCESS before calling it in order to detect failure.
92+
SetLastError(ERROR_SUCCESS);
93+
94+
DWORD requestedSize = GetDllDirectory(0, nullptr);
95+
if (requestedSize == 0)
96+
{
97+
if (GetLastError() != ERROR_SUCCESS)
98+
{
99+
throw std::system_error(GetLastError(), std::system_category(), "GetDllDirectory");
100+
}
101+
else
102+
{
103+
return L"";
104+
}
105+
}
106+
107+
std::wstring expandedStr;
108+
do
109+
{
110+
expandedStr.resize(requestedSize);
111+
requestedSize = GetDllDirectory(requestedSize, expandedStr.data());
112+
// 0 might be returned if GetDllDirectory is empty
113+
if (requestedSize == 0 && GetLastError() != ERROR_SUCCESS)
114+
{
115+
throw std::system_error(GetLastError(), std::system_category(), "GetDllDirectory");
116+
}
117+
} while (expandedStr.size() != requestedSize + 1);
118+
119+
expandedStr.resize(requestedSize);
120+
121+
return expandedStr;
122+
}

src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ class Environment
1616
std::wstring ExpandEnvironmentVariables(const std::wstring & str);
1717
static
1818
std::optional<std::wstring> GetEnvironmentVariableValue(const std::wstring & str);
19+
static
20+
std::wstring GetCurrentDirectoryValue();
21+
static
22+
std::wstring GetDllDirectoryValue();
1923
};
2024

src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessOptions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
5353
m_struStdoutLogFile = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
5454
m_fDisableStartUpErrorPage = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE);
5555
m_environmentVariables = aspNetCoreSection->GetKeyValuePairs(CS_ASPNETCORE_ENVIRONMENT_VARIABLES);
56+
57+
const auto handlerSettings = aspNetCoreSection->GetKeyValuePairs(CS_ASPNETCORE_HANDLER_SETTINGS);
58+
m_fSetCurrentDirectory = equals_ignore_case(find_element(handlerSettings, CS_ASPNETCORE_HANDLER_SET_CURRENT_DIRECTORY).value_or(L"true"), L"true");
59+
5660
m_dwStartupTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT) * 1000;
5761
m_dwShutdownTimeLimitInMS = aspNetCoreSection->GetRequiredLong(CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT) * 1000;
5862

src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessOptions.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ class InProcessOptions: NonCopyable
4040
return m_fDisableStartUpErrorPage;
4141
}
4242

43+
bool
44+
QuerySetCurrentDirectory() const
45+
{
46+
return m_fSetCurrentDirectory;
47+
}
48+
4349
bool
4450
QueryWindowsAuthEnabled() const
4551
{
@@ -87,7 +93,7 @@ class InProcessOptions: NonCopyable
8793
}
8894

8995
InProcessOptions(const ConfigurationSource &configurationSource);
90-
96+
9197
static
9298
HRESULT InProcessOptions::Create(
9399
IHttpServer& pServer,
@@ -100,6 +106,7 @@ class InProcessOptions: NonCopyable
100106
std::wstring m_struStdoutLogFile;
101107
bool m_fStdoutLogEnabled;
102108
bool m_fDisableStartUpErrorPage;
109+
bool m_fSetCurrentDirectory;
103110
bool m_fWindowsAuthEnabled;
104111
bool m_fBasicAuthEnabled;
105112
bool m_fAnonymousAuthEnabled;

src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "resources.h"
1212
#include "EventLog.h"
1313
#include "ModuleHelpers.h"
14+
#include "Environment.h"
1415

1516
IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
1617

@@ -218,6 +219,25 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
218219
// set the callbacks
219220
s_Application = this;
220221

222+
if (m_pConfig->QuerySetCurrentDirectory())
223+
{
224+
auto dllDirectory = Environment::GetDllDirectoryValue();
225+
auto currentDirectory = Environment::GetCurrentDirectoryValue();
226+
227+
LOG_INFOF(L"Initial Dll directory: '%s', current directory: '%s'", dllDirectory.c_str(), currentDirectory.c_str());
228+
229+
// If DllDirectory wasn't set change it to previous current directory value
230+
if (dllDirectory.empty())
231+
{
232+
LOG_LAST_ERROR_IF(!SetDllDirectory(currentDirectory.c_str()));
233+
LOG_INFOF(L"Setting dll directory to %s", currentDirectory.c_str());
234+
}
235+
236+
LOG_LAST_ERROR_IF(!SetCurrentDirectory(this->QueryApplicationPhysicalPath().c_str()));
237+
238+
LOG_INFOF(L"Setting current directory to %s", this->QueryApplicationPhysicalPath().c_str());
239+
}
240+
221241
//Start CLR thread
222242
m_clrThread = std::thread(ClrThreadEntryPoint, context);
223243

@@ -405,6 +425,7 @@ HRESULT
405425
IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess()
406426
{
407427
auto variables = m_pConfig->QueryEnvironmentVariables();
428+
408429
auto inputTable = std::unique_ptr<ENVIRONMENT_VAR_HASH, ENVIRONMENT_VAR_HASH_DELETER>(new ENVIRONMENT_VAR_HASH());
409430
RETURN_IF_FAILED(inputTable->Initialize(37 /*prime*/));
410431
// Copy environment variables to old style hash table
@@ -422,6 +443,7 @@ IN_PROCESS_APPLICATION::SetEnvironmentVariablesOnWorkerProcess()
422443
m_pConfig->QueryWindowsAuthEnabled(),
423444
m_pConfig->QueryBasicAuthEnabled(),
424445
m_pConfig->QueryAnonymousAuthEnabled(),
446+
QueryApplicationPhysicalPath().c_str(),
425447
&pHashTable));
426448

427449
table.reset(pHashTable);

src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/serverprocess.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ SERVER_PROCESS::StartProcess(
785785
m_fWindowsAuthEnabled,
786786
m_fBasicAuthEnabled,
787787
m_fAnonymousAuthEnabled,
788+
m_struAppFullPath.QueryStr(),
788789
&pHashTable)))
789790
{
790791
pStrStage = L"InitEnvironmentVariablesTable";

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define HOSTING_STARTUP_ASSEMBLIES_VALUE L"Microsoft.AspNetCore.Server.IISIntegration"
99
#define ASPNETCORE_IIS_AUTH_ENV_STR L"ASPNETCORE_IIS_HTTPAUTH="
1010
#define ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR L"ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED="
11+
#define ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR L"ASPNETCORE_IIS_PHYSICAL_PATH="
1112
#define ASPNETCORE_IIS_AUTH_WINDOWS L"windows;"
1213
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
1314
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehelpers.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ class ENVIRONMENT_VAR_HELPERS
191191
_In_ BOOL fWindowsAuthEnabled,
192192
_In_ BOOL fBasicAuthEnabled,
193193
_In_ BOOL fAnonymousAuthEnabled,
194+
_In_ PCWSTR pApplicationPhysicalPath,
194195
_Out_ ENVIRONMENT_VAR_HASH** ppEnvironmentVarTable
195196
)
196197
{
@@ -201,6 +202,7 @@ class ENVIRONMENT_VAR_HELPERS
201202
STACK_STRU(strStartupAssemblyEnv, 1024);
202203
ENVIRONMENT_VAR_ENTRY* pHostingEntry = NULL;
203204
ENVIRONMENT_VAR_ENTRY* pIISAuthEntry = NULL;
205+
ENVIRONMENT_VAR_ENTRY* pIISPathEntry = NULL;
204206
ENVIRONMENT_VAR_HASH* pEnvironmentVarTable = NULL;
205207

206208
pEnvironmentVarTable = new ENVIRONMENT_VAR_HASH();
@@ -213,7 +215,7 @@ class ENVIRONMENT_VAR_HELPERS
213215
goto Finished;
214216
}
215217

216-
// copy the envirable hash table (from configuration) to a temp one as we may need to remove elements
218+
// copy the envirable hash table (from configuration) to a temp one as we may need to remove elements
217219
pInEnvironmentVarTable->Apply(ENVIRONMENT_VAR_HELPERS::CopyToTable, pEnvironmentVarTable);
218220
if (pEnvironmentVarTable->Count() != pInEnvironmentVarTable->Count())
219221
{
@@ -222,6 +224,22 @@ class ENVIRONMENT_VAR_HELPERS
222224
goto Finished;
223225
}
224226

227+
pEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, &pIISPathEntry);
228+
if (pIISPathEntry != NULL)
229+
{
230+
// user defined ASPNETCORE_IIS_PHYSICAL_PATH in configuration, wipe it off
231+
pIISPathEntry->Dereference();
232+
pEnvironmentVarTable->DeleteKey((PWSTR)ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR);
233+
}
234+
235+
pIISPathEntry = new ENVIRONMENT_VAR_ENTRY();
236+
237+
if (FAILED(hr = pIISPathEntry->Initialize(ASPNETCORE_IIS_PHYSICAL_PATH_ENV_STR, pApplicationPhysicalPath)) ||
238+
FAILED(hr = pEnvironmentVarTable->InsertRecord(pIISPathEntry)))
239+
{
240+
goto Finished;
241+
}
242+
225243
pEnvironmentVarTable->FindKey((PWSTR)ASPNETCORE_IIS_AUTH_ENV_STR, &pIISAuthEntry);
226244
if (pIISAuthEntry != NULL)
227245
{
@@ -259,7 +277,7 @@ class ENVIRONMENT_VAR_HELPERS
259277
}
260278

261279
// Compiler is complaining about conversion between PCWSTR and PWSTR here.
262-
// Explictly casting.
280+
// Explictly casting.
263281
pEnvironmentVarTable->FindKey((PWSTR)HOSTING_STARTUP_ASSEMBLIES_NAME, &pHostingEntry);
264282
if (pHostingEntry != NULL)
265283
{

src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/ErrorPagesTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public async Task IncludesAdditionalErrorPageTextInProcessStartupFailure_Correct
105105

106106
private static void VerifyNoExtraTrailingBytes(string responseString)
107107
{
108-
if (!DeployerSelector.IsBackwardsCompatiblityTest)
108+
if (DeployerSelector.HasNewShim)
109109
{
110110
Assert.EndsWith("</html>\r\n", responseString);
111111
}

0 commit comments

Comments
 (0)