Adds RequestHandler dll and hostfxr changes from ANCM (#497)
This commit is contained in:
parent
8cedb4eff3
commit
c3bc6fed9c
|
|
@ -30,8 +30,15 @@
|
|||
<PackageId>Microsoft.AspNetCore.AspNetCoreModule</PackageId>
|
||||
<Version>$(PackageVersion)</Version>
|
||||
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
|
||||
</ArtifactInfo>
|
||||
<ArtifactInfo Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModule.RequestHandler.$(PackageVersion).nupkg">
|
||||
<ArtifactType>NuGetPackage</ArtifactType>
|
||||
<PackageId>Microsoft.AspNetCore.AspNetCoreModule.RequestHandler</PackageId>
|
||||
<Version>$(PackageVersion)</Version>
|
||||
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
|
||||
</ArtifactInfo>
|
||||
<FilesToExcludeFromSigning Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModule.$(PackageVersion).nupkg" />
|
||||
<FilesToExcludeFromSigning Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModule.RequestHandler.$(PackageVersion).nupkg" />
|
||||
|
||||
<ArtifactInfo Include="$(AncmZipOutputPath)">
|
||||
<ArtifactType>ZipArchive</ArtifactType>
|
||||
|
|
@ -69,6 +76,11 @@
|
|||
Overwrite="true"
|
||||
SourceFiles="@(AncmFiles)"
|
||||
WorkingDirectory="$(RepositoryRoot)" />
|
||||
|
||||
<PackNuspec NuspecPath="$(MSBuildThisFileDirectory)..\nuget\AspNetCoreRequestHandler.nuspec"
|
||||
DestinationFolder="$(BuildDir)"
|
||||
Properties="version=$(PackageVersion);Configuration=$(Configuration)"
|
||||
BasePath="$(RepositoryRoot)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
<licenseUrl>http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
||||
<copyright>© .NET Foundation. All rights reserved.</copyright>
|
||||
<projectUrl>http://www.asp.net/</projectUrl>
|
||||
<iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<description>ASP.NET Core Module</description>
|
||||
<language>en-US</language>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Microsoft.AspNetCore.AspNetCoreModule.RequestHandler</id>
|
||||
<title>Microsoft ASP.NET Core Module Request Handler</title>
|
||||
<version>$VERSION$</version>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>Microsoft</owners>
|
||||
<licenseUrl>http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
||||
<copyright>© .NET Foundation. All rights reserved.</copyright>
|
||||
<projectUrl>http://www.asp.net/</projectUrl>
|
||||
<iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<description>ASP.NET Core Module Request Handler</description>
|
||||
<language>en-US</language>
|
||||
<tags>Microsoft.AspNetCore.AspNetCoreModule.RequestHandler</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- TODO make build output outside of content files. -->
|
||||
<file src="src\RequestHandler\bin\$Configuration$\Win32\aspnetcorerh.dll" target="runtimes\win-x86\nativeassets\netcoreapp2.1\aspnetcorerh.dll" />
|
||||
<file src="src\RequestHandler\bin\$Configuration$\x64\aspnetcorerh.dll" target="runtimes\win-x64\nativeassets\netcoreapp2.1\aspnetcorerh.dll" />
|
||||
</files>
|
||||
</package>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
#define API_BUFFER_TOO_SMALL 0x80008098
|
||||
|
||||
typedef
|
||||
HRESULT
|
||||
|
|
@ -145,8 +146,7 @@ public:
|
|||
private:
|
||||
HRESULT FindRequestHandlerAssembly();
|
||||
HRESULT FindNativeAssemblyFromGlobalLocation(STRU* struFilename);
|
||||
HRESULT FindNativeAssemblyFromLocalBin(STRU* struFilename);
|
||||
HRESULT GetRequestHandlerFromRuntimeStore(STRU* struFilename);
|
||||
HRESULT FindNativeAssemblyFromHostfxr(STRU* struFilename);
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
APPLICATION_INFO_KEY m_applicationInfoKey;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
if (HRESULT_FROM_WIN32(GetLastError()) == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
fResult = FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,11 +145,11 @@ APPLICATION_INFO::UpdateAppOfflineFileHandle()
|
|||
HRESULT
|
||||
APPLICATION_INFO::EnsureApplicationCreated()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
APPLICATION* pApplication = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
APPLICATION* pApplication = NULL;
|
||||
STACK_STRU(struFileName, 300); // >MAX_PATH
|
||||
STRU hostFxrDllLocation;
|
||||
STRU hostFxrDllLocation;
|
||||
|
||||
if (m_pApplication != NULL)
|
||||
{
|
||||
|
|
@ -184,7 +184,6 @@ APPLICATION_INFO::EnsureApplicationCreated()
|
|||
}
|
||||
m_pApplication = pApplication;
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (fLocked)
|
||||
{
|
||||
|
|
@ -196,9 +195,9 @@ Finished:
|
|||
HRESULT
|
||||
APPLICATION_INFO::FindRequestHandlerAssembly()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
STACK_STRU(struFileName, 300); // >MAX_PATH
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
STACK_STRU(struFileName, 256);
|
||||
|
||||
if (g_fAspnetcoreRHLoadedError)
|
||||
{
|
||||
|
|
@ -219,19 +218,10 @@ APPLICATION_INFO::FindRequestHandlerAssembly()
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
// load assembly and create the application
|
||||
if (m_pConfiguration->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
||||
{
|
||||
// Look at inetsvr only for now. TODO add in functionality
|
||||
hr = FindNativeAssemblyFromGlobalLocation(&struFileName);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (FAILED(hr = HOSTFXR_UTILITY::GetHostFxrParameters(m_pConfiguration)) ||
|
||||
FAILED(hr = FindNativeAssemblyFromHostfxr(&struFileName)))
|
||||
{
|
||||
// TODO eventually make this fail for in process loading.
|
||||
hr = FindNativeAssemblyFromGlobalLocation(&struFileName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
|
@ -294,6 +284,11 @@ APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(STRU* struFilename)
|
|||
// Though we could call LoadLibrary(L"aspnetcorerh.dll") relying the OS to solve
|
||||
// the path (the targeted dll is the same folder of w3wp.exe/iisexpress)
|
||||
// let's still load with full path to avoid security issue
|
||||
if (FAILED(hr = struFilename->Resize(dwSize + 20)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
while (!fDone)
|
||||
{
|
||||
DWORD dwReturnedSize = GetModuleFileNameW(g_hModule, struFilename->QueryStr(), dwSize);
|
||||
|
|
@ -306,7 +301,10 @@ APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(STRU* struFilename)
|
|||
else if ((dwReturnedSize == dwSize) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
dwSize *= 2; // smaller buffer. increase the buffer and retry
|
||||
struFilename->Resize(dwSize + 20); // aspnetcorerh.dll
|
||||
if (FAILED(hr = struFilename->Resize(dwSize + 20))) // + 20 for aspnetcorerh.dll
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -322,6 +320,7 @@ APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(STRU* struFilename)
|
|||
struFilename->QueryStr()[dwPosition] = L'\0';
|
||||
|
||||
if (FAILED(hr = struFilename->SyncWithBuffer()) ||
|
||||
FAILED(hr = struFilename->Append(L"\\")) ||
|
||||
FAILED(hr = struFilename->Append(g_pwzAspnetcoreRequestHandlerName)))
|
||||
{
|
||||
goto Finished;
|
||||
|
|
@ -330,3 +329,137 @@ APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(STRU* struFilename)
|
|||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// Tries to find aspnetcorerh.dll from the application
|
||||
// Calls into hostfxr.dll to find it.
|
||||
// Will leave hostfxr.dll loaded as it will be used again to call hostfxr_main.
|
||||
//
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::FindNativeAssemblyFromHostfxr(
|
||||
STRU* struFilename
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struApplicationFullPath;
|
||||
STRU struNativeSearchPaths;
|
||||
STRU struNativeDllLocation;
|
||||
HMODULE hmHostFxrDll = NULL;
|
||||
INT intHostFxrExitCode = 0;
|
||||
INT intIndex = -1;
|
||||
INT intPrevIndex = 0;
|
||||
BOOL fFound = FALSE;
|
||||
DWORD dwBufferSize = 1024 * 10;
|
||||
|
||||
DBG_ASSERT(struFileName != NULL);
|
||||
|
||||
hmHostFxrDll = LoadLibraryW(m_pConfiguration->QueryHostFxrFullPath());
|
||||
|
||||
if (hmHostFxrDll == NULL)
|
||||
{
|
||||
// Could not load hostfxr
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hostfxr_get_native_search_directories_fn pFnHostFxrSearchDirectories = (hostfxr_get_native_search_directories_fn)
|
||||
GetProcAddress(hmHostFxrDll, "hostfxr_get_native_search_directories");
|
||||
|
||||
if (pFnHostFxrSearchDirectories == NULL)
|
||||
{
|
||||
// Host fxr version is incorrect (need a higher version).
|
||||
// TODO log error
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = struNativeSearchPaths.Resize(dwBufferSize)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
intHostFxrExitCode = pFnHostFxrSearchDirectories(
|
||||
m_pConfiguration->QueryHostFxrArgCount(),
|
||||
m_pConfiguration->QueryHostFxrArguments(),
|
||||
struNativeSearchPaths.QueryStr(),
|
||||
dwBufferSize
|
||||
);
|
||||
|
||||
if (intHostFxrExitCode == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (intHostFxrExitCode == API_BUFFER_TOO_SMALL)
|
||||
{
|
||||
dwBufferSize *= 2; // smaller buffer. increase the buffer and retry
|
||||
if (FAILED(hr = struNativeSearchPaths.Resize(dwBufferSize)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_FAIL;
|
||||
// Log "Error finding native search directories from aspnetcore application.
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = struNativeSearchPaths.SyncWithBuffer()))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
fFound = FALSE;
|
||||
|
||||
// The native search directories are semicolon delimited.
|
||||
// Split on semicolons, append aspnetcorerh.dll, and check if the file exists.
|
||||
while ((intIndex = struNativeSearchPaths.IndexOf(L";", intPrevIndex)) != -1)
|
||||
{
|
||||
if (FAILED(hr = struNativeDllLocation.Copy(struNativeSearchPaths.QueryStr(), intIndex - intPrevIndex)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!struNativeDllLocation.EndsWith(L"\\"))
|
||||
{
|
||||
if (FAILED(hr = struNativeDllLocation.Append(L"\\")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = struNativeDllLocation.Append(g_pwzAspnetcoreRequestHandlerName)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (UTILITY::CheckIfFileExists(struNativeDllLocation.QueryStr()))
|
||||
{
|
||||
if (FAILED(hr = struFilename->Copy(struNativeDllLocation)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
fFound = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
intPrevIndex = intIndex + 1;
|
||||
}
|
||||
|
||||
if (!fFound)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (FAILED(hr) && hmHostFxrDll != NULL)
|
||||
{
|
||||
FreeLibrary(hmHostFxrDll);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ DWORD g_dwActiveServerProcesses = 0;
|
|||
SRWLOCK g_srwLock;
|
||||
DWORD g_dwDebugFlags = 0;
|
||||
PCSTR g_szDebugLabel = "ASPNET_CORE_MODULE";
|
||||
PCWSTR g_pwzAspnetcoreRequestHandlerName = L"\\aspnetcorerh.dll";
|
||||
PCWSTR g_pwzAspnetcoreRequestHandlerName = L"aspnetcorerh.dll";
|
||||
PFN_ASPNETCORE_CREATE_APPLICATION g_pfnAspNetCoreCreateApplication;
|
||||
PFN_ASPNETCORE_CREATE_REQUEST_HANDLER g_pfnAspNetCoreCreateRequestHandler;
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ inline bool IsSpace(char ch)
|
|||
|
||||
#include "..\..\CommonLib\environmentvariablehash.h"
|
||||
#include "..\..\CommonLib\aspnetcoreconfig.h"
|
||||
#include "..\..\CommonLib\hostfxr_utility.h"
|
||||
#include "..\..\CommonLib\application.h"
|
||||
#include "..\..\CommonLib\utility.h"
|
||||
#include "..\..\CommonLib\debugutil.h"
|
||||
|
|
@ -116,6 +117,7 @@ inline bool IsSpace(char ch)
|
|||
#include "globalmodule.h"
|
||||
#include "resource.h"
|
||||
#include "proxymodule.h"
|
||||
#include "applicationinfo.h"
|
||||
|
||||
|
||||
FORCEINLINE
|
||||
|
|
|
|||
|
|
@ -151,8 +151,8 @@ ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
|||
// cannot recreate the application as we cannot reload clr for inprocess
|
||||
if (pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||
goto Finished;
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Create RequestHandler and process the request
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
||||
{
|
||||
if (m_ppStrArguments != NULL)
|
||||
{
|
||||
delete[] m_ppStrArguments;
|
||||
m_ppStrArguments = NULL;
|
||||
}
|
||||
|
||||
if (m_pEnvironmentVariables != NULL)
|
||||
{
|
||||
m_pEnvironmentVariables->Clear();
|
||||
|
|
@ -22,7 +28,6 @@ ASPNETCORE_CONFIG::ReferenceConfiguration(
|
|||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
ASPNETCORE_CONFIG::DereferenceConfiguration(
|
||||
VOID
|
||||
|
|
@ -132,6 +137,7 @@ ASPNETCORE_CONFIG::Populate(
|
|||
IHttpContext *pHttpContext
|
||||
)
|
||||
{
|
||||
STACK_STRU(strHostingModel, 300);
|
||||
HRESULT hr = S_OK;
|
||||
STRU strEnvName;
|
||||
STRU strEnvValue;
|
||||
|
|
@ -308,7 +314,7 @@ ASPNETCORE_CONFIG::Populate(
|
|||
|
||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||
CS_ASPNETCORE_HOSTING_MODEL,
|
||||
&m_strHostingModel);
|
||||
&strHostingModel);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Swallow this error for backward compatability
|
||||
|
|
@ -316,11 +322,11 @@ ASPNETCORE_CONFIG::Populate(
|
|||
hr = S_OK;
|
||||
}
|
||||
|
||||
if (m_strHostingModel.IsEmpty() || m_strHostingModel.Equals(L"outofprocess", TRUE))
|
||||
if (strHostingModel.IsEmpty() || strHostingModel.Equals(L"outofprocess", TRUE))
|
||||
{
|
||||
m_hostingModel = HOSTING_OUT_PROCESS;
|
||||
}
|
||||
else if (m_strHostingModel.Equals(L"inprocess", TRUE))
|
||||
else if (strHostingModel.Equals(L"inprocess", TRUE))
|
||||
{
|
||||
m_hostingModel = HOSTING_IN_PROCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public:
|
|||
_In_ IHttpServer *pHttpServer,
|
||||
_In_ HTTP_MODULE_ID pModuleId,
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
);
|
||||
|
||||
ENVIRONMENT_VAR_HASH*
|
||||
|
|
@ -215,18 +215,54 @@ public:
|
|||
return &m_struConfigPath;
|
||||
}
|
||||
|
||||
STRU*
|
||||
QueryHostfxrPath()
|
||||
{
|
||||
return &m_struHostFxrPath;
|
||||
}
|
||||
|
||||
BOOL
|
||||
QueryIsStandAloneApplication(
|
||||
CONST
|
||||
PCWSTR*
|
||||
QueryHostFxrArguments(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_fIsStandAloneApplication;
|
||||
return m_ppStrArguments;
|
||||
}
|
||||
|
||||
CONST
|
||||
DWORD
|
||||
QueryHostFxrArgCount(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_dwArgc;
|
||||
}
|
||||
|
||||
CONST
|
||||
PCWSTR
|
||||
QueryHostFxrFullPath(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_struHostFxrLocation.QueryStr();
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SetHostFxrFullPath(
|
||||
PCWSTR pStrHostFxrFullPath
|
||||
)
|
||||
{
|
||||
return m_struHostFxrLocation.Copy(pStrHostFxrFullPath);
|
||||
}
|
||||
|
||||
VOID
|
||||
SetHostFxrArguments(
|
||||
DWORD dwArgc,
|
||||
PCWSTR* ppStrArguments
|
||||
)
|
||||
{
|
||||
if (m_ppStrArguments != NULL)
|
||||
{
|
||||
delete[] m_ppStrArguments;
|
||||
}
|
||||
|
||||
m_dwArgc = dwArgc;
|
||||
m_ppStrArguments = ppStrArguments;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
@ -248,7 +284,8 @@ private:
|
|||
m_fStdoutLogEnabled( FALSE ),
|
||||
m_pEnvironmentVariables( NULL ),
|
||||
m_cRefs( 1 ),
|
||||
m_hostingModel( HOSTING_UNKNOWN )
|
||||
m_hostingModel( HOSTING_UNKNOWN ),
|
||||
m_ppStrArguments(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -272,8 +309,6 @@ private:
|
|||
STRU m_struApplicationPhysicalPath;
|
||||
STRU m_struApplicationVirtualPath;
|
||||
STRU m_struConfigPath;
|
||||
STRU m_strHostingModel;
|
||||
STRU m_struHostFxrPath;
|
||||
BOOL m_fStdoutLogEnabled;
|
||||
BOOL m_fForwardWindowsAuthToken;
|
||||
BOOL m_fDisableStartUpErrorPage;
|
||||
|
|
@ -283,4 +318,7 @@ private:
|
|||
BOOL m_fIsStandAloneApplication;
|
||||
APP_HOSTING_MODEL m_hostingModel;
|
||||
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
||||
STRU m_struHostFxrLocation;
|
||||
PCWSTR* m_ppStrArguments;
|
||||
DWORD m_dwArgc;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,40 +7,10 @@ HOSTFXR_UTILITY::HOSTFXR_UTILITY()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
HOSTFXR_UTILITY::~HOSTFXR_UTILITY()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::FindHostFxrDll(
|
||||
ASPNETCORE_CONFIG *pConfig,
|
||||
STRU* struHostFxrDllLocation,
|
||||
BOOL* fStandAlone
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// If the process path isn't dotnet, assume we are a standalone appliction.
|
||||
// TODO: this should be a path equivalent check
|
||||
if (!(pConfig->QueryProcessPath()->Equals(L".\\dotnet")
|
||||
|| pConfig->QueryProcessPath()->Equals(L"dotnet")
|
||||
|| pConfig->QueryProcessPath()->Equals(L".\\dotnet.exe")
|
||||
|| pConfig->QueryProcessPath()->Equals(L"dotnet.exe")))
|
||||
{
|
||||
// hostfxr is in the same folder, parse and use it.
|
||||
hr = GetStandaloneHostfxrLocation(struHostFxrDllLocation, pConfig);
|
||||
*fStandAlone = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = GetPortableHostfxrLocation(struHostFxrDllLocation);
|
||||
fStandAlone = FALSE;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// Runs a standalone appliction.
|
||||
// The folder structure looks like this:
|
||||
|
|
@ -54,160 +24,183 @@ HOSTFXR_UTILITY::FindHostFxrDll(
|
|||
// Assuming we don't need Application.exe as the dll is the actual application.
|
||||
//
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetStandaloneHostfxrLocation(
|
||||
STRU* struHostfxrPath,
|
||||
HOSTFXR_UTILITY::GetStandaloneHostfxrParameters(
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE hFileHandle = INVALID_HANDLE_VALUE;
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
HRESULT hr = S_OK;
|
||||
STRU struExePath;
|
||||
STRU struDllPath;
|
||||
STRU struArguments;
|
||||
DWORD dwPosition;
|
||||
|
||||
// Get the full path to the exe and check if it exists
|
||||
if (FAILED(hr = UTILITY::ConvertPathToFullPath(L"\\hostfxr.dll",
|
||||
hr = UTILITY::ConvertPathToFullPath(pConfig->QueryProcessPath()->QueryStr(),
|
||||
pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
struHostfxrPath)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
hFileHandle = CreateFile(struHostfxrPath->QueryStr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Treat access isseu as File not found
|
||||
hr = ERROR_FILE_NOT_FOUND;
|
||||
goto Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle(hFileHandle);
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetPortableHostfxrLocation(
|
||||
STRU* struHostfxrPath
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
STRU struSystemPathVariable;
|
||||
STRU strDotnetExeLocation;
|
||||
STRU strHostFxrSearchExpression;
|
||||
STRU strHighestDotnetVersion;
|
||||
PWSTR pwzDelimeterContext = NULL;
|
||||
PCWSTR pszDotnetLocation = NULL;
|
||||
PCWSTR pszDotnetExeString(L"dotnet.exe");
|
||||
DWORD dwCopyLength;
|
||||
BOOL fFound = FALSE;
|
||||
HANDLE hFileHandle = INVALID_HANDLE_VALUE;
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
std::vector<std::wstring> vVersionFolders;
|
||||
|
||||
&struExePath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Get the System PATH value.
|
||||
if (!UTILITY::GetSystemPathVariable(L"PATH", &struSystemPathVariable))
|
||||
if (FAILED(hr = struDllPath.Copy(struExePath)))
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Split on ';', checking to see if dotnet.exe exists in any folders.
|
||||
pszDotnetLocation = wcstok_s(struSystemPathVariable.QueryStr(), L";", &pwzDelimeterContext);
|
||||
while (pszDotnetLocation != NULL)
|
||||
dwPosition = struDllPath.LastIndexOf(L'.', 0);
|
||||
if (dwPosition == -1)
|
||||
{
|
||||
dwCopyLength = (DWORD) wcsnlen_s(pszDotnetLocation, 260);
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// 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
|
||||
hr = strDotnetExeLocation.Copy(pszDotnetLocation, dwCopyLength);
|
||||
struDllPath.QueryStr()[dwPosition] = L'\0';
|
||||
|
||||
if (FAILED(hr = struDllPath.SyncWithBuffer()) ||
|
||||
FAILED(hr = struDllPath.Append(L".dll")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::CheckIfFileExists(struDllPath.QueryStr()))
|
||||
{
|
||||
// Treat access issue as File not found
|
||||
hr = ERROR_FILE_NOT_FOUND;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = struArguments.Copy(struDllPath)) ||
|
||||
FAILED(hr = struArguments.Append(L" ")) ||
|
||||
FAILED(hr = struArguments.Append(pConfig->QueryArguments())))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = SetHostFxrArguments(&struArguments, &struExePath, pConfig)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetHostFxrParameters(
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struSystemPathVariable;
|
||||
STRU struHostFxrPath;
|
||||
STRU strDotnetExeLocation;
|
||||
STRU strHostFxrSearchExpression;
|
||||
STRU strHighestDotnetVersion;
|
||||
std::vector<std::wstring> vVersionFolders;
|
||||
DWORD dwPosition;
|
||||
DWORD dwPathLength = MAX_PATH;
|
||||
DWORD dwDotnetLength = 0;
|
||||
BOOL fFound = FALSE;
|
||||
|
||||
if (UTILITY::CheckIfFileExists(pConfig->QueryProcessPath()->QueryStr()))
|
||||
{
|
||||
hr = UTILITY::ConvertPathToFullPath(L"hostfxr.dll", pConfig->QueryApplicationPath()->QueryStr(), &struHostFxrPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (dwCopyLength > 0 && pszDotnetLocation[dwCopyLength - 1] != L'\\')
|
||||
if (UTILITY::CheckIfFileExists(struHostFxrPath.QueryStr()))
|
||||
{
|
||||
hr = strDotnetExeLocation.Append(L"\\");
|
||||
// Standalone application
|
||||
if (FAILED(hr = pConfig->SetHostFxrFullPath(struHostFxrPath.QueryStr())))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = GetStandaloneHostfxrParameters(pConfig);
|
||||
goto Finished;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = UTILITY::ConvertPathToFullPath(
|
||||
pConfig->QueryProcessPath()->QueryStr(),
|
||||
pConfig->QueryApplicationPath()->QueryStr(),
|
||||
&strDotnetExeLocation
|
||||
);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Copy(strDotnetExeLocation);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = strDotnetExeLocation.Append(pszDotnetExeString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
hFileHandle = CreateFile(strDotnetExeLocation.QueryStr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// means we found the folder with a dotnet.exe inside of it.
|
||||
fFound = TRUE;
|
||||
CloseHandle(hFileHandle);
|
||||
break;
|
||||
}
|
||||
pszDotnetLocation = wcstok_s(NULL, L";", &pwzDelimeterContext);
|
||||
}
|
||||
|
||||
if (!fFound)
|
||||
if (FAILED(hr = strDotnetExeLocation.Resize(MAX_PATH)))
|
||||
{
|
||||
// could not find dotnet.exe, error out
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(L"host\\fxr");
|
||||
while (!fFound)
|
||||
{
|
||||
dwDotnetLength = SearchPath(NULL, L"dotnet", L".exe", dwPathLength, strDotnetExeLocation.QueryStr(), NULL);
|
||||
if (dwDotnetLength == 0)
|
||||
{
|
||||
hr = GetLastError();
|
||||
// Could not find dotnet
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwDotnetLength == dwPathLength)
|
||||
{
|
||||
// Increase size
|
||||
dwPathLength *= 2;
|
||||
if (FAILED(hr = strDotnetExeLocation.Resize(dwPathLength)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fFound = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = strDotnetExeLocation.SyncWithBuffer())
|
||||
|| FAILED(hr = struHostFxrPath.Copy(strDotnetExeLocation)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
dwPosition = struHostFxrPath.LastIndexOf(L'\\', 0);
|
||||
if (dwPosition == -1)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
struHostFxrPath.QueryStr()[dwPosition] = L'\0';
|
||||
|
||||
if (FAILED(hr = struHostFxrPath.SyncWithBuffer())
|
||||
|| FAILED(hr = struHostFxrPath.Append(L"\\")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostFxrPath.Append(L"host\\fxr");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::DirectoryExists(struHostfxrPath))
|
||||
if (!UTILITY::DirectoryExists(&struHostFxrPath))
|
||||
{
|
||||
// error, not found the folder
|
||||
// error, not found in folder
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Find all folders under host\\fxr\\ for version numbers.
|
||||
hr = strHostFxrSearchExpression.Copy(struHostfxrPath);
|
||||
hr = strHostFxrSearchExpression.Copy(struHostFxrPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
|
|
@ -235,25 +228,84 @@ HOSTFXR_UTILITY::GetPortableHostfxrLocation(
|
|||
{
|
||||
goto Finished;
|
||||
}
|
||||
hr = struHostfxrPath->Append(L"\\");
|
||||
if (FAILED(hr))
|
||||
|
||||
if (FAILED(hr = struHostFxrPath.Append(L"\\"))
|
||||
|| FAILED(hr = struHostFxrPath.Append(strHighestDotnetVersion.QueryStr()))
|
||||
|| FAILED(hr = struHostFxrPath.Append(L"\\hostfxr.dll")))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(strHighestDotnetVersion.QueryStr());
|
||||
if (FAILED(hr))
|
||||
if (!UTILITY::CheckIfFileExists(struHostFxrPath.QueryStr()))
|
||||
{
|
||||
hr = ERROR_FILE_INVALID;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (FAILED(hr = SetHostFxrArguments(pConfig->QueryArguments(), &strDotnetExeLocation, pConfig)))
|
||||
{
|
||||
goto Finished;
|
||||
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(L"\\hostfxr.dll");
|
||||
if (FAILED(hr))
|
||||
if (FAILED(hr = pConfig->SetHostFxrFullPath(struHostFxrPath.QueryStr())))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// Forms the argument list in HOSTFXR_PARAMETERS.
|
||||
// Sets the ArgCount and Arguments.
|
||||
// Arg structure:
|
||||
// argv[0] = Path to exe activating hostfxr.
|
||||
// argv[1] = L"exec"
|
||||
// argv[2] = first argument specified in the arguments portion of aspnetcore config.
|
||||
//
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::SetHostFxrArguments(
|
||||
STRU* struArgumentsFromConfig,
|
||||
STRU* pstruExePath,
|
||||
ASPNETCORE_CONFIG* pConfig
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
INT argc = 0;
|
||||
PCWSTR* argv = NULL;
|
||||
LPWSTR* pwzArgs = NULL;
|
||||
|
||||
pwzArgs = CommandLineToArgvW(struArgumentsFromConfig->QueryStr(), &argc);
|
||||
|
||||
if (pwzArgs == NULL)
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
argv = new PCWSTR[argc + 2];
|
||||
if (argv == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
argv[0] = SysAllocString(pstruExePath->QueryStr());
|
||||
argv[1] = SysAllocString(L"exec");
|
||||
|
||||
for (INT i = 0; i < argc; i++)
|
||||
{
|
||||
argv[i + 2] = SysAllocString(pwzArgs[i]);
|
||||
}
|
||||
|
||||
pConfig->SetHostFxrArguments(argc + 2, argv);
|
||||
|
||||
Finished:
|
||||
if (pwzArgs != NULL)
|
||||
{
|
||||
LocalFree(pwzArgs);
|
||||
DBG_ASSERT(pwzArgs == NULL);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef INT(*hostfxr_get_native_search_directories_fn) (const int argc, const PCWSTR argv[], PCWSTR dest, size_t dest_size);
|
||||
typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]);
|
||||
|
||||
|
||||
class HOSTFXR_UTILITY
|
||||
{
|
||||
public:
|
||||
|
|
@ -11,23 +15,23 @@ public:
|
|||
|
||||
static
|
||||
HRESULT
|
||||
FindHostFxrDll(
|
||||
ASPNETCORE_CONFIG *pConfig,
|
||||
STRU* struHostFxrDllLocation,
|
||||
BOOL* fStandAlone
|
||||
GetHostFxrParameters(
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
);
|
||||
|
||||
private:
|
||||
static
|
||||
HRESULT
|
||||
GetStandaloneHostfxrLocation(
|
||||
STRU* struHostfxrPath,
|
||||
GetStandaloneHostfxrParameters(
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetPortableHostfxrLocation(
|
||||
STRU* struHostfxrPath
|
||||
SetHostFxrArguments(
|
||||
STRU * struArguments,
|
||||
STRU * pstruExePath,
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <httpserv.h>
|
||||
#include <wchar.h>
|
||||
#include <vector>
|
||||
#include <shellapi.h>
|
||||
#include <sstream>
|
||||
#include "..\IISLib\hashtable.h"
|
||||
#include "..\IISLib\stringu.h"
|
||||
|
|
|
|||
|
|
@ -545,45 +545,6 @@ UTILITY::DirectoryExists(
|
|||
return GetFileAttributesExW(pstrPath->QueryStr(), GetFileExInfoStandard, &data);
|
||||
}
|
||||
|
||||
BOOL
|
||||
UTILITY::GetSystemPathVariable(
|
||||
_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
|
||||
UTILITY::FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
|
|
@ -606,4 +567,35 @@ UTILITY::FindDotNetFolders(
|
|||
} while (FindNextFileW(handle, &data));
|
||||
|
||||
FindClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
UTILITY::CheckIfFileExists(
|
||||
_In_ PCWSTR pszFilePath
|
||||
)
|
||||
{
|
||||
HANDLE hFileHandle = INVALID_HANDLE_VALUE;
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
BOOL fFileExists = FALSE;
|
||||
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
hFileHandle = CreateFile(pszFilePath,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
fFileExists = hFileHandle != INVALID_HANDLE_VALUE || GetLastError() == ERROR_SHARING_VIOLATION;
|
||||
|
||||
if (fFileExists)
|
||||
{
|
||||
CloseHandle(hFileHandle);
|
||||
}
|
||||
|
||||
return fFileExists;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,13 +91,6 @@ public:
|
|||
_In_ STRU *pstrPath
|
||||
);
|
||||
|
||||
static
|
||||
BOOL
|
||||
GetSystemPathVariable(
|
||||
_In_ PCWSTR pszEnvironmentVariable,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
FindDotNetFolders(
|
||||
|
|
@ -112,6 +105,12 @@ public:
|
|||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
BOOL
|
||||
CheckIfFileExists(
|
||||
PCWSTR pszFilePath
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
UTILITY() {}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "..\precomp.hxx"
|
||||
|
||||
typedef DWORD(*hostfxr_main_fn) (CONST DWORD argc, CONST WCHAR* argv[]);
|
||||
|
||||
IN_PROCESS_APPLICATION* IN_PROCESS_APPLICATION::s_Application = NULL;
|
||||
|
||||
IN_PROCESS_APPLICATION::IN_PROCESS_APPLICATION(
|
||||
|
|
@ -180,84 +178,6 @@ IN_PROCESS_APPLICATION::OnExecuteRequest(
|
|||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IN_PROCESS_APPLICATION::DirectoryExists(
|
||||
_In_ STRU *pstrPath
|
||||
)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
|
||||
if (pstrPath->IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetFileAttributesExW(pstrPath->QueryStr(), GetFileExInfoStandard, &data);
|
||||
}
|
||||
|
||||
BOOL
|
||||
IN_PROCESS_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
|
||||
IN_PROCESS_APPLICATION::FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
_Out_ std::vector<std::wstring> *pvFolders
|
||||
)
|
||||
{
|
||||
HANDLE handle = NULL;
|
||||
WIN32_FIND_DATAW data = { 0 };
|
||||
|
||||
handle = FindFirstFileExW(pszPath, 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);
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::SetCallbackHandles(
|
||||
_In_ PFN_REQUEST_HANDLER request_handler,
|
||||
|
|
@ -277,30 +197,6 @@ IN_PROCESS_APPLICATION::SetCallbackHandles(
|
|||
SetEvent(m_pInitalizeEvent);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_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))
|
||||
{
|
||||
// TODO using max instead of std::max works
|
||||
max_ver = max(max_ver, fx_ver);
|
||||
}
|
||||
}
|
||||
|
||||
hr = pstrResult->Copy(max_ver.as_str().c_str());
|
||||
|
||||
// we check FAILED(hr) outside of function
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::SetStdOut(
|
||||
VOID
|
||||
|
|
@ -495,6 +391,11 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
|
|||
{
|
||||
// Core CLR has already been loaded.
|
||||
// Cannot load more than once even there was a failure
|
||||
if (m_fLoadManagedAppError)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
}
|
||||
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
|
@ -505,6 +406,11 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
|
|||
fLocked = TRUE;
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
if (m_fLoadManagedAppError)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
}
|
||||
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
|
@ -572,16 +478,12 @@ IN_PROCESS_APPLICATION::LoadManagedApplication
|
|||
m_fManagedAppLoaded = TRUE;
|
||||
|
||||
Finished:
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Question: in case of application loading failure, should we allow retry on
|
||||
// following request or block the activation at all
|
||||
m_fLoadManagedAppError = FALSE; // m_hThread != NULL ?
|
||||
m_fLoadManagedAppError = TRUE; // m_hThread != NULL ?
|
||||
|
||||
// TODO
|
||||
//if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
|
|
@ -610,6 +512,12 @@ Finished:
|
|||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
@ -619,166 +527,29 @@ IN_PROCESS_APPLICATION::ExecuteAspNetCoreProcess(
|
|||
_In_ LPVOID pContext
|
||||
)
|
||||
{
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
IN_PROCESS_APPLICATION *pApplication = (IN_PROCESS_APPLICATION*)pContext;
|
||||
DBG_ASSERT(pApplication != NULL);
|
||||
pApplication->ExecuteApplication();
|
||||
hr = pApplication->ExecuteApplication();
|
||||
//
|
||||
// no need to log the error here as if error happened, the thread will exit
|
||||
// the error will ba catched by caller LoadManagedApplication which will log an error
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::ExecuteApplication(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT hr = S_OK;
|
||||
HMODULE hModule;
|
||||
hostfxr_main_fn pProc;
|
||||
|
||||
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;
|
||||
bool fFound = FALSE;
|
||||
|
||||
// Get the System PATH value.
|
||||
if (!GetEnv(L"PATH", &strFullPath))
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Split on ';', checking to see if dotnet.exe exists in any folders.
|
||||
pszDotnetExeLocation = wcstok_s(strFullPath.QueryStr(), L";", &strDelimeterContext);
|
||||
|
||||
while (pszDotnetExeLocation != NULL)
|
||||
{
|
||||
dwCopyLength = (DWORD) 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 Finished;
|
||||
}
|
||||
|
||||
hr = strDotnetFolderLocation.Copy(pszDotnetExeLocation, dwCopyLength);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (dwCopyLength > 0 && pszDotnetExeLocation[dwCopyLength - 1] != L'\\')
|
||||
{
|
||||
hr = strDotnetExeLocation.Append(L"\\");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
hr = strDotnetExeLocation.Append(pszDotnetExeString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (PathFileExists(strDotnetExeLocation.QueryStr()))
|
||||
{
|
||||
// means we found the folder with a dotnet.exe inside of it.
|
||||
fFound = TRUE;
|
||||
break;
|
||||
}
|
||||
pszDotnetExeLocation = wcstok_s(NULL, L";", &strDelimeterContext);
|
||||
}
|
||||
if (!fFound)
|
||||
{
|
||||
// could not find dotnet.exe, error out
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
}
|
||||
|
||||
hr = strDotnetFolderLocation.Append(L"\\host\\fxr");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!DirectoryExists(&strDotnetFolderLocation))
|
||||
{
|
||||
// error, not found the folder
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Find all folders under host\\fxr\\ for version numbers.
|
||||
hr = strHostFxrSearchExpression.Copy(strDotnetFolderLocation);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = strHostFxrSearchExpression.Append(L"\\*");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// As we use the logic from core-setup, we are opting to use std here.
|
||||
// TODO remove all uses of std?
|
||||
FindDotNetFolders(strHostFxrSearchExpression.QueryStr(), &vVersionFolders);
|
||||
|
||||
if (vVersionFolders.size() == 0)
|
||||
{
|
||||
// no core framework was found
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = FindHighestDotNetVersion(vVersionFolders, &strHighestDotnetVersion);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
hr = strDotnetFolderLocation.Append(L"\\");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = strDotnetFolderLocation.Append(strHighestDotnetVersion.QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
|
||||
}
|
||||
|
||||
hr = strDotnetFolderLocation.Append(L"\\hostfxr.dll");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hModule = LoadLibraryW(strDotnetFolderLocation.QueryStr());
|
||||
// should be a redudant call here, but we will be safe and call it twice.
|
||||
// TODO AV here on m_pHostFxrParameters being null
|
||||
hModule = LoadLibraryW(m_pConfig->QueryHostFxrFullPath());
|
||||
|
||||
if (hModule == NULL)
|
||||
{
|
||||
|
|
@ -791,17 +562,10 @@ IN_PROCESS_APPLICATION::ExecuteApplication(
|
|||
pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main");
|
||||
if (pProc == NULL)
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT; // better hrresult?
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// The first argument is mostly ignored
|
||||
argv[0] = strDotnetExeLocation.QueryStr();
|
||||
UTILITY::ConvertPathToFullPath(m_pConfig->QueryArguments()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->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
|
||||
|
|
@ -811,7 +575,7 @@ IN_PROCESS_APPLICATION::ExecuteApplication(
|
|||
// set the callbacks
|
||||
s_Application = this;
|
||||
|
||||
RunDotnetApplication(argv, pProc);
|
||||
RunDotnetApplication(m_pConfig->QueryHostFxrArgCount(), m_pConfig->QueryHostFxrArguments(), pProc);
|
||||
|
||||
Finished:
|
||||
//
|
||||
|
|
@ -862,19 +626,20 @@ Finished:
|
|||
// Calls hostfxr_main with the hostfxr and application as arguments.
|
||||
// Method should be called with only
|
||||
// Need to have __try / __except in methods that require unwinding.
|
||||
// Note, this will not
|
||||
//
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::RunDotnetApplication(PCWSTR* argv, hostfxr_main_fn pProc)
|
||||
IN_PROCESS_APPLICATION::RunDotnetApplication(DWORD argc, CONST PCWSTR* argv, hostfxr_main_fn pProc)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
__try
|
||||
{
|
||||
m_ProcessExitCode = pProc(2, argv);
|
||||
m_ProcessExitCode = pProc(argc, argv);
|
||||
}
|
||||
__except (FilterException(GetExceptionCode(), GetExceptionInformation()))
|
||||
{
|
||||
// TODO Log error message here.
|
||||
hr = E_FAIL;
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@ typedef void(*request_handler_cb) (int error, IHttpContext* pHttpContext, void*
|
|||
typedef REQUEST_NOTIFICATION_STATUS(*PFN_REQUEST_HANDLER) (IN_PROCESS_HANDLER* pInProcessHandler, void* pvRequestHandlerContext);
|
||||
typedef BOOL(*PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext);
|
||||
typedef REQUEST_NOTIFICATION_STATUS(*PFN_MANAGED_CONTEXT_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion);
|
||||
typedef DWORD(*hostfxr_main_fn) (CONST DWORD argc, CONST WCHAR* argv[]);
|
||||
|
||||
class IN_PROCESS_APPLICATION : public APPLICATION
|
||||
{
|
||||
public:
|
||||
IN_PROCESS_APPLICATION(IHttpServer* pHttpServer, ASPNETCORE_CONFIG *pConfig);
|
||||
IN_PROCESS_APPLICATION(IHttpServer* pHttpServer, ASPNETCORE_CONFIG* pConfig);
|
||||
|
||||
~IN_PROCESS_APPLICATION();
|
||||
|
||||
|
|
@ -59,16 +58,6 @@ public:
|
|||
IN_PROCESS_HANDLER* pInProcessHandler
|
||||
);
|
||||
|
||||
static
|
||||
INT
|
||||
FilterException(unsigned int code, struct _EXCEPTION_POINTERS *ep);
|
||||
|
||||
HRESULT
|
||||
RunDotnetApplication(
|
||||
PCWSTR* argv,
|
||||
hostfxr_main_fn pProc
|
||||
);
|
||||
|
||||
static
|
||||
IN_PROCESS_APPLICATION*
|
||||
GetInstance(
|
||||
|
|
@ -120,35 +109,20 @@ private:
|
|||
VOID
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
_Out_ std::vector<std::wstring> *pvFolders
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
FindHighestDotNetVersion(
|
||||
_In_ std::vector<std::wstring> vFolders,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
BOOL
|
||||
DirectoryExists(
|
||||
_In_ STRU *pstrPath //todo: this does not need to be stru, can be PCWSTR
|
||||
);
|
||||
|
||||
static BOOL
|
||||
GetEnv(
|
||||
_In_ PCWSTR pszEnvironmentVariable,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
);
|
||||
|
||||
static
|
||||
INT
|
||||
FilterException(unsigned int code, struct _EXCEPTION_POINTERS *ep);
|
||||
|
||||
HRESULT
|
||||
RunDotnetApplication(
|
||||
DWORD argc,
|
||||
CONST PCWSTR* argv,
|
||||
hostfxr_main_fn pProc
|
||||
);
|
||||
};
|
||||
|
|
@ -127,7 +127,7 @@ struct IISConfigurationData
|
|||
};
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT // TODO probably should make this a wide string
|
||||
HRESULT
|
||||
http_get_application_properties(
|
||||
_In_ IISConfigurationData* pIISCofigurationData
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue