Adds in-process mode to ANCM. (#152)
This commit is contained in:
parent
5c2906a7c6
commit
2e540341db
|
|
@ -5,4 +5,4 @@
|
||||||
<TestSdkVersion>15.3.0-*</TestSdkVersion>
|
<TestSdkVersion>15.3.0-*</TestSdkVersion>
|
||||||
<XunitVersion>2.3.0-beta2-*</XunitVersion>
|
<XunitVersion>2.3.0-beta2-*</XunitVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="..\..\Build\Build.Settings" />
|
<Import Project="..\..\Build\Build.Settings" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
|
@ -26,32 +26,33 @@
|
||||||
<ProjectName>AspNetCore</ProjectName>
|
<ProjectName>AspNetCore</ProjectName>
|
||||||
<TargetName>aspnetcore</TargetName>
|
<TargetName>aspnetcore</TargetName>
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -153,6 +154,7 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Inc\aspnetcoreapplication.h" />
|
||||||
<ClInclude Include="Inc\resource.h" />
|
<ClInclude Include="Inc\resource.h" />
|
||||||
<ClInclude Include="Inc\application.h" />
|
<ClInclude Include="Inc\application.h" />
|
||||||
<ClInclude Include="Inc\applicationmanager.h" />
|
<ClInclude Include="Inc\applicationmanager.h" />
|
||||||
|
|
@ -171,9 +173,11 @@
|
||||||
<ClInclude Include="Inc\sttimer.h" />
|
<ClInclude Include="Inc\sttimer.h" />
|
||||||
<ClInclude Include="Inc\websockethandler.h" />
|
<ClInclude Include="Inc\websockethandler.h" />
|
||||||
<ClInclude Include="Inc\winhttphelper.h" />
|
<ClInclude Include="Inc\winhttphelper.h" />
|
||||||
|
<ClInclude Include="Inc\fx_ver.h" />
|
||||||
<ClInclude Include="Src\precomp.hxx" />
|
<ClInclude Include="Src\precomp.hxx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Src\aspnetcoreapplication.cxx" />
|
||||||
<ClCompile Include="Src\application.cxx" />
|
<ClCompile Include="Src\application.cxx" />
|
||||||
<ClCompile Include="Src\applicationmanager.cxx" />
|
<ClCompile Include="Src\applicationmanager.cxx" />
|
||||||
<ClCompile Include="Src\aspnetcoreconfig.cxx" />
|
<ClCompile Include="Src\aspnetcoreconfig.cxx" />
|
||||||
|
|
@ -181,6 +185,7 @@
|
||||||
<ClCompile Include="Src\filewatcher.cxx" />
|
<ClCompile Include="Src\filewatcher.cxx" />
|
||||||
<ClCompile Include="Src\forwarderconnection.cxx" />
|
<ClCompile Include="Src\forwarderconnection.cxx" />
|
||||||
<ClCompile Include="Src\forwardinghandler.cxx" />
|
<ClCompile Include="Src\forwardinghandler.cxx" />
|
||||||
|
<ClCompile Include="Src\fx_ver.cxx" />
|
||||||
<ClCompile Include="Src\path.cxx" />
|
<ClCompile Include="Src\path.cxx" />
|
||||||
<ClCompile Include="Src\processmanager.cxx" />
|
<ClCompile Include="Src\processmanager.cxx" />
|
||||||
<ClCompile Include="Src\protocolconfig.cxx" />
|
<ClCompile Include="Src\protocolconfig.cxx" />
|
||||||
|
|
|
||||||
|
|
@ -147,8 +147,10 @@ class APPLICATION
|
||||||
public:
|
public:
|
||||||
|
|
||||||
APPLICATION() : m_pProcessManager(NULL), m_pApplicationManager(NULL), m_cRefs(1),
|
APPLICATION() : m_pProcessManager(NULL), m_pApplicationManager(NULL), m_cRefs(1),
|
||||||
m_fAppOfflineFound(FALSE), m_pAppOfflineHtm(NULL), m_pFileWatcherEntry(NULL)
|
m_fAppOfflineFound(FALSE), m_pAppOfflineHtm(NULL), m_pFileWatcherEntry(NULL),
|
||||||
|
m_pAspNetCoreApplication(NULL)
|
||||||
{
|
{
|
||||||
|
InitializeSRWLock(&m_srwLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
APPLICATION_KEY *
|
APPLICATION_KEY *
|
||||||
|
|
@ -181,6 +183,61 @@ public:
|
||||||
return m_pProcessManager->GetProcess( context, pConfig, ppServerProcess );
|
return m_pProcessManager->GetProcess( context, pConfig, ppServerProcess );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
GetAspNetCoreApplication(
|
||||||
|
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||||
|
_In_ IHttpContext *context,
|
||||||
|
_Out_ ASPNETCORE_APPLICATION **ppAspNetCoreApplication
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
BOOL fLockTaken = FALSE;
|
||||||
|
ASPNETCORE_APPLICATION *application;
|
||||||
|
IHttpApplication *pHttpApplication = context->GetApplication();
|
||||||
|
|
||||||
|
if (m_pAspNetCoreApplication == NULL)
|
||||||
|
{
|
||||||
|
AcquireSRWLockExclusive(&m_srwLock);
|
||||||
|
fLockTaken = TRUE;
|
||||||
|
|
||||||
|
if (m_pAspNetCoreApplication == NULL)
|
||||||
|
{
|
||||||
|
application = new ASPNETCORE_APPLICATION();
|
||||||
|
if (application == NULL) {
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = application->Initialize(pConfig);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign after initialization
|
||||||
|
m_pAspNetCoreApplication = application;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pHttpApplication->GetModuleContextContainer()->GetModuleContext(g_pModuleId) == NULL)
|
||||||
|
{
|
||||||
|
// This means that we are trying to load a second application
|
||||||
|
// TODO set a flag saying that the whole app pool is invalid '
|
||||||
|
// (including the running application) and return 500 every request.
|
||||||
|
hr = E_FAIL;
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppAspNetCoreApplication = m_pAspNetCoreApplication;
|
||||||
|
|
||||||
|
Finished:
|
||||||
|
if (fLockTaken)
|
||||||
|
{
|
||||||
|
ReleaseSRWLockExclusive(&m_srwLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
Recycle()
|
Recycle()
|
||||||
{
|
{
|
||||||
|
|
@ -226,14 +283,16 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
STRU m_strAppPhysicalPath;
|
STRU m_strAppPhysicalPath;
|
||||||
mutable LONG m_cRefs;
|
mutable LONG m_cRefs;
|
||||||
APPLICATION_KEY m_applicationKey;
|
APPLICATION_KEY m_applicationKey;
|
||||||
PROCESS_MANAGER* m_pProcessManager;
|
PROCESS_MANAGER* m_pProcessManager;
|
||||||
APPLICATION_MANAGER *m_pApplicationManager;
|
APPLICATION_MANAGER *m_pApplicationManager;
|
||||||
BOOL m_fAppOfflineFound;
|
BOOL m_fAppOfflineFound;
|
||||||
APP_OFFLINE_HTM *m_pAppOfflineHtm;
|
APP_OFFLINE_HTM *m_pAppOfflineHtm;
|
||||||
FILE_WATCHER_ENTRY *m_pFileWatcherEntry;
|
FILE_WATCHER_ENTRY *m_pFileWatcherEntry;
|
||||||
|
ASPNETCORE_APPLICATION *m_pAspNetCoreApplication;
|
||||||
|
SRWLOCK m_srwLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class APPLICATION_HASH :
|
class APPLICATION_HASH :
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class APPLICATION_MANAGER
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static
|
static
|
||||||
APPLICATION_MANAGER*
|
APPLICATION_MANAGER*
|
||||||
GetInstance(
|
GetInstance(
|
||||||
VOID
|
VOID
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef void(*request_handler_cb) (int error, IHttpContext* pHttpContext, void* pvCompletionContext);
|
||||||
|
typedef REQUEST_NOTIFICATION_STATUS(*PFN_REQUEST_HANDLER) (IHttpContext* pHttpContext, void* pvRequstHandlerContext);
|
||||||
|
typedef BOOL(*PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext);
|
||||||
|
|
||||||
|
class ASPNETCORE_APPLICATION
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ASPNETCORE_APPLICATION():
|
||||||
|
m_pConfiguration(NULL),
|
||||||
|
m_RequestHandler(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ASPNETCORE_APPLICATION()
|
||||||
|
{
|
||||||
|
if (m_hThread != NULL)
|
||||||
|
{
|
||||||
|
CloseHandle(m_hThread);
|
||||||
|
m_hThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_pInitalizeEvent != NULL)
|
||||||
|
{
|
||||||
|
CloseHandle(m_pInitalizeEvent);
|
||||||
|
m_pInitalizeEvent = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
Initialize(
|
||||||
|
_In_ ASPNETCORE_CONFIG* pConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
REQUEST_NOTIFICATION_STATUS
|
||||||
|
ExecuteRequest(
|
||||||
|
_In_ IHttpContext* pHttpContext
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
Shutdown(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
SetCallbackHandles(
|
||||||
|
_In_ PFN_REQUEST_HANDLER request_callback,
|
||||||
|
_In_ PFN_SHUTDOWN_HANDLER shutdown_callback,
|
||||||
|
_In_ VOID* pvRequstHandlerContext,
|
||||||
|
_In_ VOID* pvShutdownHandlerContext
|
||||||
|
);
|
||||||
|
|
||||||
|
// Executes the .NET Core process
|
||||||
|
HRESULT
|
||||||
|
ExecuteApplication(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
ASPNETCORE_CONFIG*
|
||||||
|
GetConfig(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return m_pConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ASPNETCORE_APPLICATION*
|
||||||
|
GetInstance(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return s_Application;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Thread executing the .NET Core process
|
||||||
|
HANDLE m_hThread;
|
||||||
|
|
||||||
|
// Configuration for this application
|
||||||
|
ASPNETCORE_CONFIG* m_pConfiguration;
|
||||||
|
|
||||||
|
// The request handler callback from managed code
|
||||||
|
PFN_REQUEST_HANDLER m_RequestHandler;
|
||||||
|
VOID* m_RequstHandlerContext;
|
||||||
|
|
||||||
|
// The shutdown handler callback from managed code
|
||||||
|
PFN_SHUTDOWN_HANDLER m_ShutdownHandler;
|
||||||
|
VOID* m_ShutdownHandlerContext;
|
||||||
|
|
||||||
|
// The event that gets triggered when managed initialization is complete
|
||||||
|
HANDLE m_pInitalizeEvent;
|
||||||
|
|
||||||
|
// The exit code of the .NET Core process
|
||||||
|
INT m_ProcessExitCode;
|
||||||
|
|
||||||
|
static ASPNETCORE_APPLICATION* s_Application;
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
FindDotNetFolders(
|
||||||
|
_In_ STRU *pstrPath,
|
||||||
|
_Out_ std::vector<std::wstring> *pvFolders
|
||||||
|
);
|
||||||
|
|
||||||
|
static HRESULT
|
||||||
|
FindHighestDotNetVersion(
|
||||||
|
_In_ std::vector<std::wstring> vFolders,
|
||||||
|
_Out_ STRU *pstrResult
|
||||||
|
);
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
DirectoryExists(
|
||||||
|
_In_ STRU *pstrPath
|
||||||
|
);
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
GetEnv(
|
||||||
|
_In_ PCWSTR pszEnvironmentVariable,
|
||||||
|
_Out_ STRU *pstrResult
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE L"recycleOnFileChange"
|
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE L"recycleOnFileChange"
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE L"file"
|
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE L"file"
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE_PATH L"path"
|
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE_PATH L"path"
|
||||||
|
#define CS_ASPNETCORE_HOSTING_MODEL L"hostingModel"
|
||||||
|
|
||||||
#define MAX_RAPID_FAILS_PER_MINUTE 100
|
#define MAX_RAPID_FAILS_PER_MINUTE 100
|
||||||
#define MILLISECONDS_IN_ONE_SECOND 1000
|
#define MILLISECONDS_IN_ONE_SECOND 1000
|
||||||
|
|
@ -57,7 +58,7 @@ public:
|
||||||
_In_ IHttpContext *pHttpContext,
|
_In_ IHttpContext *pHttpContext,
|
||||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
ENVIRONMENT_VAR_HASH*
|
ENVIRONMENT_VAR_HASH*
|
||||||
QueryEnvironmentVariables(
|
QueryEnvironmentVariables(
|
||||||
VOID
|
VOID
|
||||||
|
|
@ -117,11 +118,19 @@ public:
|
||||||
STRU*
|
STRU*
|
||||||
QueryApplicationPath(
|
QueryApplicationPath(
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return &m_struApplication;
|
return &m_struApplication;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRU*
|
||||||
|
QueryApplicationFullPath(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return &m_struApplicationFullPath;
|
||||||
|
}
|
||||||
|
|
||||||
STRU*
|
STRU*
|
||||||
QueryProcessPath(
|
QueryProcessPath(
|
||||||
VOID
|
VOID
|
||||||
|
|
@ -166,6 +175,19 @@ public:
|
||||||
return m_fDisableStartUpErrorPage;
|
return m_fDisableStartUpErrorPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
QueryIsInProcess()
|
||||||
|
{
|
||||||
|
return m_fIsInProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
QueryIsOutOfProcess()
|
||||||
|
{
|
||||||
|
return m_fIsOutOfProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
STRU*
|
STRU*
|
||||||
QueryStdoutLogFile()
|
QueryStdoutLogFile()
|
||||||
{
|
{
|
||||||
|
|
@ -197,11 +219,14 @@ private:
|
||||||
STRU m_struArguments;
|
STRU m_struArguments;
|
||||||
STRU m_struProcessPath;
|
STRU m_struProcessPath;
|
||||||
STRU m_struStdoutLogFile;
|
STRU m_struStdoutLogFile;
|
||||||
|
STRU m_struApplicationFullPath;
|
||||||
BOOL m_fStdoutLogEnabled;
|
BOOL m_fStdoutLogEnabled;
|
||||||
BOOL m_fForwardWindowsAuthToken;
|
BOOL m_fForwardWindowsAuthToken;
|
||||||
BOOL m_fDisableStartUpErrorPage;
|
BOOL m_fDisableStartUpErrorPage;
|
||||||
BOOL m_fWindowsAuthEnabled;
|
BOOL m_fWindowsAuthEnabled;
|
||||||
BOOL m_fBasicAuthEnabled;
|
BOOL m_fBasicAuthEnabled;
|
||||||
BOOL m_fAnonymousAuthEnabled;
|
BOOL m_fAnonymousAuthEnabled;
|
||||||
|
BOOL m_fIsInProcess;
|
||||||
|
BOOL m_fIsOutOfProcess;
|
||||||
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
#ifndef __FX_VER_H__
|
||||||
|
#define __FX_VER_H__
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Note: This is not SemVer (esp., in comparing pre-release part, fx_ver_t does not
|
||||||
|
// compare multiple dot separated identifiers individually.) ex: 1.0.0-beta.2 vs. 1.0.0-beta.11
|
||||||
|
struct fx_ver_t
|
||||||
|
{
|
||||||
|
fx_ver_t(int major, int minor, int patch);
|
||||||
|
fx_ver_t(int major, int minor, int patch, const std::wstring& pre);
|
||||||
|
fx_ver_t(int major, int minor, int patch, const std::wstring& pre, const std::wstring& build);
|
||||||
|
|
||||||
|
int get_major() const { return m_major; }
|
||||||
|
int get_minor() const { return m_minor; }
|
||||||
|
int get_patch() const { return m_patch; }
|
||||||
|
|
||||||
|
void set_major(int m) { m_major = m; }
|
||||||
|
void set_minor(int m) { m_minor = m; }
|
||||||
|
void set_patch(int p) { m_patch = p; }
|
||||||
|
|
||||||
|
bool is_prerelease() const { return !m_pre.empty(); }
|
||||||
|
|
||||||
|
std::wstring as_str() const;
|
||||||
|
std::wstring prerelease_glob() const;
|
||||||
|
std::wstring patch_glob() const;
|
||||||
|
|
||||||
|
bool operator ==(const fx_ver_t& b) const;
|
||||||
|
bool operator !=(const fx_ver_t& b) const;
|
||||||
|
bool operator <(const fx_ver_t& b) const;
|
||||||
|
bool operator >(const fx_ver_t& b) const;
|
||||||
|
bool operator <=(const fx_ver_t& b) const;
|
||||||
|
bool operator >=(const fx_ver_t& b) const;
|
||||||
|
|
||||||
|
static bool parse(const std::wstring& ver, fx_ver_t* fx_ver, bool parse_only_production = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_major;
|
||||||
|
int m_minor;
|
||||||
|
int m_patch;
|
||||||
|
std::wstring m_pre;
|
||||||
|
std::wstring m_build;
|
||||||
|
|
||||||
|
static int compare(const fx_ver_t&a, const fx_ver_t& b);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __FX_VER_H__
|
||||||
|
|
@ -0,0 +1,601 @@
|
||||||
|
#include "precomp.hxx"
|
||||||
|
#include "fx_ver.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
typedef DWORD(*hostfxr_main_fn) (CONST DWORD argc, CONST WCHAR* argv[]);
|
||||||
|
|
||||||
|
// Initialization export
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
VOID
|
||||||
|
register_callbacks(
|
||||||
|
_In_ PFN_REQUEST_HANDLER request_handler,
|
||||||
|
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
|
||||||
|
_In_ VOID* pvRequstHandlerContext,
|
||||||
|
_In_ VOID* pvShutdownHandlerContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASPNETCORE_APPLICATION::GetInstance()->SetCallbackHandles(
|
||||||
|
request_handler,
|
||||||
|
shutdown_handler,
|
||||||
|
pvRequstHandlerContext,
|
||||||
|
pvShutdownHandlerContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HTTP_REQUEST*
|
||||||
|
http_get_raw_request(
|
||||||
|
_In_ IHttpContext* pHttpContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return pHttpContext->GetRequest()->GetRawHttpRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HTTP_RESPONSE*
|
||||||
|
http_get_raw_response(
|
||||||
|
_In_ IHttpContext* pHttpContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return pHttpContext->GetResponse()->GetRawHttpResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT VOID http_set_response_status_code(
|
||||||
|
_In_ IHttpContext* pHttpContext,
|
||||||
|
_In_ USHORT statusCode,
|
||||||
|
_In_ PCSTR pszReason
|
||||||
|
)
|
||||||
|
{
|
||||||
|
pHttpContext->GetResponse()->SetStatus(statusCode, pszReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HRESULT
|
||||||
|
http_post_completion(
|
||||||
|
_In_ IHttpContext* pHttpContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return pHttpContext->PostCompletion(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
VOID
|
||||||
|
http_indicate_completion(
|
||||||
|
_In_ IHttpContext* pHttpContext,
|
||||||
|
_In_ REQUEST_NOTIFICATION_STATUS notificationStatus
|
||||||
|
)
|
||||||
|
{
|
||||||
|
pHttpContext->IndicateCompletion(notificationStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
VOID
|
||||||
|
http_get_completion_info(
|
||||||
|
_In_ IHttpCompletionInfo2* info,
|
||||||
|
_Out_ DWORD* cbBytes,
|
||||||
|
_Out_ HRESULT* hr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*cbBytes = info->GetCompletionBytes();
|
||||||
|
*hr = info->GetCompletionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
BSTR // TODO probably should make this a wide string
|
||||||
|
http_get_application_full_path()
|
||||||
|
{
|
||||||
|
return SysAllocString(ASPNETCORE_APPLICATION::GetInstance()->GetConfig()->QueryApplicationFullPath()->QueryStr());
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HRESULT
|
||||||
|
http_read_request_bytes(
|
||||||
|
_In_ IHttpContext* pHttpContext,
|
||||||
|
_In_ CHAR* pvBuffer,
|
||||||
|
_In_ DWORD cbBuffer,
|
||||||
|
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||||
|
_In_ VOID* pvCompletionContext,
|
||||||
|
_In_ DWORD* pDwBytesReceived,
|
||||||
|
_In_ BOOL* pfCompletionPending
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IHttpRequest3 *pHttpRequest = (IHttpRequest3*)pHttpContext->GetRequest();
|
||||||
|
|
||||||
|
BOOL fAsync = TRUE;
|
||||||
|
|
||||||
|
HRESULT hr = pHttpRequest->ReadEntityBody(
|
||||||
|
pvBuffer,
|
||||||
|
cbBuffer,
|
||||||
|
fAsync,
|
||||||
|
pfnCompletionCallback,
|
||||||
|
pvCompletionContext,
|
||||||
|
pDwBytesReceived,
|
||||||
|
pfCompletionPending);
|
||||||
|
|
||||||
|
if (hr == HRESULT_FROM_WIN32(ERROR_HANDLE_EOF))
|
||||||
|
{
|
||||||
|
// We reached the end of the data
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HRESULT
|
||||||
|
http_write_response_bytes(
|
||||||
|
_In_ IHttpContext* pHttpContext,
|
||||||
|
_In_ HTTP_DATA_CHUNK* pDataChunks,
|
||||||
|
_In_ DWORD nChunks,
|
||||||
|
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||||
|
_In_ VOID* pvCompletionContext,
|
||||||
|
_In_ BOOL* pfCompletionExpected
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pHttpContext->GetResponse();
|
||||||
|
|
||||||
|
BOOL fAsync = TRUE;
|
||||||
|
BOOL fMoreData = TRUE;
|
||||||
|
DWORD dwBytesSent;
|
||||||
|
|
||||||
|
HRESULT hr = pHttpResponse->WriteEntityChunks(
|
||||||
|
pDataChunks,
|
||||||
|
nChunks,
|
||||||
|
fAsync,
|
||||||
|
fMoreData,
|
||||||
|
pfnCompletionCallback,
|
||||||
|
pvCompletionContext,
|
||||||
|
&dwBytesSent,
|
||||||
|
pfCompletionExpected);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HRESULT
|
||||||
|
http_flush_response_bytes(
|
||||||
|
_In_ IHttpContext* pHttpContext,
|
||||||
|
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||||
|
_In_ VOID* pvCompletionContext,
|
||||||
|
_In_ BOOL* pfCompletionExpected
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pHttpContext->GetResponse();
|
||||||
|
|
||||||
|
BOOL fAsync = TRUE;
|
||||||
|
BOOL fMoreData = TRUE;
|
||||||
|
DWORD dwBytesSent;
|
||||||
|
|
||||||
|
HRESULT hr = pHttpResponse->Flush(
|
||||||
|
fAsync,
|
||||||
|
fMoreData,
|
||||||
|
pfnCompletionCallback,
|
||||||
|
pvCompletionContext,
|
||||||
|
&dwBytesSent,
|
||||||
|
pfCompletionExpected);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thread execution callback
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
ExecuteAspNetCoreProcess(
|
||||||
|
_In_ LPVOID pContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ASPNETCORE_APPLICATION *pApplication = (ASPNETCORE_APPLICATION*)pContext;
|
||||||
|
|
||||||
|
hr = pApplication->ExecuteApplication();
|
||||||
|
if (hr != S_OK)
|
||||||
|
{
|
||||||
|
// TODO log error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASPNETCORE_APPLICATION*
|
||||||
|
ASPNETCORE_APPLICATION::s_Application = NULL;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ASPNETCORE_APPLICATION::SetCallbackHandles(
|
||||||
|
_In_ PFN_REQUEST_HANDLER request_handler,
|
||||||
|
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
|
||||||
|
_In_ VOID* pvRequstHandlerContext,
|
||||||
|
_In_ VOID* pvShutdownHandlerContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_RequestHandler = request_handler;
|
||||||
|
m_RequstHandlerContext = pvRequstHandlerContext;
|
||||||
|
m_ShutdownHandler = shutdown_handler;
|
||||||
|
m_ShutdownHandlerContext = pvShutdownHandlerContext;
|
||||||
|
|
||||||
|
// Initialization complete
|
||||||
|
SetEvent(m_pInitalizeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
ASPNETCORE_APPLICATION::Initialize(
|
||||||
|
_In_ ASPNETCORE_CONFIG * pConfig
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
DWORD dwTimeout;
|
||||||
|
DWORD dwResult;
|
||||||
|
DBG_ASSERT(pConfig != NULL);
|
||||||
|
|
||||||
|
m_pConfiguration = pConfig;
|
||||||
|
|
||||||
|
m_pInitalizeEvent = CreateEvent(
|
||||||
|
NULL, // default security attributes
|
||||||
|
TRUE, // manual reset event
|
||||||
|
FALSE, // not set
|
||||||
|
NULL); // name
|
||||||
|
|
||||||
|
if (m_pInitalizeEvent == NULL)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hThread = CreateThread(
|
||||||
|
NULL, // default security attributes
|
||||||
|
0, // default stack size
|
||||||
|
(LPTHREAD_START_ROUTINE)ExecuteAspNetCoreProcess,
|
||||||
|
this, // thread function arguments
|
||||||
|
0, // default creation flags
|
||||||
|
NULL); // receive thread identifier
|
||||||
|
|
||||||
|
if (m_hThread == NULL)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the debugger is attached, never timeout
|
||||||
|
if (IsDebuggerPresent())
|
||||||
|
{
|
||||||
|
dwTimeout = INFINITE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwTimeout = pConfig->QueryStartupTimeLimitInMS();
|
||||||
|
}
|
||||||
|
|
||||||
|
const HANDLE pHandles[2]{ m_hThread, m_pInitalizeEvent };
|
||||||
|
|
||||||
|
// Wait on either the thread to complete or the event to be set
|
||||||
|
dwResult = WaitForMultipleObjects(2, pHandles, FALSE, dwTimeout);
|
||||||
|
|
||||||
|
// It all timed out
|
||||||
|
if (dwResult == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(dwResult);
|
||||||
|
}
|
||||||
|
else if (dwResult == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
dwResult = WaitForSingleObject(m_hThread, 0);
|
||||||
|
|
||||||
|
// The thread ended it means that something failed
|
||||||
|
if (dwResult == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(dwResult);
|
||||||
|
}
|
||||||
|
else if (dwResult == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
ASPNETCORE_APPLICATION::ExecuteApplication(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
STRU strFullPath;
|
||||||
|
STRU strDotnetExeLocation;
|
||||||
|
STRU strHostFxrSearchExpression;
|
||||||
|
STRU strDotnetFolderLocation;
|
||||||
|
STRU strHighestDotnetVersion;
|
||||||
|
STRU strApplicationFullPath;
|
||||||
|
PWSTR strDelimeterContext = NULL;
|
||||||
|
PCWSTR pszDotnetExeLocation = NULL;
|
||||||
|
PCWSTR pszDotnetExeString(L"dotnet.exe");
|
||||||
|
DWORD dwCopyLength;
|
||||||
|
HMODULE hModule;
|
||||||
|
PCWSTR argv[2];
|
||||||
|
hostfxr_main_fn pProc;
|
||||||
|
std::vector<std::wstring> vVersionFolders;
|
||||||
|
|
||||||
|
// Get the System PATH value.
|
||||||
|
if (!GetEnv(L"PATH", &strFullPath))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split on ';', checking to see if dotnet.exe exists in any folders.
|
||||||
|
pszDotnetExeLocation = wcstok_s(strFullPath.QueryStr(), L";", &strDelimeterContext);
|
||||||
|
|
||||||
|
while (pszDotnetExeLocation != NULL)
|
||||||
|
{
|
||||||
|
dwCopyLength = wcsnlen_s(pszDotnetExeLocation, 260);
|
||||||
|
if (dwCopyLength == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We store both the exe and folder locations as we eventually need to check inside of host\\fxr
|
||||||
|
// which doesn't need the dotnet.exe portion of the string
|
||||||
|
// TODO consider reducing allocations.
|
||||||
|
strDotnetExeLocation.Reset();
|
||||||
|
strDotnetFolderLocation.Reset();
|
||||||
|
hr = strDotnetExeLocation.Copy(pszDotnetExeLocation, dwCopyLength);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strDotnetFolderLocation.Copy(pszDotnetExeLocation, dwCopyLength);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwCopyLength > 0 && pszDotnetExeLocation[dwCopyLength - 1] != L'\\')
|
||||||
|
{
|
||||||
|
hr = strDotnetExeLocation.Append(L"\\");
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strDotnetExeLocation.Append(pszDotnetExeString);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PathFileExists(strDotnetExeLocation.QueryStr()))
|
||||||
|
{
|
||||||
|
// means we found the folder with a dotnet.exe inside of it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pszDotnetExeLocation = wcstok_s(NULL, L";", &strDelimeterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strDotnetFolderLocation.Append(L"\\host\\fxr");
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DirectoryExists(&strDotnetFolderLocation))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all folders under host\\fxr\\ for version numbers.
|
||||||
|
hr = strHostFxrSearchExpression.Copy(strDotnetFolderLocation);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strHostFxrSearchExpression.Append(L"\\*");
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// As we use the logic from core-setup, we are opting to use std here.
|
||||||
|
// TODO remove all uses of std?
|
||||||
|
FindDotNetFolders(&strHostFxrSearchExpression, &vVersionFolders);
|
||||||
|
|
||||||
|
if (vVersionFolders.size() == 0)
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = FindHighestDotNetVersion(vVersionFolders, &strHighestDotnetVersion);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
hr = strDotnetFolderLocation.Append(L"\\");
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strDotnetFolderLocation.Append(strHighestDotnetVersion.QueryStr());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = strDotnetFolderLocation.Append(L"\\hostfxr.dll");
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hModule = LoadLibraryW(strDotnetFolderLocation.QueryStr());
|
||||||
|
|
||||||
|
if (hModule == NULL)
|
||||||
|
{
|
||||||
|
// .NET Core not installed (we can log a more detailed error message here)
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the entry point for main
|
||||||
|
pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main");
|
||||||
|
if (pProc == NULL) {
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first argument is mostly ignored
|
||||||
|
hr = strDotnetExeLocation.Append(pszDotnetExeString);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[0] = strDotnetExeLocation.QueryStr();
|
||||||
|
PATH::ConvertPathToFullPath(m_pConfiguration->QueryArguments()->QueryStr(), m_pConfiguration->QueryApplicationFullPath()->QueryStr(), &strApplicationFullPath);
|
||||||
|
argv[1] = strApplicationFullPath.QueryStr();
|
||||||
|
|
||||||
|
// There can only ever be a single instance of .NET Core
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// We set a static so that managed code can call back into this instance and
|
||||||
|
// set the callbacks
|
||||||
|
s_Application = this;
|
||||||
|
|
||||||
|
m_ProcessExitCode = pProc(2, argv);
|
||||||
|
if (m_ProcessExitCode != 0)
|
||||||
|
{
|
||||||
|
// TODO error
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
Failed:
|
||||||
|
// TODO log any errors
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
ASPNETCORE_APPLICATION::GetEnv(
|
||||||
|
_In_ PCWSTR pszEnvironmentVariable,
|
||||||
|
_Out_ STRU *pstrResult
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DWORD dwLength;
|
||||||
|
PWSTR pszBuffer= NULL;
|
||||||
|
BOOL fSucceeded = FALSE;
|
||||||
|
|
||||||
|
if (pszEnvironmentVariable == NULL)
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
pstrResult->Reset();
|
||||||
|
dwLength = GetEnvironmentVariableW(pszEnvironmentVariable, NULL, 0);
|
||||||
|
|
||||||
|
if (dwLength == 0)
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
pszBuffer = new WCHAR[dwLength];
|
||||||
|
if (GetEnvironmentVariableW(pszEnvironmentVariable, pszBuffer, dwLength) == 0)
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstrResult->Copy(pszBuffer);
|
||||||
|
|
||||||
|
fSucceeded = TRUE;
|
||||||
|
|
||||||
|
Finished:
|
||||||
|
if (pszBuffer != NULL) {
|
||||||
|
delete[] pszBuffer;
|
||||||
|
}
|
||||||
|
return fSucceeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ASPNETCORE_APPLICATION::FindDotNetFolders(
|
||||||
|
_In_ STRU *pstrPath,
|
||||||
|
_Out_ std::vector<std::wstring> *pvFolders
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HANDLE handle = NULL;
|
||||||
|
WIN32_FIND_DATAW data = { 0 };
|
||||||
|
|
||||||
|
handle = FindFirstFileExW(pstrPath->QueryStr(), FindExInfoStandard, &data, FindExSearchNameMatch, NULL, 0);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::wstring folder(data.cFileName);
|
||||||
|
pvFolders->push_back(folder);
|
||||||
|
} while (FindNextFileW(handle, &data));
|
||||||
|
|
||||||
|
FindClose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
ASPNETCORE_APPLICATION::FindHighestDotNetVersion(
|
||||||
|
_In_ std::vector<std::wstring> vFolders,
|
||||||
|
_Out_ STRU *pstrResult
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
fx_ver_t max_ver(-1, -1, -1);
|
||||||
|
for (const auto& dir : vFolders)
|
||||||
|
{
|
||||||
|
fx_ver_t fx_ver(-1, -1, -1);
|
||||||
|
if (fx_ver_t::parse(dir, &fx_ver, false))
|
||||||
|
{
|
||||||
|
max_ver = std::max(max_ver, fx_ver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pstrResult->Copy(max_ver.as_str().c_str());
|
||||||
|
|
||||||
|
// we check FAILED(hr) outside of function
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
ASPNETCORE_APPLICATION::DirectoryExists(
|
||||||
|
_In_ STRU *pstrPath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||||
|
|
||||||
|
if (pstrPath->IsEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetFileAttributesExW(pstrPath->QueryStr(), GetFileExInfoStandard, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUEST_NOTIFICATION_STATUS
|
||||||
|
ASPNETCORE_APPLICATION::ExecuteRequest(
|
||||||
|
_In_ IHttpContext* pHttpContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (m_RequestHandler != NULL)
|
||||||
|
{
|
||||||
|
return m_RequestHandler(pHttpContext, m_RequstHandlerContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||||
|
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ASPNETCORE_APPLICATION::Shutdown(
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// First call into the managed server and shutdown
|
||||||
|
BOOL result = m_ShutdownHandler(m_ShutdownHandlerContext);
|
||||||
|
s_Application = NULL;
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
@ -8,11 +8,16 @@ ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
||||||
//
|
//
|
||||||
// the destructor will be called once IIS decides to recycle the module context (i.e., application)
|
// the destructor will be called once IIS decides to recycle the module context (i.e., application)
|
||||||
//
|
//
|
||||||
|
// shutting down core application first
|
||||||
|
if (ASPNETCORE_APPLICATION::GetInstance() != NULL) {
|
||||||
|
ASPNETCORE_APPLICATION::GetInstance()->Shutdown();
|
||||||
|
}
|
||||||
|
m_struApplicationFullPath.Reset();
|
||||||
if (!m_struApplication.IsEmpty())
|
if (!m_struApplication.IsEmpty())
|
||||||
{
|
{
|
||||||
APPLICATION_MANAGER::GetInstance()->RecycleApplication(m_struApplication.QueryStr());
|
APPLICATION_MANAGER::GetInstance()->RecycleApplication(m_struApplication.QueryStr());
|
||||||
}
|
}
|
||||||
if(m_pEnvironmentVariables != NULL)
|
if (m_pEnvironmentVariables != NULL)
|
||||||
{
|
{
|
||||||
m_pEnvironmentVariables->Clear();
|
m_pEnvironmentVariables->Clear();
|
||||||
delete m_pEnvironmentVariables;
|
delete m_pEnvironmentVariables;
|
||||||
|
|
@ -86,7 +91,7 @@ ASPNETCORE_CONFIG::GetConfig(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// set appliction info here instead of inside Populate()
|
// set appliction info here instead of inside Populate()
|
||||||
// as the destructor will delete the backend process
|
// as the destructor will delete the backend process
|
||||||
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -118,6 +123,8 @@ ASPNETCORE_CONFIG::Populate(
|
||||||
STRU strEnvName;
|
STRU strEnvName;
|
||||||
STRU strEnvValue;
|
STRU strEnvValue;
|
||||||
STRU strExpandedEnvValue;
|
STRU strExpandedEnvValue;
|
||||||
|
STRU strApplicationFullPath;
|
||||||
|
STRU strHostingModel;
|
||||||
IAppHostAdminManager *pAdminManager = NULL;
|
IAppHostAdminManager *pAdminManager = NULL;
|
||||||
IAppHostElement *pAspNetCoreElement = NULL;
|
IAppHostElement *pAspNetCoreElement = NULL;
|
||||||
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
||||||
|
|
@ -144,13 +151,18 @@ ASPNETCORE_CONFIG::Populate(
|
||||||
}
|
}
|
||||||
|
|
||||||
pAdminManager = g_pHttpServer->GetAdminManager();
|
pAdminManager = g_pHttpServer->GetAdminManager();
|
||||||
|
|
||||||
hr = strSiteConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
hr = strSiteConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = m_struApplicationFullPath.Copy(pHttpContext->GetApplication()->GetApplicationPhysicalPath());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
hr = pAdminManager->GetAdminSection(CS_WINDOWS_AUTHENTICATION_SECTION,
|
hr = pAdminManager->GetAdminSection(CS_WINDOWS_AUTHENTICATION_SECTION,
|
||||||
strSiteConfigPath.QueryStr(),
|
strSiteConfigPath.QueryStr(),
|
||||||
&pWindowsAuthenticationElement);
|
&pWindowsAuthenticationElement);
|
||||||
|
|
@ -224,6 +236,23 @@ ASPNETCORE_CONFIG::Populate(
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||||
|
CS_ASPNETCORE_HOSTING_MODEL,
|
||||||
|
&strHostingModel);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strHostingModel.IsEmpty() || strHostingModel.Equals(L"outofprocess", TRUE))
|
||||||
|
{
|
||||||
|
m_fIsOutOfProcess = TRUE;
|
||||||
|
}
|
||||||
|
else if (strHostingModel.Equals(L"inprocess", TRUE))
|
||||||
|
{
|
||||||
|
m_fIsInProcess = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||||
CS_ASPNETCORE_PROCESS_ARGUMENTS,
|
CS_ASPNETCORE_PROCESS_ARGUMENTS,
|
||||||
&m_struArguments);
|
&m_struArguments);
|
||||||
|
|
@ -314,14 +343,13 @@ ASPNETCORE_CONFIG::Populate(
|
||||||
{
|
{
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
CS_ASPNETCORE_STDOUT_LOG_FILE,
|
||||||
CS_ASPNETCORE_STDOUT_LOG_FILE,
|
&m_struStdoutLogFile);
|
||||||
&m_struStdoutLogFile);
|
if (FAILED(hr))
|
||||||
if (FAILED(hr))
|
{
|
||||||
{
|
goto Finished;
|
||||||
goto Finished;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementChildByName(pAspNetCoreElement,
|
hr = GetElementChildByName(pAspNetCoreElement,
|
||||||
CS_ASPNETCORE_ENVIRONMENT_VARIABLES,
|
CS_ASPNETCORE_ENVIRONMENT_VARIABLES,
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ HRESULT
|
||||||
// static object initialized.
|
// static object initialized.
|
||||||
//
|
//
|
||||||
pFactory = new CProxyModuleFactory;
|
pFactory = new CProxyModuleFactory;
|
||||||
|
|
||||||
if (pFactory == NULL)
|
if (pFactory == NULL)
|
||||||
{
|
{
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
|
|
@ -225,7 +226,8 @@ HRESULT
|
||||||
goto Finished;
|
goto Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFactory = NULL;
|
pFactory = NULL;
|
||||||
|
|
||||||
g_pResponseHeaderHash = new RESPONSE_HEADER_HASH;
|
g_pResponseHeaderHash = new RESPONSE_HEADER_HASH;
|
||||||
if (g_pResponseHeaderHash == NULL)
|
if (g_pResponseHeaderHash == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
#include "fx_ver.h"
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
fx_ver_t::fx_ver_t(int major, int minor, int patch, const std::wstring& pre, const std::wstring& build)
|
||||||
|
: m_major(major)
|
||||||
|
, m_minor(minor)
|
||||||
|
, m_patch(patch)
|
||||||
|
, m_pre(pre)
|
||||||
|
, m_build(build)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_ver_t::fx_ver_t(int major, int minor, int patch, const std::wstring& pre)
|
||||||
|
: fx_ver_t(major, minor, patch, pre, TEXT(""))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_ver_t::fx_ver_t(int major, int minor, int patch)
|
||||||
|
: fx_ver_t(major, minor, patch, TEXT(""), TEXT(""))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator ==(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return compare(*this, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator !=(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return !operator ==(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator <(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return compare(*this, b) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator >(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return compare(*this, b) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator <=(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return compare(*this, b) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_ver_t::operator >=(const fx_ver_t& b) const
|
||||||
|
{
|
||||||
|
return compare(*this, b) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring fx_ver_t::as_str() const
|
||||||
|
{
|
||||||
|
std::wstringstream stream;
|
||||||
|
stream << m_major << TEXT(".") << m_minor << TEXT(".") << m_patch;
|
||||||
|
if (!m_pre.empty())
|
||||||
|
{
|
||||||
|
stream << m_pre;
|
||||||
|
}
|
||||||
|
if (!m_build.empty())
|
||||||
|
{
|
||||||
|
stream << TEXT("+") << m_build;
|
||||||
|
}
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
int fx_ver_t::compare(const fx_ver_t&a, const fx_ver_t& b)
|
||||||
|
{
|
||||||
|
// compare(u.v.w-p+b, x.y.z-q+c)
|
||||||
|
if (a.m_major != b.m_major)
|
||||||
|
{
|
||||||
|
return (a.m_major > b.m_major) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.m_minor != b.m_minor)
|
||||||
|
{
|
||||||
|
return (a.m_minor > b.m_minor) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.m_patch != b.m_patch)
|
||||||
|
{
|
||||||
|
return (a.m_patch > b.m_patch) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.m_pre.empty() != b.m_pre.empty())
|
||||||
|
{
|
||||||
|
// Either a is empty or b is empty
|
||||||
|
return a.m_pre.empty() ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Either both are empty or both are non-empty (may be equal)
|
||||||
|
int pre_cmp = a.m_pre.compare(b.m_pre);
|
||||||
|
if (pre_cmp != 0)
|
||||||
|
{
|
||||||
|
return pre_cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.m_build.compare(b.m_build);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_stou(const std::wstring& str, unsigned* num)
|
||||||
|
{
|
||||||
|
if (str.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (str.find_first_not_of(TEXT("0123456789")) != std::wstring::npos)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*num = (unsigned)std::stoul(str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_internal(const std::wstring& ver, fx_ver_t* fx_ver, bool parse_only_production)
|
||||||
|
{
|
||||||
|
size_t maj_start = 0;
|
||||||
|
size_t maj_sep = ver.find(TEXT('.'));
|
||||||
|
if (maj_sep == std::wstring::npos)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned major = 0;
|
||||||
|
if (!try_stou(ver.substr(maj_start, maj_sep), &major))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t min_start = maj_sep + 1;
|
||||||
|
size_t min_sep = ver.find(TEXT('.'), min_start);
|
||||||
|
if (min_sep == std::wstring::npos)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned minor = 0;
|
||||||
|
if (!try_stou(ver.substr(min_start, min_sep - min_start), &minor))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned patch = 0;
|
||||||
|
size_t pat_start = min_sep + 1;
|
||||||
|
size_t pat_sep = ver.find_first_not_of(TEXT("0123456789"), pat_start);
|
||||||
|
if (pat_sep == std::wstring::npos)
|
||||||
|
{
|
||||||
|
if (!try_stou(ver.substr(pat_start), &patch))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*fx_ver = fx_ver_t(major, minor, patch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_only_production)
|
||||||
|
{
|
||||||
|
// This is a prerelease or has build suffix.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!try_stou(ver.substr(pat_start, pat_sep - pat_start), &patch))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pre_start = pat_sep;
|
||||||
|
size_t pre_sep = ver.find(TEXT('+'), pre_start);
|
||||||
|
if (pre_sep == std::wstring::npos)
|
||||||
|
{
|
||||||
|
*fx_ver = fx_ver_t(major, minor, patch, ver.substr(pre_start));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t build_start = pre_sep + 1;
|
||||||
|
*fx_ver = fx_ver_t(major, minor, patch, ver.substr(pre_start, pre_sep - pre_start), ver.substr(build_start));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool fx_ver_t::parse(const std::wstring& ver, fx_ver_t* fx_ver, bool parse_only_production)
|
||||||
|
{
|
||||||
|
bool valid = parse_internal(ver, fx_ver, parse_only_production);
|
||||||
|
assert(!valid || fx_ver->as_str() == ver);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
@ -42,6 +42,10 @@
|
||||||
#include <httptrace.h>
|
#include <httptrace.h>
|
||||||
#include <winhttp.h>
|
#include <winhttp.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// Option available starting Windows 8.
|
// Option available starting Windows 8.
|
||||||
// 111 is the value in SDK on May 15, 2012.
|
// 111 is the value in SDK on May 15, 2012.
|
||||||
|
|
@ -110,6 +114,7 @@ inline bool IsSpace(char ch)
|
||||||
#include "environmentvariablehash.h"
|
#include "environmentvariablehash.h"
|
||||||
#include "..\aspnetcore_msg.h"
|
#include "..\aspnetcore_msg.h"
|
||||||
#include "aspnetcoreconfig.h"
|
#include "aspnetcoreconfig.h"
|
||||||
|
#include "aspnetcoreapplication.h"
|
||||||
#include "serverprocess.h"
|
#include "serverprocess.h"
|
||||||
#include "processmanager.h"
|
#include "processmanager.h"
|
||||||
#include "filewatcher.h"
|
#include "filewatcher.h"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "precomp.hxx"
|
#include "precomp.hxx"
|
||||||
|
|
||||||
|
|
||||||
__override
|
__override
|
||||||
HRESULT
|
HRESULT
|
||||||
CProxyModuleFactory::GetHttpModule(
|
CProxyModuleFactory::GetHttpModule(
|
||||||
|
|
@ -79,32 +78,86 @@ CProxyModule::OnExecuteRequestHandler(
|
||||||
IHttpEventProvider *
|
IHttpEventProvider *
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_pHandler = new FORWARDING_HANDLER(pHttpContext);
|
HRESULT hr;
|
||||||
if (m_pHandler == NULL)
|
APPLICATION_MANAGER* pApplicationManager;
|
||||||
{
|
APPLICATION* pApplication;
|
||||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, E_OUTOFMEMORY);
|
ASPNETCORE_CONFIG* config;
|
||||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
ASPNETCORE_APPLICATION* pAspNetCoreApplication;
|
||||||
}
|
ASPNETCORE_CONFIG::GetConfig(pHttpContext, &config);
|
||||||
|
|
||||||
return m_pHandler->OnExecuteRequestHandler();
|
// TODO store whether we are inproc or outofproc so we don't need to check the config everytime?
|
||||||
|
if (config->QueryIsOutOfProcess())// case insensitive
|
||||||
|
{
|
||||||
|
m_pHandler = new FORWARDING_HANDLER(pHttpContext);
|
||||||
|
if (m_pHandler == NULL)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pHandler->OnExecuteRequestHandler();
|
||||||
|
}
|
||||||
|
else if (config->QueryIsInProcess())
|
||||||
|
{
|
||||||
|
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
||||||
|
if (pApplicationManager == NULL)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pApplicationManager->GetApplication(pHttpContext,
|
||||||
|
&pApplication);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pApplication->GetAspNetCoreApplication(config, pHttpContext, &pAspNetCoreApplication);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
goto Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow reading and writing to simultaneously
|
||||||
|
((IHttpContext3*)pHttpContext)->EnableFullDuplex();
|
||||||
|
|
||||||
|
// Disable response buffering by default, we'll do a write behind buffering in managed code
|
||||||
|
((IHttpResponse2*)pHttpContext->GetResponse())->DisableBuffering();
|
||||||
|
|
||||||
|
// TODO: Optimize sync completions
|
||||||
|
return pAspNetCoreApplication->ExecuteRequest(pHttpContext);
|
||||||
|
}
|
||||||
|
Failed:
|
||||||
|
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr);
|
||||||
|
return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
__override
|
__override
|
||||||
REQUEST_NOTIFICATION_STATUS
|
REQUEST_NOTIFICATION_STATUS
|
||||||
CProxyModule::OnAsyncCompletion(
|
CProxyModule::OnAsyncCompletion(
|
||||||
IHttpContext *,
|
IHttpContext * pHttpContext,
|
||||||
DWORD dwNotification,
|
DWORD dwNotification,
|
||||||
BOOL fPostNotification,
|
BOOL fPostNotification,
|
||||||
IHttpEventProvider *,
|
IHttpEventProvider *,
|
||||||
IHttpCompletionInfo * pCompletionInfo
|
IHttpCompletionInfo * pCompletionInfo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(dwNotification);
|
// TODO store whether we are inproc or outofproc so we don't need to check the config everytime?
|
||||||
UNREFERENCED_PARAMETER(fPostNotification);
|
ASPNETCORE_CONFIG* config;
|
||||||
DBG_ASSERT(dwNotification == RQ_EXECUTE_REQUEST_HANDLER);
|
ASPNETCORE_CONFIG::GetConfig(pHttpContext, &config);
|
||||||
DBG_ASSERT(fPostNotification == FALSE);
|
|
||||||
|
|
||||||
return m_pHandler->OnAsyncCompletion(
|
if (config->QueryIsOutOfProcess())
|
||||||
|
{
|
||||||
|
return m_pHandler->OnAsyncCompletion(
|
||||||
pCompletionInfo->GetCompletionBytes(),
|
pCompletionInfo->GetCompletionBytes(),
|
||||||
pCompletionInfo->GetCompletionStatus());
|
pCompletionInfo->GetCompletionStatus());
|
||||||
|
}
|
||||||
|
else if (config->QueryIsInProcess())
|
||||||
|
{
|
||||||
|
return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||||
|
return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST;
|
||||||
}
|
}
|
||||||
|
|
@ -832,7 +832,7 @@ SERVER_PROCESS::PostStartCheck(
|
||||||
pStruErrorMessage->SafeSnwprintf(
|
pStruErrorMessage->SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG,
|
||||||
m_struAppFullPath.QueryStr(),
|
m_struAppFullPath.QueryStr(),
|
||||||
m_pszRootApplicationPath,
|
m_pszRootApplicationPath.QueryStr(),
|
||||||
pStruCommandline->QueryStr(),
|
pStruCommandline->QueryStr(),
|
||||||
m_dwPort,
|
m_dwPort,
|
||||||
hr);
|
hr);
|
||||||
|
|
@ -1071,7 +1071,7 @@ Finished:
|
||||||
strEventMsg.SafeSnwprintf(
|
strEventMsg.SafeSnwprintf(
|
||||||
ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG,
|
ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG,
|
||||||
m_struAppFullPath.QueryStr(),
|
m_struAppFullPath.QueryStr(),
|
||||||
m_pszRootApplicationPath,
|
m_pszRootApplicationPath.QueryStr(),
|
||||||
struCommandLine.QueryStr(),
|
struCommandLine.QueryStr(),
|
||||||
hr);
|
hr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
<attribute name="disableStartUpErrorPage" type="bool" defaultValue="false" />
|
<attribute name="disableStartUpErrorPage" type="bool" defaultValue="false" />
|
||||||
<attribute name="hostingModel" type="string" />
|
<attribute name="hostingModel" type="string" />
|
||||||
<element name="recycleOnFileChange">
|
<element name="recycleOnFileChange">
|
||||||
|
|
||||||
<collection addElement="file" clearElement="clear">
|
<collection addElement="file" clearElement="clear">
|
||||||
<attribute name="path" type="string" required="true" validationType="nonEmptyString" expanded="true"/>
|
<attribute name="path" type="string" required="true" validationType="nonEmptyString" expanded="true"/>
|
||||||
</collection>
|
</collection>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
|
|
@ -23,31 +23,32 @@
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>IISLib</RootNamespace>
|
<RootNamespace>IISLib</RootNamespace>
|
||||||
<ProjectName>IISLib</ProjectName>
|
<ProjectName>IISLib</ProjectName>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue