Skip to content

Commit 08c642b

Browse files
committed
work
1 parent 2f66d58 commit 08c642b

33 files changed

+818
-56
lines changed

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AppOfflineHandler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class AppOfflineHandler: public REQUEST_HANDLER
1111
public:
1212
AppOfflineHandler(IHttpContext& pContext, const std::string& appOfflineContent)
1313
: REQUEST_HANDLER(pContext),
14-
m_pContext(pContext),
15-
m_strAppOfflineContent(appOfflineContent)
14+
m_pContext(pContext),
15+
m_strAppOfflineContent(appOfflineContent)
1616
{
1717
}
1818

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ApplicationFactory.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,17 @@ class ApplicationFactory
3232
HRESULT Execute(
3333
_In_ IHttpServer *pServer,
3434
_In_ IHttpContext *pHttpContext,
35+
_In_ std::wstring shadowCopyDirectory,
3536
_Outptr_ IAPPLICATION **pApplication) const
3637
{
3738
// m_location.data() is const ptr copy to local to get mutable pointer
3839
auto location = m_location;
39-
std::array<APPLICATION_PARAMETER, 3> parameters {
40+
std::array<APPLICATION_PARAMETER, 4> parameters {
4041
{
4142
{"InProcessExeLocation", location.data()},
4243
{"TraceContext", pHttpContext->GetTraceContext()},
43-
{"Site", pHttpContext->GetSite()}
44+
{"Site", pHttpContext->GetSite()},
45+
{"ShadowCopyDirectory", shadowCopyDirectory.data()}
4446
}
4547
};
4648

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/AspNetCore.vcxproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
<Link>
112112
<SubSystem>Windows</SubSystem>
113113
<GenerateDebugInformation>true</GenerateDebugInformation>
114-
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib</AdditionalDependencies>
114+
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib;Rpcrt4.lib</AdditionalDependencies>
115115
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
116116
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
117117
</Link>
@@ -147,7 +147,7 @@
147147
<Link>
148148
<SubSystem>Windows</SubSystem>
149149
<GenerateDebugInformation>true</GenerateDebugInformation>
150-
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib</AdditionalDependencies>
150+
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib;Rpcrt4.lib</AdditionalDependencies>
151151
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
152152
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
153153
</Link>
@@ -188,7 +188,7 @@
188188
<AdditionalOptions>/NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib %(AdditionalOptions)</AdditionalOptions>
189189
<OptimizeReferences>true</OptimizeReferences>
190190
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
191-
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib</AdditionalDependencies>
191+
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib;Rpcrt4.lib</AdditionalDependencies>
192192
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
193193
</Link>
194194
<ResourceCompile>
@@ -228,7 +228,7 @@
228228
<AdditionalOptions>/NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib %(AdditionalOptions)</AdditionalOptions>
229229
<OptimizeReferences>true</OptimizeReferences>
230230
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
231-
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib</AdditionalDependencies>
231+
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;ws2_32.lib;iphlpapi.lib;version.lib;Rpcrt4.lib</AdditionalDependencies>
232232
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
233233
</Link>
234234
<ResourceCompile>
@@ -317,4 +317,4 @@
317317
</ItemGroup>
318318
<WriteLinesToFile File="$(InstallersOutputPath)aspnetcoremodule.version" Lines="@(VersionFileContents)" OverWrite="true" WriteOnlyWhenDifferent="True" />
319319
</Target>
320-
</Project>
320+
</Project>

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ HandlerResolver::HandlerResolver(HMODULE hModule, const IHttpServer &pServer)
2929

3030
HRESULT
3131
HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication,
32+
std::filesystem::path shadowCopyPath,
3233
const ShimOptions& pConfiguration,
3334
std::unique_ptr<ApplicationFactory>& pApplicationFactory,
3435
ErrorContext& errorContext)
@@ -62,7 +63,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
6263
RETURN_IF_FAILED(HostFxrResolutionResult::Create(
6364
L"",
6465
pConfiguration.QueryProcessPath(),
65-
pApplication.GetApplicationPhysicalPath(),
66+
shadowCopyPath.empty() ? pApplication.GetApplicationPhysicalPath() : shadowCopyPath,
6667
pConfiguration.QueryArguments(),
6768
errorContext,
6869
options));
@@ -125,7 +126,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication
125126
}
126127

127128
HRESULT
128-
HandlerResolver::GetApplicationFactory(const IHttpApplication& pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext)
129+
HandlerResolver::GetApplicationFactory(const IHttpApplication& pApplication, std::filesystem::path shadowCopyPath, std::unique_ptr<ApplicationFactory>& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext)
129130
{
130131
SRWExclusiveLock lock(m_requestHandlerLoadLock);
131132
if (m_loadedApplicationHostingModel != HOSTING_UNKNOWN)
@@ -168,7 +169,7 @@ HandlerResolver::GetApplicationFactory(const IHttpApplication& pApplication, std
168169

169170
m_loadedApplicationHostingModel = options.QueryHostingModel();
170171
m_loadedApplicationId = pApplication.GetApplicationId();
171-
RETURN_IF_FAILED(LoadRequestHandlerAssembly(pApplication, options, pApplicationFactory, errorContext));
172+
RETURN_IF_FAILED(LoadRequestHandlerAssembly(pApplication, shadowCopyPath, options, pApplicationFactory, errorContext));
172173

173174
return S_OK;
174175
}
@@ -181,6 +182,13 @@ void HandlerResolver::ResetHostingModel()
181182
m_loadedApplicationId.resize(0);
182183
}
183184

185+
APP_HOSTING_MODEL HandlerResolver::GetHostingModel()
186+
{
187+
SRWExclusiveLock lock(m_requestHandlerLoadLock);
188+
189+
return m_loadedApplicationHostingModel;
190+
}
191+
184192
HRESULT
185193
HandlerResolver::FindNativeAssemblyFromGlobalLocation(
186194
const ShimOptions& pConfiguration,

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ class HandlerResolver
1515
{
1616
public:
1717
HandlerResolver(HMODULE hModule, const IHttpServer &pServer);
18-
HRESULT GetApplicationFactory(const IHttpApplication &pApplication, std::unique_ptr<ApplicationFactory>& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext);
18+
HRESULT GetApplicationFactory(const IHttpApplication &pApplication, std::filesystem::path shadowCopyPath, std::unique_ptr<ApplicationFactory>& pApplicationFactory, const ShimOptions& options, ErrorContext& errorContext);
1919
void ResetHostingModel();
20+
APP_HOSTING_MODEL GetHostingModel();
2021

2122
private:
22-
HRESULT LoadRequestHandlerAssembly(const IHttpApplication &pApplication, const ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory, ErrorContext& errorContext);
23+
HRESULT LoadRequestHandlerAssembly(const IHttpApplication &pApplication, std::filesystem::path shadowCopyPath, const ShimOptions& pConfiguration, std::unique_ptr<ApplicationFactory>& pApplicationFactory, ErrorContext& errorContext);
2324
HRESULT FindNativeAssemblyFromGlobalLocation(const ShimOptions& pConfiguration, PCWSTR libraryName, std::wstring& handlerDllPath);
2425
HRESULT FindNativeAssemblyFromHostfxr(
2526
const HostFxrResolutionResult& hostfxrOptions,

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include "Environment.h"
99

1010
#define CS_ASPNETCORE_HANDLER_VERSION L"handlerVersion"
11+
#define CS_ASPNETCORE_SHADOW_COPY L"enableShadowCopy"
12+
#define CS_ASPNETCORE_SHADOW_COPY_DIRECTORY L"shadowCopyDirectory"
13+
#define CS_ASPNETCORE_CLEAN_SHADOW_DIRECTORY_CONTENT L"cleanShadowCopyDirectory"
1114

1215
ShimOptions::ShimOptions(const ConfigurationSource &configurationSource) :
1316
m_hostingModel(HOSTING_UNKNOWN),
@@ -31,12 +34,21 @@ ShimOptions::ShimOptions(const ConfigurationSource &configurationSource) :
3134
"or hostingModel=\"outofprocess\" in the web.config file.", hostingModel.c_str()));
3235
}
3336

37+
const auto handlerSettings = section->GetKeyValuePairs(CS_ASPNETCORE_HANDLER_SETTINGS);
38+
3439
if (m_hostingModel == HOSTING_OUT_PROCESS)
3540
{
36-
const auto handlerSettings = section->GetKeyValuePairs(CS_ASPNETCORE_HANDLER_SETTINGS);
3741
m_strHandlerVersion = find_element(handlerSettings, CS_ASPNETCORE_HANDLER_VERSION).value_or(std::wstring());
3842
}
3943

44+
auto enableShadowCopyElement = find_element(handlerSettings, CS_ASPNETCORE_SHADOW_COPY).value_or(std::wstring());
45+
m_fEnableShadowCopying = equals_ignore_case(L"true", enableShadowCopyElement);
46+
47+
auto cleanShadowCopyDirectory = find_element(handlerSettings, CS_ASPNETCORE_CLEAN_SHADOW_DIRECTORY_CONTENT).value_or(std::wstring());
48+
m_fCleanShadowCopyDirectory = equals_ignore_case(L"true", cleanShadowCopyDirectory);
49+
50+
m_strShadowCopyingDirectory = find_element(handlerSettings, CS_ASPNETCORE_SHADOW_COPY_DIRECTORY).value_or(std::wstring());
51+
4052
m_strProcessPath = section->GetRequiredString(CS_ASPNETCORE_PROCESS_EXE_PATH);
4153
m_strArguments = section->GetString(CS_ASPNETCORE_PROCESS_ARGUMENTS).value_or(CS_ASPNETCORE_PROCESS_ARGUMENTS_DEFAULT);
4254
m_fStdoutLogEnabled = section->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,24 @@ class ShimOptions: NonCopyable
6565
return m_fShowDetailedErrors;
6666
}
6767

68+
bool
69+
QueryShadowCopyEnabled() const noexcept
70+
{
71+
return m_fEnableShadowCopying;
72+
}
73+
74+
bool
75+
QueryCleanShadowCopyDirectory() const noexcept
76+
{
77+
return m_fCleanShadowCopyDirectory;
78+
}
79+
80+
const std::wstring&
81+
QueryShadowCopyDirectory() const noexcept
82+
{
83+
return m_strShadowCopyingDirectory;
84+
}
85+
6886
ShimOptions(const ConfigurationSource &configurationSource);
6987

7088
private:
@@ -76,4 +94,7 @@ class ShimOptions: NonCopyable
7694
bool m_fStdoutLogEnabled;
7795
bool m_fDisableStartupPage;
7896
bool m_fShowDetailedErrors;
97+
bool m_fEnableShadowCopying;
98+
bool m_fCleanShadowCopyDirectory;
99+
std::wstring m_strShadowCopyingDirectory;
79100
};

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.cpp

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "applicationinfo.h"
55

6+
#include "rpcdce.h"
7+
#include "Rpc.h"
68
#include "proxymodule.h"
79
#include "HostFxrResolver.h"
810
#include "debugutil.h"
@@ -18,6 +20,7 @@
1820
#include "file_utility.h"
1921

2022
extern HINSTANCE g_hServerModule;
23+
extern BOOL g_fInAppOfflineShutdown;
2124

2225
HRESULT
2326
APPLICATION_INFO::CreateHandler(
@@ -49,7 +52,6 @@ APPLICATION_INFO::CreateHandler(
4952
while (hr != S_OK)
5053
{
5154
// At this point application is either null or shutdown and is returning S_FALSE
52-
5355
if (m_pApplication != nullptr)
5456
{
5557
LOG_INFO(L"Application went offline");
@@ -80,6 +82,20 @@ APPLICATION_INFO::CreateApplication(IHttpContext& pHttpContext)
8082

8183
return S_OK;
8284
}
85+
86+
if (g_fInAppOfflineShutdown)
87+
{
88+
m_pApplication = make_application<ServerErrorApplication>(
89+
pHttpApplication,
90+
E_FAIL,
91+
false /* disableStartupPage */,
92+
"" /* responseContent */,
93+
503i16 /* statusCode */,
94+
0i16 /* subStatusCode */,
95+
"Application Shutting Down");
96+
return S_OK;
97+
}
98+
8399
try
84100
{
85101
const WebConfigConfigurationSource configurationSource(m_pServer.GetAdminManager(), pHttpApplication);
@@ -93,6 +109,7 @@ APPLICATION_INFO::CreateApplication(IHttpContext& pHttpContext)
93109

94110
if (FAILED_LOG(hr))
95111
{
112+
OBSERVE_CAUGHT_EXCEPTION();
96113
EventLog::Error(
97114
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR,
98115
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG,
@@ -175,13 +192,16 @@ APPLICATION_INFO::TryCreateApplication(IHttpContext& pHttpContext, const ShimOpt
175192
}
176193
}
177194

178-
RETURN_IF_FAILED(m_handlerResolver.GetApplicationFactory(*pHttpContext.GetApplication(), m_pApplicationFactory, options, error));
195+
std::filesystem::path shadowCopyPath = HandleShadowCopy(options, pHttpContext);
196+
197+
RETURN_IF_FAILED(m_handlerResolver.GetApplicationFactory(*pHttpContext.GetApplication(), shadowCopyPath, m_pApplicationFactory, options, error));
179198
LOG_INFO(L"Creating handler application");
180199

181200
IAPPLICATION * newApplication;
182201
RETURN_IF_FAILED(m_pApplicationFactory->Execute(
183202
&m_pServer,
184203
&pHttpContext,
204+
shadowCopyPath,
185205
&newApplication));
186206

187207
m_pApplication.reset(newApplication);
@@ -206,19 +226,92 @@ APPLICATION_INFO::TryCreateHandler(
206226
return S_OK;
207227
}
208228
}
229+
209230
return S_FALSE;
210231
}
211232

212233
VOID
213234
APPLICATION_INFO::ShutDownApplication(const bool fServerInitiated)
214235
{
236+
IAPPLICATION* app = nullptr;
237+
{
238+
SRWExclusiveLock lock(m_applicationLock);
239+
if (!m_pApplication)
240+
{
241+
return;
242+
}
243+
app = m_pApplication.get();
244+
}
245+
246+
LOG_INFOF(L"Stopping application '%ls'", QueryApplicationInfoKey().c_str());
247+
app->Stop(fServerInitiated);
248+
LOG_INFO(L"Setting app to null");
249+
215250
SRWExclusiveLock lock(m_applicationLock);
251+
LOG_INFO(L"lock acquired");
252+
253+
m_pApplication = nullptr;
254+
m_pApplicationFactory = nullptr;
255+
}
216256

217-
if (m_pApplication)
257+
std::wstring
258+
APPLICATION_INFO::HandleShadowCopy(const ShimOptions& options, IHttpContext& pHttpContext)
259+
{
260+
std::filesystem::path shadowCopyPath;
261+
262+
if (options.QueryShadowCopyEnabled())
218263
{
219-
LOG_INFOF(L"Stopping application '%ls'", QueryApplicationInfoKey().c_str());
220-
m_pApplication->Stop(fServerInitiated);
221-
m_pApplication = nullptr;
222-
m_pApplicationFactory = nullptr;
264+
shadowCopyPath = options.QueryShadowCopyDirectory();
265+
std::wstring physicalPath = pHttpContext.GetApplication()->GetApplicationPhysicalPath();
266+
267+
// Make shadow copy path absolute.
268+
if (!shadowCopyPath.is_absolute())
269+
{
270+
shadowCopyPath = std::filesystem::absolute(std::filesystem::path(physicalPath) / shadowCopyPath);
271+
}
272+
273+
// The shadow copy directory itself isn't copied to directly.
274+
// Instead subdirectories with numerically increasing names are created.
275+
// This is because on shutdown, the app itself will still have all dlls loaded,
276+
// meaning we can't copy to the same subdirectory. Therefore, on shutdown,
277+
// we create a directory that is one larger than the previous largest directory number.
278+
auto directoryName = 0;
279+
std::string directoryNameStr = "0";
280+
auto shadowCopyBaseDirectory = std::filesystem::directory_entry(shadowCopyPath);
281+
if (!shadowCopyBaseDirectory.exists())
282+
{
283+
CreateDirectory(shadowCopyBaseDirectory.path().wstring().c_str(), NULL);
284+
}
285+
286+
for (auto& entry : std::filesystem::directory_iterator(shadowCopyPath))
287+
{
288+
if (entry.is_directory())
289+
{
290+
try
291+
{
292+
std::string::size_type size;
293+
int intFileName = std::stoi(entry.path().filename().string(), &size);
294+
if (intFileName > directoryName)
295+
{
296+
directoryName = intFileName;
297+
directoryNameStr = std::string(entry.path().string());
298+
}
299+
}
300+
catch (...)
301+
{
302+
OBSERVE_CAUGHT_EXCEPTION();
303+
// Ignore any folders that can't be converted to an int.
304+
}
305+
}
306+
}
307+
308+
shadowCopyPath = shadowCopyPath / std::filesystem::path(directoryNameStr);
309+
HRESULT hr = Environment::CopyToDirectory(physicalPath, shadowCopyPath, options.QueryCleanShadowCopyDirectory(), shadowCopyBaseDirectory.path().parent_path());
310+
if (hr != S_OK)
311+
{
312+
return std::wstring();
313+
}
223314
}
315+
316+
return shadowCopyPath;
224317
}

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/applicationinfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class APPLICATION_INFO: NonCopyable
6666
return false;
6767
}
6868

69+
6970
private:
7071

7172
HRESULT
@@ -79,6 +80,9 @@ class APPLICATION_INFO: NonCopyable
7980
HRESULT
8081
TryCreateApplication(IHttpContext& pHttpContext, const ShimOptions& options, ErrorContext& error);
8182

83+
std::wstring
84+
HandleShadowCopy(const ShimOptions& options, IHttpContext& pHttpContext);
85+
8286
IHttpServer &m_pServer;
8387
HandlerResolver &m_handlerResolver;
8488

0 commit comments

Comments
 (0)