Panwang/refactor (#277)
* Init check in for refactoring * clean up to make app_offline work * update loadassembly and build * add configpath to aspnetcore_config to make recycle work * Adds in process component to refactor (#249) * outprocess first checkin (still missing marjor components) * Adds In-Process support for shimmed module. (#257) * Init check in for refactoring * clean up to make app_offline work * update loadassembly and build * add configpath to aspnetcore_config to make recycle work * Adds in process component to refactor (#249) * outprocess first checkin (still missing marjor components) * Adds In-Process support for shimmed module. (#257) * load from bin start and catch unhandled exception * Fixes request handler vcxproj * Adds request handler to nuget package * build issues * outofprocess refactoring * adding logging support * enforce Warning As Error for build and enable process recycle for outofprocess * fix AV for win32 build and update build flags * Fixed m_srwLock lock issue * remove dealock in loadmanagedapp and remove UseMFC * Readd lost exception catching * nuget package issue and status code * fixing warnings * Adds Headers * removing web sockets exe for now * remove flags * nuspec stuff * spelling * only look in inetsvr for now (or same folder) * rename method * terminte thread before closing the handle to it * couple changes related with AV * null check and Kill thread for in process if dotnet timed out * fix recursive lock issue reported by appverifier * client disconnect support AV fix * flow 502.5 process start failure error page * Feedback from inperson code review
This commit is contained in:
Родитель
588f0768e1
Коммит
3b6a01945e
|
@ -32,12 +32,15 @@ project.lock.json
|
|||
*.obj
|
||||
*.tlog
|
||||
*.CppClean.log
|
||||
*msbuild.log
|
||||
|
||||
src/*/Debug/
|
||||
src/*/x64/Debug/
|
||||
src/*/Release/
|
||||
src/*/x64/Release/
|
||||
x64/
|
||||
|
||||
*vcxproj.filters
|
||||
*.aps
|
||||
*.pdb
|
||||
*.lib
|
||||
|
|
|
@ -8,6 +8,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AspNetCore", "src\AspNetCor
|
|||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE} = {4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RequestHandler", "src\RequestHandler\RequestHandler.vcxproj", "{D57EA297-6DC2-4BC0-8C91-334863327863}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IISLib", "src\IISLib\IISLib.vcxproj", "{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{02F461DC-5166-4E88-AAD5-CF110016A647}"
|
||||
|
@ -23,6 +25,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
NuGet.Config = NuGet.Config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "src\CommonLib\CommonLib.vcxproj", "{55494E58-E061-4C4C-A0A8-837008E72F85}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -34,8 +38,8 @@ Global
|
|||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Win32.ActiveCfg = Release|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Win32.Build.0 = Release|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Win32.ActiveCfg = Debug|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Win32.Build.0 = Debug|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|x64.Build.0 = Debug|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
|
@ -43,9 +47,19 @@ Global
|
|||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|Win32.Build.0 = Release|Win32
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x64.ActiveCfg = Release|x64
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x64.Build.0 = Release|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|Win32.ActiveCfg = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|Win32.Build.0 = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x64.Build.0 = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|Win32.Build.0 = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.ActiveCfg = Release|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.Build.0 = Release|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Win32.ActiveCfg = Release|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Win32.Build.0 = Release|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Win32.ActiveCfg = Debug|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Win32.Build.0 = Debug|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|x64.Build.0 = Debug|x64
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
|
@ -77,15 +91,31 @@ Global
|
|||
{030225D8-4EE8-47E5-B692-2A96B3B51A38}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{030225D8-4EE8-47E5-B692-2A96B3B51A38}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{030225D8-4EE8-47E5-B692-2A96B3B51A38}.Release|x64.Build.0 = Release|Any CPU
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Win32.ActiveCfg = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Win32.Build.0 = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Win32.Deploy.0 = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x64.Build.0 = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Win32.Build.0 = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Win32.Deploy.0 = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x64.ActiveCfg = Release|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x64.Build.0 = Release|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x64.Deploy.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {FDD2EDF8-1B62-4978-9815-9D95260B8B91}
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {FDD2EDF8-1B62-4978-9815-9D95260B8B91}
|
||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE} = {FDD2EDF8-1B62-4978-9815-9D95260B8B91}
|
||||
{4DDA7560-AA29-4161-A5EA-A7E8F3997321} = {02F461DC-5166-4E88-AAD5-CF110016A647}
|
||||
{030225D8-4EE8-47E5-B692-2A96B3B51A38} = {02F461DC-5166-4E88-AAD5-CF110016A647}
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85} = {FDD2EDF8-1B62-4978-9815-9D95260B8B91}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0967E9B4-FEE7-40D7-860A-23E340E65840}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<Import Project="$(MSBuildThisFileDirectory)\Build.Settings" />
|
||||
<ItemGroup>
|
||||
<Projects Include="$(SolutionDir)\src\AspNetCore\AspNetCore.vcxproj" />
|
||||
<Projects Include="$(SolutionDir)\src\RequestHandler\RequestHandler.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Build">
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" "$(RepositoryRoot)src\AspNetCore\AspNetCore.vcxproj" %(BuildConfigurations.Identity)"
|
||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" "$(RepositoryRoot)src\RequestHandler\RequestHandler.vcxproj" %(BuildConfigurations.Identity)"
|
||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PackageProjects">
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
<files>
|
||||
<file src="..\artifacts\build\AspNetCore\bin\Release\Win32\aspnetcore.dll" target="contentFiles\any\any\x86\aspnetcore.dll" />
|
||||
<file src="..\artifacts\build\AspNetCore\bin\Release\x64\aspnetcore.dll" target="contentFiles\any\any\x64\aspnetcore.dll" />
|
||||
<file src="..\artifacts\build\AspNetCore\bin\Release\Win32\aspnetcorerh.dll" target="contentFiles\any\any\x86\aspnetcorerh.dll" />
|
||||
<file src="..\artifacts\build\AspNetCore\bin\Release\x64\aspnetcorerh.dll" target="contentFiles\any\any\x64\aspnetcorerh.dll" />
|
||||
<file src="..\artifacts\build\AspNetCore\bin\Release\x64\*.xml"/>
|
||||
<file src="..\tools\installancm.ps1"/>
|
||||
<file src="..\LICENSE.txt"/>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
<PropertyGroup>
|
||||
<AspNetCoreModuleX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\aspnetcore.dll</AspNetCoreModuleX64Location>
|
||||
<AspNetCoreModuleX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcore.dll</AspNetCoreModuleX86Location>
|
||||
<RequestHandlerX64Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x64\aspnetcorerh.dll</RequestHandlerX64Location>
|
||||
<RequestHandlerX86Location>$(MSBuildThisFileDirectory)..\contentFiles\any\any\x86\aspnetcorerh.dll</RequestHandlerX86Location>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
|
@ -75,16 +74,34 @@
|
|||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<OutDir>$(SolutionDir)artifacts\build\$(ProjectName)\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)artifacts\build\$(ProjectName)\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)artifacts\build\$(ProjectName)\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ASPNETCOREMODULE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalIncludeDirectories>..\IISLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -104,6 +121,17 @@
|
|||
<AdditionalIncludeDirectories>..\IISLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -123,6 +151,17 @@
|
|||
<AdditionalIncludeDirectories>..\IISLib;inc</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -144,6 +183,17 @@
|
|||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>..\IISLib;inc</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -155,52 +205,22 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Inc\aspnetcore_event.h" />
|
||||
<ClInclude Include="Inc\applicationinfo.h" />
|
||||
<ClInclude Include="Inc\appoffline.h" />
|
||||
<ClInclude Include="inc\globalmodule.h" />
|
||||
<ClInclude Include="Inc\resource.h" />
|
||||
<ClInclude Include="Inc\application.h" />
|
||||
<ClInclude Include="Inc\applicationmanager.h" />
|
||||
<ClInclude Include="Inc\aspnetcoreconfig.h" />
|
||||
<ClInclude Include="Inc\environmentvariablehash.h" />
|
||||
<ClInclude Include="Inc\debugutil.h" />
|
||||
<ClInclude Include="Inc\filewatcher.h" />
|
||||
<ClInclude Include="Inc\forwarderconnection.h" />
|
||||
<ClInclude Include="Inc\forwardinghandler.h" />
|
||||
<ClInclude Include="Inc\path.h" />
|
||||
<ClInclude Include="Inc\processmanager.h" />
|
||||
<ClInclude Include="Inc\protocolconfig.h" />
|
||||
<ClInclude Include="Inc\proxymodule.h" />
|
||||
<ClInclude Include="Inc\responseheaderhash.h" />
|
||||
<ClInclude Include="Inc\serverprocess.h" />
|
||||
<ClInclude Include="Inc\sttimer.h" />
|
||||
<ClInclude Include="Inc\websockethandler.h" />
|
||||
<ClInclude Include="Inc\winhttphelper.h" />
|
||||
<ClInclude Include="Inc\fx_ver.h" />
|
||||
<ClInclude Include="Inc\inprocessapplication.h" />
|
||||
<ClInclude Include="Inc\outprocessapplication.h" />
|
||||
<ClInclude Include="Inc\inprocessstoredcontext.h" />
|
||||
<ClInclude Include="Src\precomp.hxx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\inprocessstoredcontext.cxx" />
|
||||
<ClCompile Include="Src\inprocessapplication.cxx" />
|
||||
<ClCompile Include="Src\managedexports.cxx" />
|
||||
<ClCompile Include="Src\outprocessapplication.cxx" />
|
||||
<ClCompile Include="Src\application.cxx" />
|
||||
<ClCompile Include="Src\applicationinfo.cpp" />
|
||||
<ClCompile Include="Src\applicationmanager.cxx" />
|
||||
<ClCompile Include="Src\aspnetcoreconfig.cxx" />
|
||||
<ClCompile Include="Src\dllmain.cpp" />
|
||||
<ClCompile Include="Src\filewatcher.cxx" />
|
||||
<ClCompile Include="Src\forwarderconnection.cxx" />
|
||||
<ClCompile Include="Src\forwardinghandler.cxx" />
|
||||
<ClCompile Include="Src\fx_ver.cxx" />
|
||||
<ClCompile Include="Src\path.cxx" />
|
||||
<ClCompile Include="Src\processmanager.cxx" />
|
||||
<ClCompile Include="Src\protocolconfig.cxx" />
|
||||
<ClCompile Include="src\globalmodule.cpp" />
|
||||
<ClCompile Include="Src\proxymodule.cxx" />
|
||||
<ClCompile Include="Src\responseheaderhash.cxx" />
|
||||
<ClCompile Include="Src\serverprocess.cxx" />
|
||||
<ClCompile Include="Src\websockethandler.cxx" />
|
||||
<ClCompile Include="Src\winhttphelper.cxx" />
|
||||
</ItemGroup>
|
||||
<Target Name="CreateVersionHeader" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
@ -221,29 +241,16 @@
|
|||
</ItemGroup>
|
||||
<WriteLinesToFile File="version.h" Lines="@(VersionHeaderContents)" OverWrite="true" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="Src\aspnetcore_msg.mc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="aspnetcoremodule.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommonLib\CommonLib.vcxproj">
|
||||
<Project>{55494e58-e061-4c4c-a0a8-837008e72f85}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
||||
<Project>{4787a64f-9a3e-4867-a55a-70cb4b2b2ffe}</Project>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -254,6 +261,9 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xml Include="aspnetcore_schema.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -1,286 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// The key used for hash-table lookups, consists of the port on which the http process is created.
|
||||
//
|
||||
class APPLICATION_KEY
|
||||
{
|
||||
public:
|
||||
|
||||
APPLICATION_KEY(
|
||||
VOID
|
||||
) : INLINE_STRU_INIT(m_struKey)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Initialize(
|
||||
_In_ LPCWSTR pszKey
|
||||
)
|
||||
{
|
||||
return m_struKey.Copy(pszKey);
|
||||
}
|
||||
|
||||
BOOL
|
||||
GetIsEqual(
|
||||
const APPLICATION_KEY * key2
|
||||
) const
|
||||
{
|
||||
return m_struKey.Equals(key2->m_struKey);
|
||||
}
|
||||
|
||||
DWORD CalcKeyHash() const
|
||||
{
|
||||
return Hash(m_struKey.QueryStr());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
INLINE_STRU(m_struKey, 1024);
|
||||
};
|
||||
|
||||
class APP_OFFLINE_HTM
|
||||
{
|
||||
public:
|
||||
APP_OFFLINE_HTM(LPCWSTR pszPath) : m_cRefs(1)
|
||||
{
|
||||
m_Path.Copy( pszPath );
|
||||
}
|
||||
|
||||
VOID
|
||||
ReferenceAppOfflineHtm() const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceAppOfflineHtm() const
|
||||
{
|
||||
if (InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
Load(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
BOOL fResult = TRUE;
|
||||
LARGE_INTEGER li = {0};
|
||||
CHAR *pszBuff = NULL;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
handle = CreateFile( m_Path.QueryStr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
|
||||
if( handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
if ( GetLastError() == ERROR_FILE_NOT_FOUND )
|
||||
{
|
||||
fResult = FALSE;
|
||||
}
|
||||
|
||||
// This Load() member function is supposed be called only when the change notification event of file creation or file modification happens.
|
||||
// If file is currenlty locked exclusively by other processes, we might get INVALID_HANDLE_VALUE even though the file exists. In that case, we should return TRUE here.
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if(!GetFileSizeEx( handle, &li ))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if( li.HighPart != 0 )
|
||||
{
|
||||
// > 4gb file size not supported
|
||||
// todo: log a warning at event log
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
|
||||
if(li.LowPart > 0)
|
||||
{
|
||||
pszBuff = new CHAR[ li.LowPart + 1 ];
|
||||
|
||||
if( ReadFile( handle, pszBuff, li.LowPart, &bytesRead, NULL ) )
|
||||
{
|
||||
m_Contents.Copy( pszBuff, bytesRead );
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
if( handle != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
CloseHandle(handle);
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if( pszBuff != NULL )
|
||||
{
|
||||
delete[] pszBuff;
|
||||
pszBuff = NULL;
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
STRA m_Contents;
|
||||
STRU m_Path;
|
||||
};
|
||||
|
||||
class APPLICATION_MANAGER;
|
||||
|
||||
class APPLICATION
|
||||
{
|
||||
public:
|
||||
|
||||
APPLICATION() : m_pApplicationManager(NULL), m_cRefs(1),
|
||||
m_fAppOfflineFound(FALSE), m_pAppOfflineHtm(NULL),
|
||||
m_pFileWatcherEntry(NULL), m_pConfiguration(NULL)
|
||||
{
|
||||
InitializeSRWLock(&m_srwLock);
|
||||
}
|
||||
|
||||
APPLICATION_KEY *
|
||||
QueryApplicationKey()
|
||||
{
|
||||
return &m_applicationKey;
|
||||
}
|
||||
|
||||
virtual
|
||||
~APPLICATION();
|
||||
|
||||
virtual
|
||||
HRESULT
|
||||
Initialize(
|
||||
_In_ APPLICATION_MANAGER *pApplicationManager,
|
||||
_In_ ASPNETCORE_CONFIG *pConfiguration) = 0;
|
||||
|
||||
VOID
|
||||
ReferenceApplication() const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceApplication() const
|
||||
{
|
||||
if (InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
APP_OFFLINE_HTM* QueryAppOfflineHtm()
|
||||
{
|
||||
return m_pAppOfflineHtm;
|
||||
}
|
||||
|
||||
BOOL
|
||||
AppOfflineFound()
|
||||
{
|
||||
return m_fAppOfflineFound;
|
||||
}
|
||||
|
||||
virtual
|
||||
VOID
|
||||
OnAppOfflineHandleChange() = 0;
|
||||
|
||||
VOID
|
||||
UpdateAppOfflineFileHandle();
|
||||
|
||||
HRESULT
|
||||
StartMonitoringAppOffline();
|
||||
|
||||
ASPNETCORE_CONFIG*
|
||||
QueryConfig()
|
||||
{
|
||||
return m_pConfiguration;
|
||||
}
|
||||
|
||||
virtual
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
ExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
APPLICATION_KEY m_applicationKey;
|
||||
APPLICATION_MANAGER *m_pApplicationManager;
|
||||
BOOL m_fAppOfflineFound;
|
||||
APP_OFFLINE_HTM *m_pAppOfflineHtm;
|
||||
FILE_WATCHER_ENTRY *m_pFileWatcherEntry;
|
||||
ASPNETCORE_CONFIG *m_pConfiguration;
|
||||
SRWLOCK m_srwLock;
|
||||
|
||||
};
|
||||
|
||||
class APPLICATION_HASH :
|
||||
public HASH_TABLE<APPLICATION, APPLICATION_KEY *>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
APPLICATION_HASH()
|
||||
{}
|
||||
|
||||
APPLICATION_KEY *
|
||||
ExtractKey(
|
||||
APPLICATION *pApplication
|
||||
)
|
||||
{
|
||||
return pApplication->QueryApplicationKey();
|
||||
}
|
||||
|
||||
DWORD
|
||||
CalcKeyHash(
|
||||
APPLICATION_KEY *key
|
||||
)
|
||||
{
|
||||
return key->CalcKeyHash();
|
||||
}
|
||||
|
||||
BOOL
|
||||
EqualKeys(
|
||||
APPLICATION_KEY *key1,
|
||||
APPLICATION_KEY *key2
|
||||
)
|
||||
{
|
||||
return key1->GetIsEqual(key2);
|
||||
}
|
||||
|
||||
VOID
|
||||
ReferenceRecord(
|
||||
APPLICATION *pApplication
|
||||
)
|
||||
{
|
||||
pApplication->ReferenceApplication();
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceRecord(
|
||||
APPLICATION *pApplication
|
||||
)
|
||||
{
|
||||
pApplication->DereferenceApplication();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
APPLICATION_HASH(const APPLICATION_HASH &);
|
||||
void operator=(const APPLICATION_HASH &);
|
||||
};
|
|
@ -0,0 +1,218 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef
|
||||
HRESULT
|
||||
(WINAPI * PFN_ASPNETCORE_CREATE_APPLICATION)(
|
||||
_In_ IHttpServer *pServer,
|
||||
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||
_Out_ APPLICATION **pApplication
|
||||
);
|
||||
|
||||
typedef
|
||||
HRESULT
|
||||
(WINAPI * PFN_ASPNETCORE_CREATE_REQUEST_HANDLER)(
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication,
|
||||
_Out_ REQUEST_HANDLER **pRequestHandler
|
||||
);
|
||||
//
|
||||
// The key used for hash-table lookups, consists of the port on which the http process is created.
|
||||
//
|
||||
class APPLICATION_INFO_KEY
|
||||
{
|
||||
public:
|
||||
|
||||
APPLICATION_INFO_KEY(
|
||||
VOID
|
||||
) : INLINE_STRU_INIT(m_struKey)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Initialize(
|
||||
_In_ LPCWSTR pszKey
|
||||
)
|
||||
{
|
||||
return m_struKey.Copy(pszKey);
|
||||
}
|
||||
|
||||
BOOL
|
||||
GetIsEqual(
|
||||
const APPLICATION_INFO_KEY * key2
|
||||
) const
|
||||
{
|
||||
return m_struKey.Equals(key2->m_struKey);
|
||||
}
|
||||
|
||||
DWORD CalcKeyHash() const
|
||||
{
|
||||
return Hash(m_struKey.QueryStr());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
INLINE_STRU(m_struKey, 1024);
|
||||
};
|
||||
|
||||
|
||||
class APPLICATION_INFO
|
||||
{
|
||||
public:
|
||||
|
||||
APPLICATION_INFO(IHttpServer *pServer) :
|
||||
m_pServer(pServer),
|
||||
m_cRefs(1), m_fAppOfflineFound(FALSE),
|
||||
m_pAppOfflineHtm(NULL), m_pFileWatcherEntry(NULL),
|
||||
m_pConfiguration(NULL),
|
||||
m_pfnAspNetCoreCreateApplication(NULL),
|
||||
m_pfnAspNetCoreCreateRequestHandler(NULL)
|
||||
{
|
||||
InitializeSRWLock(&m_srwLock);
|
||||
}
|
||||
|
||||
APPLICATION_INFO_KEY *
|
||||
QueryApplicationInfoKey()
|
||||
{
|
||||
return &m_applicationInfoKey;
|
||||
}
|
||||
|
||||
virtual
|
||||
~APPLICATION_INFO();
|
||||
|
||||
HRESULT
|
||||
Initialize(
|
||||
_In_ ASPNETCORE_CONFIG *pConfiguration,
|
||||
_In_ FILE_WATCHER *pFileWatcher
|
||||
);
|
||||
|
||||
VOID
|
||||
ReferenceApplicationInfo() const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceApplicationInfo() const
|
||||
{
|
||||
if (InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
APP_OFFLINE_HTM* QueryAppOfflineHtm()
|
||||
{
|
||||
return m_pAppOfflineHtm;
|
||||
}
|
||||
|
||||
BOOL
|
||||
AppOfflineFound()
|
||||
{
|
||||
return m_fAppOfflineFound;
|
||||
}
|
||||
|
||||
VOID
|
||||
UpdateAppOfflineFileHandle();
|
||||
|
||||
HRESULT
|
||||
StartMonitoringAppOffline();
|
||||
|
||||
ASPNETCORE_CONFIG*
|
||||
QueryConfig()
|
||||
{
|
||||
return m_pConfiguration;
|
||||
}
|
||||
|
||||
APPLICATION*
|
||||
QueryApplication()
|
||||
{
|
||||
return m_pApplication;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
EnsureApplicationCreated();
|
||||
|
||||
PFN_ASPNETCORE_CREATE_REQUEST_HANDLER
|
||||
QueryCreateRequestHandler()
|
||||
{
|
||||
return m_pfnAspNetCoreCreateRequestHandler;
|
||||
}
|
||||
|
||||
private:
|
||||
HRESULT FindRequestHandlerAssembly();
|
||||
HRESULT FindNativeAssemblyFromGlobalLocation(STRU* struFilename);
|
||||
HRESULT FindNativeAssemblyFromLocalBin(STRU* struFilename);
|
||||
HRESULT GetRequestHandlerFromRuntimeStore(STRU* struFilename);
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
APPLICATION_INFO_KEY m_applicationInfoKey;
|
||||
BOOL m_fAppOfflineFound;
|
||||
APP_OFFLINE_HTM *m_pAppOfflineHtm;
|
||||
FILE_WATCHER_ENTRY *m_pFileWatcherEntry;
|
||||
ASPNETCORE_CONFIG *m_pConfiguration;
|
||||
APPLICATION *m_pApplication;
|
||||
SRWLOCK m_srwLock;
|
||||
IHttpServer *m_pServer;
|
||||
PFN_ASPNETCORE_CREATE_APPLICATION m_pfnAspNetCoreCreateApplication;
|
||||
PFN_ASPNETCORE_CREATE_REQUEST_HANDLER m_pfnAspNetCoreCreateRequestHandler;
|
||||
};
|
||||
|
||||
class APPLICATION_INFO_HASH :
|
||||
public HASH_TABLE<APPLICATION_INFO, APPLICATION_INFO_KEY *>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
APPLICATION_INFO_HASH()
|
||||
{}
|
||||
|
||||
APPLICATION_INFO_KEY *
|
||||
ExtractKey(
|
||||
APPLICATION_INFO *pApplicationInfo
|
||||
)
|
||||
{
|
||||
return pApplicationInfo->QueryApplicationInfoKey();
|
||||
}
|
||||
|
||||
DWORD
|
||||
CalcKeyHash(
|
||||
APPLICATION_INFO_KEY *key
|
||||
)
|
||||
{
|
||||
return key->CalcKeyHash();
|
||||
}
|
||||
|
||||
BOOL
|
||||
EqualKeys(
|
||||
APPLICATION_INFO_KEY *key1,
|
||||
APPLICATION_INFO_KEY *key2
|
||||
)
|
||||
{
|
||||
return key1->GetIsEqual(key2);
|
||||
}
|
||||
|
||||
VOID
|
||||
ReferenceRecord(
|
||||
APPLICATION_INFO *pApplicationInfo
|
||||
)
|
||||
{
|
||||
pApplicationInfo->ReferenceApplicationInfo();
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceRecord(
|
||||
APPLICATION_INFO *pApplicationInfo
|
||||
)
|
||||
{
|
||||
pApplicationInfo->DereferenceApplicationInfo();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
APPLICATION_INFO_HASH(const APPLICATION_INFO_HASH &);
|
||||
void operator=(const APPLICATION_INFO_HASH &);
|
||||
};
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
#define DEFAULT_HASH_BUCKETS 293
|
||||
|
||||
//
|
||||
// This class will manage the lifecycle of all Asp.Net Core applciation
|
||||
// It should be global singleton.
|
||||
// Should always call GetInstance to get the object instance
|
||||
//
|
||||
class APPLICATION_MANAGER
|
||||
{
|
||||
public:
|
||||
|
@ -15,12 +20,12 @@ public:
|
|||
VOID
|
||||
)
|
||||
{
|
||||
if( sm_pApplicationManager == NULL )
|
||||
if ( sm_pApplicationManager == NULL )
|
||||
{
|
||||
sm_pApplicationManager = new APPLICATION_MANAGER();
|
||||
}
|
||||
|
||||
return sm_pApplicationManager;
|
||||
return sm_pApplicationManager;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -37,29 +42,27 @@ public:
|
|||
}
|
||||
|
||||
HRESULT
|
||||
GetApplication(
|
||||
_In_ IHttpContext* pContext,
|
||||
GetApplicationInfo(
|
||||
_In_ IHttpServer* pServer,
|
||||
_In_ ASPNETCORE_CONFIG* pConfig,
|
||||
_Out_ APPLICATION ** ppApplication
|
||||
_Out_ APPLICATION_INFO ** ppApplicationInfo
|
||||
);
|
||||
|
||||
HRESULT
|
||||
RecycleApplication(
|
||||
_In_ LPCWSTR pszApplication
|
||||
RecycleApplication(
|
||||
_In_ LPCWSTR pszApplicationId
|
||||
);
|
||||
|
||||
HRESULT
|
||||
Get502ErrorPage(
|
||||
_Out_ HTTP_DATA_CHUNK** ppErrorPage
|
||||
);
|
||||
VOID
|
||||
ShutDown();
|
||||
|
||||
~APPLICATION_MANAGER()
|
||||
{
|
||||
if(m_pApplicationHash != NULL)
|
||||
if(m_pApplicationInfoHash != NULL)
|
||||
{
|
||||
m_pApplicationHash->Clear();
|
||||
delete m_pApplicationHash;
|
||||
m_pApplicationHash = NULL;
|
||||
m_pApplicationInfoHash->Clear();
|
||||
delete m_pApplicationInfoHash;
|
||||
m_pApplicationInfoHash = NULL;
|
||||
}
|
||||
|
||||
if( m_pFileWatcher!= NULL )
|
||||
|
@ -67,13 +70,6 @@ public:
|
|||
delete m_pFileWatcher;
|
||||
m_pFileWatcher = NULL;
|
||||
}
|
||||
|
||||
if(m_pHttp502ErrorPage != NULL)
|
||||
{
|
||||
delete m_pHttp502ErrorPage;
|
||||
m_pHttp502ErrorPage = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FILE_WATCHER*
|
||||
|
@ -86,16 +82,16 @@ public:
|
|||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if(m_pApplicationHash == NULL)
|
||||
if(m_pApplicationInfoHash == NULL)
|
||||
{
|
||||
m_pApplicationHash = new APPLICATION_HASH();
|
||||
if(m_pApplicationHash == NULL)
|
||||
m_pApplicationInfoHash = new APPLICATION_INFO_HASH();
|
||||
if(m_pApplicationInfoHash == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_pApplicationHash->Initialize(DEFAULT_HASH_BUCKETS);
|
||||
hr = m_pApplicationInfoHash->Initialize(DEFAULT_HASH_BUCKETS);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
|
@ -122,41 +118,18 @@ private:
|
|||
//
|
||||
// we currently limit the size of m_pstrErrorInfo to 5000, be careful if you want to change its payload
|
||||
//
|
||||
APPLICATION_MANAGER() : m_pApplicationHash(NULL), m_pFileWatcher(NULL),
|
||||
m_pHttp502ErrorPage(NULL), m_hostingModel(HOSTING_UNKNOWN),
|
||||
m_pstrErrorInfo(
|
||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> \
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\"> \
|
||||
<head> \
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" /> \
|
||||
<title> IIS 502.5 Error </title><style type=\"text/css\"></style></head> \
|
||||
<body> <div id = \"content\"> \
|
||||
<div class = \"content-container\"><h3> HTTP Error 502.5 - Process Failure </h3></div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset> <h4> Common causes of this issue: </h4> \
|
||||
<ul><li> The application process failed to start </li> \
|
||||
<li> The application process started but then stopped </li> \
|
||||
<li> The application process started but failed to listen on the configured port </li></ul></fieldset> \
|
||||
</div> \
|
||||
<div class = \"content-container\"> \
|
||||
<fieldset><h4> Troubleshooting steps: </h4> \
|
||||
<ul><li> Check the system event log for error messages </li> \
|
||||
<li> Enable logging the application process' stdout messages </li> \
|
||||
<li> Attach a debugger to the application process and inspect </li></ul></fieldset> \
|
||||
<fieldset><h4> For more information visit: \
|
||||
<a href=\"https://go.microsoft.com/fwlink/?linkid=808681\"> <cite> https://go.microsoft.com/fwlink/?LinkID=808681 </cite></a></h4> \
|
||||
</fieldset> \
|
||||
</div> \
|
||||
</div></body></html>")
|
||||
APPLICATION_MANAGER() : m_pApplicationInfoHash(NULL),
|
||||
m_pFileWatcher(NULL),
|
||||
m_hostingModel(HOSTING_UNKNOWN),
|
||||
m_fInShutdown(FALSE)
|
||||
{
|
||||
InitializeSRWLock(&m_srwLock);
|
||||
}
|
||||
|
||||
FILE_WATCHER *m_pFileWatcher;
|
||||
APPLICATION_HASH *m_pApplicationHash;
|
||||
APPLICATION_INFO_HASH *m_pApplicationInfoHash;
|
||||
static APPLICATION_MANAGER *sm_pApplicationManager;
|
||||
SRWLOCK m_srwLock;
|
||||
HTTP_DATA_CHUNK *m_pHttp502ErrorPage;
|
||||
LPSTR m_pstrErrorInfo;
|
||||
APP_HOSTING_MODEL m_hostingModel;
|
||||
bool m_fInShutdown;
|
||||
};
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
class APP_OFFLINE_HTM
|
||||
{
|
||||
public:
|
||||
APP_OFFLINE_HTM(LPCWSTR pszPath) : m_cRefs(1)
|
||||
{
|
||||
m_Path.Copy(pszPath);
|
||||
}
|
||||
|
||||
VOID
|
||||
ReferenceAppOfflineHtm() const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
DereferenceAppOfflineHtm() const
|
||||
{
|
||||
if (InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
Load(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
BOOL fResult = TRUE;
|
||||
LARGE_INTEGER li = { 0 };
|
||||
CHAR *pszBuff = NULL;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
handle = CreateFile(m_Path.QueryStr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
fResult = FALSE;
|
||||
}
|
||||
|
||||
// This Load() member function is supposed be called only when the change notification event of file creation or file modification happens.
|
||||
// If file is currenlty locked exclusively by other processes, we might get INVALID_HANDLE_VALUE even though the file exists. In that case, we should return TRUE here.
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!GetFileSizeEx(handle, &li))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (li.HighPart != 0)
|
||||
{
|
||||
// > 4gb file size not supported
|
||||
// todo: log a warning at event log
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
|
||||
if (li.LowPart > 0)
|
||||
{
|
||||
pszBuff = new CHAR[li.LowPart + 1];
|
||||
|
||||
if (ReadFile(handle, pszBuff, li.LowPart, &bytesRead, NULL))
|
||||
{
|
||||
m_Contents.Copy(pszBuff, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (pszBuff != NULL)
|
||||
{
|
||||
delete[] pszBuff;
|
||||
pszBuff = NULL;
|
||||
}
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
STRA m_Contents;
|
||||
STRU m_Path;
|
||||
};
|
|
@ -19,7 +19,7 @@
|
|||
#define FILE_WATCHER_ENTRY_SIGNATURE ((DWORD) 'FWES')
|
||||
#define FILE_WATCHER_ENTRY_SIGNATURE_FREE ((DWORD) 'sewf')
|
||||
|
||||
class APPLICATION;
|
||||
class APPLICATION_INFO;
|
||||
|
||||
class FILE_WATCHER{
|
||||
public:
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
Create(
|
||||
_In_ PCWSTR pszDirectoryToMonitor,
|
||||
_In_ PCWSTR pszFileNameToMonitor,
|
||||
_In_ APPLICATION* pApplication,
|
||||
_In_ APPLICATION_INFO* pApplicationInfo,
|
||||
_In_ HANDLE hImpersonationToken
|
||||
);
|
||||
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
HANDLE _hImpersonationToken;
|
||||
HANDLE _hDirectory;
|
||||
FILE_WATCHER* _pFileMonitor;
|
||||
APPLICATION* _pApplication;
|
||||
APPLICATION_INFO* _pApplicationInfo;
|
||||
STRU _strFileName;
|
||||
STRU _strDirectoryName;
|
||||
LONG _lStopMonitorCalled;
|
||||
|
|
|
@ -1,446 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "forwarderconnection.h"
|
||||
#include "protocolconfig.h"
|
||||
#include "serverprocess.h"
|
||||
#include "application.h"
|
||||
#include "tracelog.h"
|
||||
#include "websockethandler.h"
|
||||
|
||||
enum FORWARDING_REQUEST_STATUS
|
||||
{
|
||||
FORWARDER_START,
|
||||
FORWARDER_SENDING_REQUEST,
|
||||
FORWARDER_RECEIVING_RESPONSE,
|
||||
FORWARDER_RECEIVED_WEBSOCKET_RESPONSE,
|
||||
FORWARDER_RESET_CONNECTION,
|
||||
FORWARDER_DONE
|
||||
};
|
||||
|
||||
extern HTTP_MODULE_ID g_pModuleId;
|
||||
extern IHttpServer * g_pHttpServer;
|
||||
extern BOOL g_fAsyncDisconnectAvailable;
|
||||
extern PCWSTR g_pszModuleName;
|
||||
extern HMODULE g_hModule;
|
||||
extern HMODULE g_hWinHttpModule;
|
||||
extern DWORD g_dwTlsIndex;
|
||||
extern DWORD g_OptionalWinHttpFlags;
|
||||
|
||||
enum MULTI_PART_POSITION
|
||||
{
|
||||
MULTI_PART_IN_BOUNDARY,
|
||||
MULTI_PART_IN_HEADER,
|
||||
MULTI_PART_IN_CHUNK,
|
||||
MULTI_PART_IN_CHUNK_END
|
||||
};
|
||||
|
||||
class ASYNC_DISCONNECT_CONTEXT;
|
||||
|
||||
#define FORWARDING_HANDLER_SIGNATURE ((DWORD)'FHLR')
|
||||
#define FORWARDING_HANDLER_SIGNATURE_FREE ((DWORD)'fhlr')
|
||||
|
||||
class FORWARDING_HANDLER
|
||||
{
|
||||
public:
|
||||
|
||||
FORWARDING_HANDLER(
|
||||
__in IHttpContext * pW3Context,
|
||||
__in APPLICATION * pApplication
|
||||
);
|
||||
|
||||
static void * operator new(size_t size);
|
||||
|
||||
static void operator delete(void * pMemory);
|
||||
|
||||
VOID
|
||||
ReferenceForwardingHandler(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
VOID
|
||||
DereferenceForwardingHandler(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnExecuteRequestHandler();
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
);
|
||||
|
||||
IHttpTraceContext *
|
||||
QueryTraceContext()
|
||||
{
|
||||
return m_pW3Context->GetTraceContext();
|
||||
}
|
||||
|
||||
IHttpContext *
|
||||
QueryHttpContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_pW3Context;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
CALLBACK
|
||||
OnWinHttpCompletion(
|
||||
HINTERNET hRequest,
|
||||
DWORD_PTR dwContext,
|
||||
DWORD dwInternetStatus,
|
||||
LPVOID lpvStatusInformation,
|
||||
DWORD dwStatusInformationLength
|
||||
)
|
||||
{
|
||||
|
||||
FORWARDING_HANDLER * pThis = static_cast<FORWARDING_HANDLER *>(reinterpret_cast<PVOID>(dwContext));
|
||||
if (pThis == NULL)
|
||||
{
|
||||
//error happened, nothing can be done here
|
||||
return;
|
||||
}
|
||||
DBG_ASSERT(pThis->m_Signature == FORWARDING_HANDLER_SIGNATURE);
|
||||
pThis->OnWinHttpCompletionInternal(hRequest,
|
||||
dwInternetStatus,
|
||||
lpvStatusInformation,
|
||||
dwStatusInformationLength);
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT
|
||||
StaticInitialize(
|
||||
BOOL fEnableReferenceCountTracing
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
StaticTerminate();
|
||||
|
||||
static
|
||||
PCWSTR
|
||||
QueryErrorFormat()
|
||||
{
|
||||
return sm_strErrorFormat.QueryStr();
|
||||
}
|
||||
|
||||
static
|
||||
HANDLE
|
||||
QueryEventLog()
|
||||
{
|
||||
return sm_hEventLog;
|
||||
}
|
||||
|
||||
VOID
|
||||
TerminateRequest(
|
||||
bool fClientInitiated
|
||||
);
|
||||
|
||||
static HINTERNET sm_hSession;
|
||||
|
||||
HRESULT
|
||||
SetStatusAndHeaders(
|
||||
PCSTR pszHeaders,
|
||||
DWORD cchHeaders
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnSharedRequestEntity(
|
||||
ULONGLONG ulOffset,
|
||||
LPCBYTE pvBuffer,
|
||||
DWORD cbBuffer
|
||||
);
|
||||
|
||||
VOID
|
||||
SetStatus(
|
||||
FORWARDING_REQUEST_STATUS status
|
||||
)
|
||||
{
|
||||
m_RequestStatus = status;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual
|
||||
~FORWARDING_HANDLER(
|
||||
VOID
|
||||
);
|
||||
|
||||
//
|
||||
// Begin OnMapRequestHandler phases.
|
||||
//
|
||||
|
||||
HRESULT
|
||||
CreateWinHttpRequest(
|
||||
__in const IHttpRequest * pRequest,
|
||||
__in const PROTOCOL_CONFIG * pProtocol,
|
||||
__in HINTERNET hConnect,
|
||||
__inout STRU * pstrUrl,
|
||||
ASPNETCORE_CONFIG* pAspNetCoreConfig,
|
||||
SERVER_PROCESS* pServerProcess
|
||||
);
|
||||
|
||||
//
|
||||
// End OnMapRequestHandler phases.
|
||||
//
|
||||
|
||||
VOID
|
||||
RemoveRequest();
|
||||
|
||||
HRESULT
|
||||
GetHeaders(
|
||||
const PROTOCOL_CONFIG * pProtocol,
|
||||
PCWSTR * ppszHeaders,
|
||||
DWORD * pcchHeaders,
|
||||
ASPNETCORE_CONFIG* pAspNetCoreConfig,
|
||||
SERVER_PROCESS* pServerProcess
|
||||
);
|
||||
|
||||
HRESULT
|
||||
DoReverseRewrite(
|
||||
__in IHttpResponse *pResponse
|
||||
);
|
||||
|
||||
BYTE *
|
||||
GetNewResponseBuffer(
|
||||
DWORD dwBufferSize
|
||||
);
|
||||
|
||||
VOID
|
||||
FreeResponseBuffers();
|
||||
|
||||
VOID
|
||||
OnWinHttpCompletionInternal(
|
||||
HINTERNET hRequest,
|
||||
DWORD dwInternetStatus,
|
||||
LPVOID lpvStatusInformation,
|
||||
DWORD dwStatusInformationLength
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionSendRequestOrWriteComplete(
|
||||
HINTERNET hRequest,
|
||||
DWORD dwInternetStatus,
|
||||
__out bool * pfClientError,
|
||||
__out bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusHeadersAvailable(
|
||||
HINTERNET hRequest,
|
||||
__out bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusDataAvailable(
|
||||
HINTERNET hRequest,
|
||||
DWORD dwBytes,
|
||||
__out bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusReadComplete(
|
||||
__in IHttpResponse * pResponse,
|
||||
DWORD dwStatusInformationLength,
|
||||
__out bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnSendingRequest(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus,
|
||||
__out bool * pfClientError
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnReceivingResponse();
|
||||
|
||||
HRESULT
|
||||
OnWebSocketWinHttpSendComplete(
|
||||
HINTERNET hRequest,
|
||||
LPVOID pvStatus,
|
||||
DWORD hrCompletion,
|
||||
DWORD cbCompletion,
|
||||
bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWebSocketWinHttpReceiveComplete(
|
||||
HINTERNET hRequest,
|
||||
LPVOID pvStatus,
|
||||
DWORD hrCompletion,
|
||||
DWORD cbCompletion,
|
||||
bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWebSocketIisSendComplete(
|
||||
DWORD hrCompletion,
|
||||
DWORD cbCompletion
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWebSocketIisReceiveComplete(
|
||||
DWORD hrCompletion,
|
||||
DWORD cbCompletion
|
||||
);
|
||||
|
||||
HRESULT
|
||||
DoIisWebSocketReceive(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
TerminateWebsocket(
|
||||
VOID
|
||||
);
|
||||
|
||||
HRESULT
|
||||
SetHttpSysDisconnectCallback(
|
||||
VOID
|
||||
);
|
||||
|
||||
DWORD m_Signature;
|
||||
mutable LONG m_cRefs;
|
||||
|
||||
IHttpContext * m_pW3Context;
|
||||
IHttpContext * m_pChildRequestContext;
|
||||
|
||||
//
|
||||
// WinHTTP request handle is protected using a read-write lock.
|
||||
//
|
||||
SRWLOCK m_RequestLock;
|
||||
HINTERNET m_hRequest;
|
||||
|
||||
APP_OFFLINE_HTM *m_pAppOfflineHtm;
|
||||
APPLICATION *m_pApplication;
|
||||
|
||||
bool m_fWebSocketEnabled;
|
||||
bool m_fHandleClosedDueToClient;
|
||||
bool m_fResponseHeadersReceivedAndSet;
|
||||
BOOL m_fDoReverseRewriteHeaders;
|
||||
BOOL m_fErrorHandled;
|
||||
BOOL m_fWebSocketUpgrade;
|
||||
BOOL m_fFinishRequest;
|
||||
BOOL m_fClientDisconnected;
|
||||
BOOL m_fHasError;
|
||||
DWORD m_msStartTime;
|
||||
DWORD m_BytesToReceive;
|
||||
DWORD m_BytesToSend;
|
||||
DWORD m_cchLastSend;
|
||||
DWORD m_cEntityBuffers;
|
||||
DWORD m_cBytesBuffered;
|
||||
DWORD m_cMinBufferLimit;
|
||||
|
||||
BYTE * m_pEntityBuffer;
|
||||
static const SIZE_T INLINE_ENTITY_BUFFERS = 8;
|
||||
BUFFER_T<BYTE*,INLINE_ENTITY_BUFFERS> m_buffEntityBuffers;
|
||||
|
||||
PCSTR m_pszOriginalHostHeader;
|
||||
|
||||
FORWARDING_REQUEST_STATUS m_RequestStatus;
|
||||
|
||||
ASYNC_DISCONNECT_CONTEXT * m_pDisconnect;
|
||||
|
||||
PCWSTR m_pszHeaders;
|
||||
DWORD m_cchHeaders;
|
||||
|
||||
STRU m_strFullUri;
|
||||
|
||||
ULONGLONG m_cContentLength;
|
||||
|
||||
WEBSOCKET_HANDLER * m_pWebSocket;
|
||||
|
||||
static PROTOCOL_CONFIG sm_ProtocolConfig;
|
||||
|
||||
static STRU sm_strErrorFormat;
|
||||
|
||||
static HANDLE sm_hEventLog;
|
||||
|
||||
static ALLOC_CACHE_HANDLER * sm_pAlloc;
|
||||
|
||||
//
|
||||
// Reference cout tracing for debugging purposes.
|
||||
//
|
||||
static TRACE_LOG * sm_pTraceLog;
|
||||
};
|
||||
|
||||
class ASYNC_DISCONNECT_CONTEXT : public IHttpConnectionStoredContext
|
||||
{
|
||||
public:
|
||||
ASYNC_DISCONNECT_CONTEXT()
|
||||
{
|
||||
m_pHandler = NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
CleanupStoredContext()
|
||||
{
|
||||
DBG_ASSERT(m_pHandler == NULL);
|
||||
delete this;
|
||||
}
|
||||
|
||||
VOID
|
||||
NotifyDisconnect()
|
||||
{
|
||||
FORWARDING_HANDLER *pInitialValue = (FORWARDING_HANDLER*)
|
||||
InterlockedExchangePointer((PVOID*) &m_pHandler, NULL);
|
||||
|
||||
if (pInitialValue != NULL)
|
||||
{
|
||||
pInitialValue->TerminateRequest(TRUE);
|
||||
pInitialValue->DereferenceForwardingHandler();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
SetHandler(
|
||||
FORWARDING_HANDLER *pHandler
|
||||
)
|
||||
{
|
||||
//
|
||||
// Take a reference on the forwarding handler.
|
||||
// This reference will be released on either of two conditions:
|
||||
//
|
||||
// 1. When the request processing ends, in which case a ResetHandler()
|
||||
// is called.
|
||||
//
|
||||
// 2. When a disconnect notification arrives.
|
||||
//
|
||||
// We need to make sure that only one of them ends up dereferencing
|
||||
// the object.
|
||||
//
|
||||
|
||||
DBG_ASSERT (pHandler != NULL);
|
||||
DBG_ASSERT (m_pHandler == NULL);
|
||||
|
||||
pHandler->ReferenceForwardingHandler();
|
||||
InterlockedExchangePointer((PVOID*)&m_pHandler, pHandler);
|
||||
}
|
||||
|
||||
VOID
|
||||
ResetHandler(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
FORWARDING_HANDLER *pInitialValue = (FORWARDING_HANDLER*)
|
||||
InterlockedExchangePointer( (PVOID*)&m_pHandler, NULL);
|
||||
|
||||
if (pInitialValue != NULL)
|
||||
{
|
||||
pInitialValue->DereferenceForwardingHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
~ASYNC_DISCONNECT_CONTEXT()
|
||||
{}
|
||||
|
||||
FORWARDING_HANDLER * m_pHandler;
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class ASPNET_CORE_GLOBAL_MODULE : public CGlobalModule
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
ASPNET_CORE_GLOBAL_MODULE(
|
||||
APPLICATION_MANAGER* pApplicationManager
|
||||
);
|
||||
|
||||
~ASPNET_CORE_GLOBAL_MODULE()
|
||||
{
|
||||
}
|
||||
|
||||
VOID Terminate()
|
||||
{
|
||||
// Remove the class from memory.
|
||||
delete this;
|
||||
}
|
||||
|
||||
GLOBAL_NOTIFICATION_STATUS
|
||||
OnGlobalStopListening(
|
||||
_In_ IGlobalStopListeningProvider * pProvider
|
||||
);
|
||||
|
||||
GLOBAL_NOTIFICATION_STATUS
|
||||
OnGlobalConfigurationChange(
|
||||
_In_ IGlobalConfigurationChangeProvider * pProvider
|
||||
);
|
||||
|
||||
private:
|
||||
APPLICATION_MANAGER * m_pApplicationManager;
|
||||
};
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
class IN_PROCESS_STORED_CONTEXT : public IHttpStoredContext
|
||||
{
|
||||
public:
|
||||
IN_PROCESS_STORED_CONTEXT(
|
||||
IHttpContext* pHttpContext,
|
||||
PVOID pvManagedContext
|
||||
);
|
||||
|
||||
~IN_PROCESS_STORED_CONTEXT();
|
||||
|
||||
virtual
|
||||
VOID
|
||||
CleanupStoredContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual
|
||||
VOID
|
||||
OnClientDisconnected(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
VOID
|
||||
OnListenerEvicted(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
PVOID
|
||||
QueryManagedHttpContext(
|
||||
VOID
|
||||
);
|
||||
|
||||
IHttpContext*
|
||||
QueryHttpContext(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOL
|
||||
QueryIsManagedRequestComplete(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
IndicateManagedRequestComplete(
|
||||
VOID
|
||||
);
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
QueryAsyncCompletionStatus(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
SetAsyncCompletionStatus(
|
||||
REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetInProcessStoredContext(
|
||||
IHttpContext* pHttpContext,
|
||||
IN_PROCESS_STORED_CONTEXT** ppInProcessStoredContext
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
SetInProcessStoredContext(
|
||||
IHttpContext* pHttpContext,
|
||||
IN_PROCESS_STORED_CONTEXT* pInProcessStoredContext
|
||||
);
|
||||
|
||||
private:
|
||||
PVOID m_pManagedHttpContext;
|
||||
IHttpContext* m_pHttpContext;
|
||||
BOOL m_fManagedRequestComplete;
|
||||
REQUEST_NOTIFICATION_STATUS m_requestNotificationStatus;
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "application.h"
|
||||
|
||||
class OUT_OF_PROCESS_APPLICATION : public APPLICATION
|
||||
{
|
||||
public:
|
||||
OUT_OF_PROCESS_APPLICATION();
|
||||
|
||||
~OUT_OF_PROCESS_APPLICATION();
|
||||
|
||||
__override
|
||||
HRESULT Initialize(_In_ APPLICATION_MANAGER* pApplicationManager,
|
||||
_In_ ASPNETCORE_CONFIG* pConfiguration);
|
||||
|
||||
__override
|
||||
VOID OnAppOfflineHandleChange();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
ExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
);
|
||||
|
||||
HRESULT
|
||||
GetProcess(
|
||||
_In_ IHttpContext *context,
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
)
|
||||
{
|
||||
return m_pProcessManager->GetProcess(context, m_pConfiguration, ppServerProcess);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PROCESS_MANAGER* m_pProcessManager;
|
||||
};
|
|
@ -1,18 +1,19 @@
|
|||
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "forwardinghandler.h"
|
||||
extern HTTP_MODULE_ID g_pModuleId;
|
||||
extern IHttpServer *g_pHttpServer;
|
||||
extern HMODULE g_hAspnetCoreRH;
|
||||
|
||||
class CProxyModule : public CHttpModule
|
||||
class ASPNET_CORE_PROXY_MODULE : public CHttpModule
|
||||
{
|
||||
public:
|
||||
|
||||
CProxyModule();
|
||||
ASPNET_CORE_PROXY_MODULE();
|
||||
|
||||
~CProxyModule();
|
||||
~ASPNET_CORE_PROXY_MODULE();
|
||||
|
||||
void * operator new(size_t size, IModuleAllocator * pPlacement)
|
||||
{
|
||||
|
@ -44,10 +45,12 @@ class CProxyModule : public CHttpModule
|
|||
|
||||
private:
|
||||
|
||||
FORWARDING_HANDLER * m_pHandler;
|
||||
APPLICATION_INFO *m_pApplicationInfo;
|
||||
APPLICATION *m_pApplication;
|
||||
REQUEST_HANDLER *m_pHandler;
|
||||
};
|
||||
|
||||
class CProxyModuleFactory : public IHttpModuleFactory
|
||||
class ASPNET_CORE_PROXY_MODULE_FACTORY : public IHttpModuleFactory
|
||||
{
|
||||
public:
|
||||
HRESULT
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define IDS_INVALID_PROPERTY 1000
|
||||
#define IDS_SERVER_ERROR 1001
|
||||
|
||||
// TODO remove this file?
|
||||
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and is listening on port '%d'."
|
||||
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
|
||||
APPLICATION::~APPLICATION()
|
||||
{
|
||||
if (m_pAppOfflineHtm != NULL)
|
||||
{
|
||||
m_pAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
m_pAppOfflineHtm = NULL;
|
||||
}
|
||||
|
||||
if (m_pFileWatcherEntry != NULL)
|
||||
{
|
||||
// Mark the entry as invalid,
|
||||
// StopMonitor will close the file handle and trigger a FCN
|
||||
// the entry will delete itself when processing this FCN
|
||||
m_pFileWatcherEntry->MarkEntryInValid();
|
||||
m_pFileWatcherEntry->StopMonitor();
|
||||
m_pFileWatcherEntry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION::StartMonitoringAppOffline()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (m_pFileWatcherEntry != NULL)
|
||||
{
|
||||
hr = m_pFileWatcherEntry->Create(m_pConfiguration->QueryApplicationFullPath()->QueryStr(), L"app_offline.htm", this, NULL);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
APPLICATION::UpdateAppOfflineFileHandle()
|
||||
{
|
||||
STRU strFilePath;
|
||||
PATH::ConvertPathToFullPath(L".\\app_offline.htm", m_pConfiguration->QueryApplicationFullPath()->QueryStr(), &strFilePath);
|
||||
APP_OFFLINE_HTM *pOldAppOfflineHtm = NULL;
|
||||
APP_OFFLINE_HTM *pNewAppOfflineHtm = NULL;
|
||||
|
||||
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFilePath.QueryStr()) && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
m_fAppOfflineFound = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fAppOfflineFound = TRUE;
|
||||
pNewAppOfflineHtm = new APP_OFFLINE_HTM(strFilePath.QueryStr());
|
||||
|
||||
if ( pNewAppOfflineHtm != NULL )
|
||||
{
|
||||
if (pNewAppOfflineHtm->Load())
|
||||
{
|
||||
//
|
||||
// loaded the new app_offline.htm
|
||||
//
|
||||
pOldAppOfflineHtm = (APP_OFFLINE_HTM *)InterlockedExchangePointer((VOID**)&m_pAppOfflineHtm, pNewAppOfflineHtm);
|
||||
|
||||
if (pOldAppOfflineHtm != NULL)
|
||||
{
|
||||
pOldAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
pOldAppOfflineHtm = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignored the new app_offline file because the file does not exist.
|
||||
pNewAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
pNewAppOfflineHtm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
OnAppOfflineHandleChange();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
|
||||
APPLICATION_INFO::~APPLICATION_INFO()
|
||||
{
|
||||
if (m_pAppOfflineHtm != NULL)
|
||||
{
|
||||
m_pAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
m_pAppOfflineHtm = NULL;
|
||||
}
|
||||
|
||||
if (m_pFileWatcherEntry != NULL)
|
||||
{
|
||||
// Mark the entry as invalid,
|
||||
// StopMonitor will close the file handle and trigger a FCN
|
||||
// the entry will delete itself when processing this FCN
|
||||
m_pFileWatcherEntry->MarkEntryInValid();
|
||||
m_pFileWatcherEntry->StopMonitor();
|
||||
m_pFileWatcherEntry = NULL;
|
||||
}
|
||||
|
||||
if (m_pApplication != NULL)
|
||||
{
|
||||
// shutdown the application
|
||||
m_pApplication->ShutDown();
|
||||
m_pApplication->DereferenceApplication();
|
||||
m_pApplication = NULL;
|
||||
}
|
||||
|
||||
// configuration should be dereferenced after application shutdown
|
||||
// since the former will use it during shutdown
|
||||
if (m_pConfiguration != NULL)
|
||||
{
|
||||
// Need to dereference the configuration instance
|
||||
m_pConfiguration->DereferenceConfiguration();
|
||||
m_pConfiguration = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::Initialize(
|
||||
_In_ ASPNETCORE_CONFIG *pConfiguration,
|
||||
_In_ FILE_WATCHER *pFileWatcher
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DBG_ASSERT(pConfiguration);
|
||||
DBG_ASSERT(pFileWatcher);
|
||||
|
||||
m_pConfiguration = pConfiguration;
|
||||
|
||||
// reference the configuration instance to prevent it will be not release
|
||||
// earlier in case of configuration change and shutdown
|
||||
m_pConfiguration->ReferenceConfiguration();
|
||||
|
||||
hr = m_applicationInfoKey.Initialize(pConfiguration->QueryConfigPath()->QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
m_pFileWatcherEntry = new FILE_WATCHER_ENTRY(pFileWatcher);
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAppOfflineFileHandle();
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::StartMonitoringAppOffline()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (m_pFileWatcherEntry != NULL)
|
||||
{
|
||||
hr = m_pFileWatcherEntry->Create(m_pConfiguration->QueryApplicationPhysicalPath()->QueryStr(), L"app_offline.htm", this, NULL);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
APPLICATION_INFO::UpdateAppOfflineFileHandle()
|
||||
{
|
||||
STRU strFilePath;
|
||||
UTILITY::ConvertPathToFullPath(L".\\app_offline.htm",
|
||||
m_pConfiguration->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
&strFilePath);
|
||||
APP_OFFLINE_HTM *pOldAppOfflineHtm = NULL;
|
||||
APP_OFFLINE_HTM *pNewAppOfflineHtm = NULL;
|
||||
|
||||
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFilePath.QueryStr()) &&
|
||||
GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
m_fAppOfflineFound = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fAppOfflineFound = TRUE;
|
||||
pNewAppOfflineHtm = new APP_OFFLINE_HTM(strFilePath.QueryStr());
|
||||
|
||||
if (pNewAppOfflineHtm != NULL)
|
||||
{
|
||||
if (pNewAppOfflineHtm->Load())
|
||||
{
|
||||
//
|
||||
// loaded the new app_offline.htm
|
||||
//
|
||||
pOldAppOfflineHtm = (APP_OFFLINE_HTM *)InterlockedExchangePointer((VOID**)&m_pAppOfflineHtm, pNewAppOfflineHtm);
|
||||
|
||||
if (pOldAppOfflineHtm != NULL)
|
||||
{
|
||||
pOldAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
pOldAppOfflineHtm = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignored the new app_offline file because the file does not exist.
|
||||
pNewAppOfflineHtm->DereferenceAppOfflineHtm();
|
||||
pNewAppOfflineHtm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// recycle the application
|
||||
if (m_pApplication != NULL)
|
||||
{
|
||||
m_pApplication->ShutDown();
|
||||
m_pApplication->DereferenceApplication();
|
||||
m_pApplication = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::EnsureApplicationCreated()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
APPLICATION* pApplication = NULL;
|
||||
STACK_STRU(struFileName, 300); // >MAX_PATH
|
||||
STRU hostFxrDllLocation;
|
||||
|
||||
if (m_pApplication != NULL)
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = FindRequestHandlerAssembly();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (m_pApplication == NULL)
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fLocked = TRUE;
|
||||
if (m_pApplication != NULL)
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (m_pfnAspNetCoreCreateApplication == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_pfnAspNetCoreCreateApplication(m_pServer, m_pConfiguration, &pApplication);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
m_pApplication = pApplication;
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::FindRequestHandlerAssembly()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
STACK_STRU(struFileName, 256);
|
||||
|
||||
if (g_fAspnetcoreRHLoadedError)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
goto Finished;
|
||||
}
|
||||
else if (!g_fAspnetcoreRHAssemblyLoaded)
|
||||
{
|
||||
AcquireSRWLockExclusive(&g_srwLock);
|
||||
fLocked = TRUE;
|
||||
if (g_fAspnetcoreRHLoadedError)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
goto Finished;
|
||||
}
|
||||
if (g_fAspnetcoreRHAssemblyLoaded)
|
||||
{
|
||||
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
|
||||
{
|
||||
hr = FindNativeAssemblyFromGlobalLocation(&struFileName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
g_hAspnetCoreRH = LoadLibraryW(struFileName.QueryStr());
|
||||
if (g_hAspnetCoreRH == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
g_pfnAspNetCoreCreateApplication = (PFN_ASPNETCORE_CREATE_APPLICATION)
|
||||
GetProcAddress(g_hAspnetCoreRH, "CreateApplication");
|
||||
if (g_pfnAspNetCoreCreateApplication == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
g_pfnAspNetCoreCreateRequestHandler = (PFN_ASPNETCORE_CREATE_REQUEST_HANDLER)
|
||||
GetProcAddress(g_hAspnetCoreRH, "CreateRequestHandler");
|
||||
if (g_pfnAspNetCoreCreateRequestHandler == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
g_fAspnetcoreRHAssemblyLoaded = TRUE;
|
||||
}
|
||||
|
||||
Finished:
|
||||
//
|
||||
// Question: we remember the load failure so that we will not try again.
|
||||
// User needs to check whether the fuction pointer is NULL
|
||||
//
|
||||
m_pfnAspNetCoreCreateApplication = g_pfnAspNetCoreCreateApplication;
|
||||
m_pfnAspNetCoreCreateRequestHandler = g_pfnAspNetCoreCreateRequestHandler;
|
||||
if (!g_fAspnetcoreRHLoadedError && FAILED(hr))
|
||||
{
|
||||
g_fAspnetcoreRHLoadedError = TRUE;
|
||||
}
|
||||
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&g_srwLock);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_INFO::FindNativeAssemblyFromGlobalLocation(STRU* struFilename)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD dwSize = MAX_PATH;
|
||||
BOOL fDone = FALSE;
|
||||
DWORD dwPosition = 0;
|
||||
|
||||
// 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
|
||||
while (!fDone)
|
||||
{
|
||||
DWORD dwReturnedSize = GetModuleFileName(NULL, struFilename->QueryStr(), dwSize);
|
||||
if (dwReturnedSize == 0)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
fDone = TRUE;
|
||||
goto Finished;
|
||||
}
|
||||
else if ((dwReturnedSize == dwSize) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
dwSize *= 2; // smaller buffer. increase the buffer and retry
|
||||
struFilename->Resize(dwSize + 20); // aspnetcorerh.dll
|
||||
}
|
||||
else
|
||||
{
|
||||
fDone = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = struFilename->SyncWithBuffer()))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
dwPosition = struFilename->LastIndexOf(L'\\', 0);
|
||||
struFilename->QueryStr()[dwPosition] = L'\0';
|
||||
|
||||
if (FAILED(hr = struFilename->SyncWithBuffer()) ||
|
||||
FAILED(hr = struFilename->Append(g_pwzAspnetcoreRequestHandlerName)))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
|
@ -6,28 +6,28 @@
|
|||
APPLICATION_MANAGER* APPLICATION_MANAGER::sm_pApplicationManager = NULL;
|
||||
|
||||
HRESULT
|
||||
APPLICATION_MANAGER::GetApplication(
|
||||
_In_ IHttpContext* pContext,
|
||||
APPLICATION_MANAGER::GetApplicationInfo(
|
||||
_In_ IHttpServer* pServer,
|
||||
_In_ ASPNETCORE_CONFIG* pConfig,
|
||||
_Out_ APPLICATION ** ppApplication
|
||||
_Out_ APPLICATION_INFO ** ppApplicationInfo
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
APPLICATION *pApplication = NULL;
|
||||
APPLICATION_KEY key;
|
||||
BOOL fExclusiveLock = FALSE;
|
||||
BOOL fMixedHostingModelError = FALSE;
|
||||
BOOL fDuplicatedInProcessApp = FALSE;
|
||||
PCWSTR pszApplicationId = NULL;
|
||||
LPCWSTR apsz[1];
|
||||
HRESULT hr = S_OK;
|
||||
APPLICATION_INFO *pApplicationInfo = NULL;
|
||||
APPLICATION_INFO_KEY key;
|
||||
BOOL fExclusiveLock = FALSE;
|
||||
BOOL fMixedHostingModelError = FALSE;
|
||||
BOOL fDuplicatedInProcessApp = FALSE;
|
||||
PCWSTR pszApplicationId = NULL;
|
||||
LPCWSTR apsz[1];
|
||||
STACK_STRU ( strEventMsg, 256 );
|
||||
|
||||
*ppApplication = NULL;
|
||||
|
||||
DBG_ASSERT(pContext != NULL);
|
||||
DBG_ASSERT(pContext->GetApplication() != NULL);
|
||||
*ppApplicationInfo = NULL;
|
||||
|
||||
pszApplicationId = pContext->GetApplication()->GetApplicationId();
|
||||
DBG_ASSERT(pServer != NULL);
|
||||
DBG_ASSERT(pConfig != NULL);
|
||||
|
||||
pszApplicationId = pConfig->QueryConfigPath()->QueryStr();
|
||||
|
||||
hr = key.Initialize(pszApplicationId);
|
||||
if (FAILED(hr))
|
||||
|
@ -35,33 +35,39 @@ APPLICATION_MANAGER::GetApplication(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
m_pApplicationHash->FindKey(&key, ppApplication);
|
||||
AcquireSRWLockShared(&m_srwLock);
|
||||
if (m_fInShutdown)
|
||||
{
|
||||
ReleaseSRWLockShared(&m_srwLock);
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
||||
goto Finished;
|
||||
}
|
||||
m_pApplicationInfoHash->FindKey(&key, ppApplicationInfo);
|
||||
ReleaseSRWLockShared(&m_srwLock);
|
||||
|
||||
if (*ppApplication == NULL)
|
||||
if (*ppApplicationInfo == NULL)
|
||||
{
|
||||
switch (pConfig->QueryHostingModel())
|
||||
{
|
||||
case HOSTING_IN_PROCESS:
|
||||
if (m_pApplicationHash->Count() > 0)
|
||||
if (m_pApplicationInfoHash->Count() > 0)
|
||||
{
|
||||
// Only one inprocess app is allowed per IIS worker process
|
||||
fDuplicatedInProcessApp = TRUE;
|
||||
hr = HRESULT_FROM_WIN32(ERROR_APP_INIT_FAILURE);
|
||||
goto Finished;
|
||||
}
|
||||
pApplication = new IN_PROCESS_APPLICATION();
|
||||
break;
|
||||
|
||||
case HOSTING_OUT_PROCESS:
|
||||
pApplication = new OUT_OF_PROCESS_APPLICATION();
|
||||
break;
|
||||
|
||||
default:
|
||||
hr = E_UNEXPECTED;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (pApplication == NULL)
|
||||
pApplicationInfo = new APPLICATION_INFO(pServer);
|
||||
if (pApplicationInfo == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
|
@ -69,13 +75,19 @@ APPLICATION_MANAGER::GetApplication(
|
|||
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = TRUE;
|
||||
m_pApplicationHash->FindKey(&key, ppApplication);
|
||||
if (m_fInShutdown)
|
||||
{
|
||||
// Already in shuting down. No need to create the application
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
||||
goto Finished;
|
||||
}
|
||||
m_pApplicationInfoHash->FindKey(&key, ppApplicationInfo);
|
||||
|
||||
if (*ppApplication != NULL)
|
||||
if (*ppApplicationInfo != NULL)
|
||||
{
|
||||
// someone else created the application
|
||||
delete pApplication;
|
||||
pApplication = NULL;
|
||||
delete pApplicationInfo;
|
||||
pApplicationInfo = NULL;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
@ -92,13 +104,13 @@ APPLICATION_MANAGER::GetApplication(
|
|||
}
|
||||
}
|
||||
|
||||
hr = pApplication->Initialize(this, pConfig);
|
||||
hr = pApplicationInfo->Initialize(pConfig, m_pFileWatcher);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_pApplicationHash->InsertRecord( pApplication );
|
||||
hr = m_pApplicationInfoHash->InsertRecord( pApplicationInfo );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
|
@ -112,13 +124,12 @@ APPLICATION_MANAGER::GetApplication(
|
|||
m_hostingModel = pConfig->QueryHostingModel();
|
||||
}
|
||||
|
||||
*ppApplicationInfo = pApplicationInfo;
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = FALSE;
|
||||
|
||||
pApplication->StartMonitoringAppOffline();
|
||||
|
||||
*ppApplication = pApplication;
|
||||
pApplication = NULL;
|
||||
pApplicationInfo->StartMonitoringAppOffline();
|
||||
pApplicationInfo = NULL;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
@ -128,21 +139,21 @@ Finished:
|
|||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
if (pApplicationInfo != NULL)
|
||||
{
|
||||
pApplicationInfo->DereferenceApplicationInfo();
|
||||
pApplicationInfo = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (pApplication != NULL)
|
||||
{
|
||||
pApplication->DereferenceApplication();
|
||||
pApplication = NULL;
|
||||
}
|
||||
|
||||
if (fDuplicatedInProcessApp)
|
||||
{
|
||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG,
|
||||
pszApplicationId)))
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
/*apsz[0] = strEventMsg.QueryStr();
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
|
@ -154,30 +165,30 @@ Finished:
|
|||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else if (fMixedHostingModelError)
|
||||
{
|
||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG,
|
||||
pszApplicationId,
|
||||
pConfig->QueryHostingModelStr())))
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
0,
|
||||
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
//if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
// ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG,
|
||||
// pszApplicationId,
|
||||
// pConfig->QueryHostingModelStr())))
|
||||
//{
|
||||
// apsz[0] = strEventMsg.QueryStr();
|
||||
// /*if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
// {
|
||||
// ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
// EVENTLOG_ERROR_TYPE,
|
||||
// 0,
|
||||
// ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR,
|
||||
// NULL,
|
||||
// 1,
|
||||
// 0,
|
||||
// apsz,
|
||||
// NULL);
|
||||
// }*/
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -187,7 +198,7 @@ Finished:
|
|||
hr)))
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
/*if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
|
@ -198,7 +209,7 @@ Finished:
|
|||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,23 +219,33 @@ Finished:
|
|||
|
||||
HRESULT
|
||||
APPLICATION_MANAGER::RecycleApplication(
|
||||
_In_ LPCWSTR pszApplication
|
||||
_In_ LPCWSTR pszApplicationId
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
APPLICATION_KEY key;
|
||||
APPLICATION_INFO_KEY key;
|
||||
|
||||
hr = key.Initialize(pszApplication);
|
||||
hr = key.Initialize(pszApplicationId);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
m_pApplicationHash->DeleteKey(&key);
|
||||
if (m_pApplicationHash->Count() == 0)
|
||||
m_pApplicationInfoHash->DeleteKey(&key);
|
||||
|
||||
if (m_pApplicationInfoHash->Count() == 0)
|
||||
{
|
||||
m_hostingModel = HOSTING_UNKNOWN;
|
||||
}
|
||||
|
||||
if (g_fAspnetcoreRHLoadedError)
|
||||
{
|
||||
// We had assembly loading failure
|
||||
// this error blocked the start of all applications
|
||||
// Let's recycle the worker process if user redeployed any application
|
||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand due to assembly loading failure");
|
||||
}
|
||||
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
|
||||
Finished:
|
||||
|
@ -232,65 +253,17 @@ Finished:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
APPLICATION_MANAGER::Get502ErrorPage(
|
||||
_Out_ HTTP_DATA_CHUNK** ppErrorPage
|
||||
)
|
||||
VOID
|
||||
APPLICATION_MANAGER::ShutDown()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fExclusiveLock = FALSE;
|
||||
HTTP_DATA_CHUNK *pHttp502ErrorPage = NULL;
|
||||
|
||||
DBG_ASSERT(ppErrorPage != NULL);
|
||||
|
||||
//on-demand create the error page
|
||||
if (m_pHttp502ErrorPage != NULL)
|
||||
{
|
||||
*ppErrorPage = m_pHttp502ErrorPage;
|
||||
}
|
||||
else
|
||||
m_fInShutdown = TRUE;
|
||||
if (m_pApplicationInfoHash != NULL)
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = TRUE;
|
||||
if (m_pHttp502ErrorPage != NULL)
|
||||
{
|
||||
*ppErrorPage = m_pHttp502ErrorPage;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t maxsize = 5000;
|
||||
pHttp502ErrorPage = new HTTP_DATA_CHUNK();
|
||||
if (pHttp502ErrorPage == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto Finished;
|
||||
}
|
||||
pHttp502ErrorPage->DataChunkType = HttpDataChunkFromMemory;
|
||||
pHttp502ErrorPage->FromMemory.pBuffer = (PVOID)m_pstrErrorInfo;
|
||||
|
||||
pHttp502ErrorPage->FromMemory.BufferLength = (ULONG)strnlen(m_pstrErrorInfo, maxsize); //(ULONG)(wcslen(m_pstrErrorInfo)); // *sizeof(WCHAR);
|
||||
if(m_pHttp502ErrorPage != NULL)
|
||||
{
|
||||
delete m_pHttp502ErrorPage;
|
||||
}
|
||||
m_pHttp502ErrorPage = pHttp502ErrorPage;
|
||||
*ppErrorPage = m_pHttp502ErrorPage;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (fExclusiveLock)
|
||||
{
|
||||
// clean up the hash table so that the application will be informed on shutdown
|
||||
m_pApplicationInfoHash->Clear();
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (pHttp502ErrorPage != NULL)
|
||||
{
|
||||
delete pHttp502ErrorPage;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,35 +6,42 @@
|
|||
|
||||
HTTP_MODULE_ID g_pModuleId = NULL;
|
||||
IHttpServer * g_pHttpServer = NULL;
|
||||
BOOL g_fAsyncDisconnectAvailable = FALSE;
|
||||
BOOL g_fWinHttpNonBlockingCallbackAvailable = FALSE;
|
||||
BOOL g_fRecycleProcessCalled = FALSE;
|
||||
PCWSTR g_pszModuleName = NULL;
|
||||
HINSTANCE g_hModule;
|
||||
HINSTANCE g_hWinHttpModule;
|
||||
BOOL g_fWebSocketSupported = FALSE;
|
||||
|
||||
DWORD g_dwTlsIndex = TLS_OUT_OF_INDEXES;
|
||||
BOOL g_fEnableReferenceCountTracing = FALSE;
|
||||
HMODULE g_hAspnetCoreRH = NULL;
|
||||
BOOL g_fAspnetcoreRHAssemblyLoaded = FALSE;
|
||||
BOOL g_fAspnetcoreRHLoadedError = FALSE;
|
||||
DWORD g_dwAspNetCoreDebugFlags = 0;
|
||||
BOOL g_fNsiApiNotSupported = FALSE;
|
||||
DWORD g_dwActiveServerProcesses = 0;
|
||||
DWORD g_OptionalWinHttpFlags = 0; //specify additional WinHTTP options when using WinHttpOpenRequest API.
|
||||
|
||||
SRWLOCK g_srwLock;
|
||||
DWORD g_dwDebugFlags = 0;
|
||||
PCSTR g_szDebugLabel = "ASPNET_CORE_MODULE";
|
||||
PCWSTR g_pwzAspnetcoreRequestHandlerName = L"\\aspnetcorerh.dll";
|
||||
PFN_ASPNETCORE_CREATE_APPLICATION g_pfnAspNetCoreCreateApplication;
|
||||
PFN_ASPNETCORE_CREATE_REQUEST_HANDLER g_pfnAspNetCoreCreateRequestHandler;
|
||||
|
||||
VOID
|
||||
StaticCleanup()
|
||||
{
|
||||
APPLICATION_MANAGER::Cleanup();
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
g_hModule = hModule;
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
StaticCleanup();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -42,75 +49,6 @@ BOOL WINAPI DllMain(HMODULE hModule,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
LoadGlobalConfiguration(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HKEY hKey;
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\Microsoft\\IIS Extensions\\IIS AspNetCore Module\\Parameters",
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == NO_ERROR)
|
||||
{
|
||||
DWORD dwType;
|
||||
DWORD dwData;
|
||||
DWORD cbData;
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"OptionalWinHttpFlags",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD))
|
||||
{
|
||||
g_OptionalWinHttpFlags = dwData;
|
||||
}
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"EnableReferenceCountTracing",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD) && (dwData == 1 || dwData == 0))
|
||||
{
|
||||
g_fEnableReferenceCountTracing = !!dwData;
|
||||
}
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"DebugFlags",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD))
|
||||
{
|
||||
g_dwAspNetCoreDebugFlags = dwData;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
DWORD dwResult = GetExtendedTcpTable(NULL,
|
||||
&dwSize,
|
||||
FALSE,
|
||||
AF_INET,
|
||||
TCP_TABLE_OWNER_PID_LISTENER,
|
||||
0);
|
||||
if (dwResult != NO_ERROR && dwResult != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
g_fNsiApiNotSupported = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
__stdcall
|
||||
RegisterModule(
|
||||
|
@ -138,8 +76,14 @@ HRESULT
|
|||
|
||||
--*/
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
CProxyModuleFactory * pFactory = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
HKEY hKey;
|
||||
BOOL fDisableANCM = FALSE;
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY * pFactory = NULL;
|
||||
ASPNET_CORE_GLOBAL_MODULE * pGlobalModule = NULL;
|
||||
APPLICATION_MANAGER * pApplicationManager = NULL;
|
||||
|
||||
UNREFERENCED_PARAMETER(dwServerVersion);
|
||||
|
||||
#ifdef DEBUG
|
||||
CREATE_DEBUG_PRINT_OBJECT("Asp.Net Core Module");
|
||||
|
@ -148,63 +92,50 @@ HRESULT
|
|||
|
||||
CREATE_DEBUG_PRINT_OBJECT;
|
||||
|
||||
LoadGlobalConfiguration();
|
||||
//LoadGlobalConfiguration();
|
||||
|
||||
//
|
||||
// 7.0 is 0,7
|
||||
//
|
||||
if (dwServerVersion > MAKELONG(0, 7))
|
||||
{
|
||||
g_fAsyncDisconnectAvailable = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// 8.0 is 0,8
|
||||
//
|
||||
if (dwServerVersion >= MAKELONG(0, 8))
|
||||
{
|
||||
// IISOOB:36641 Enable back WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS for Win8.
|
||||
// g_fWinHttpNonBlockingCallbackAvailable = TRUE;
|
||||
g_fWebSocketSupported = TRUE;
|
||||
}
|
||||
|
||||
hr = WINHTTP_HELPER::StaticInitialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND))
|
||||
{
|
||||
g_fWebSocketSupported = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
InitializeSRWLock(&g_srwLock);
|
||||
|
||||
g_pModuleId = pModuleInfo->GetId();
|
||||
g_pszModuleName = pModuleInfo->GetName();
|
||||
g_pHttpServer = pHttpServer;
|
||||
g_hWinHttpModule = GetModuleHandle(TEXT("winhttp.dll"));
|
||||
|
||||
//
|
||||
// WinHTTP does not create enough threads, ask it to create more.
|
||||
// Starting in Windows 7, this setting is ignored because WinHTTP
|
||||
// uses a thread pool.
|
||||
//
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
DWORD dwThreadCount = (si.dwNumberOfProcessors * 3 + 1) / 2;
|
||||
WinHttpSetOption(NULL,
|
||||
WINHTTP_OPTION_WORKER_THREAD_COUNT,
|
||||
&dwThreadCount,
|
||||
sizeof(dwThreadCount));
|
||||
// check whether the feature is disabled due to security reason
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\Microsoft\\IIS Extensions\\IIS AspNetCore Module\\Parameters",
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == NO_ERROR)
|
||||
{
|
||||
DWORD dwType;
|
||||
DWORD dwData;
|
||||
DWORD cbData;
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"DisableANCM",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD))
|
||||
{
|
||||
fDisableANCM = (dwData != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fDisableANCM)
|
||||
{
|
||||
// Logging
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the factory before any static initialization.
|
||||
// The CProxyModuleFactory::Terminate method will clean any
|
||||
// The ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate method will clean any
|
||||
// static object initialized.
|
||||
//
|
||||
pFactory = new CProxyModuleFactory;
|
||||
pFactory = new ASPNET_CORE_PROXY_MODULE_FACTORY;
|
||||
|
||||
if (pFactory == NULL)
|
||||
{
|
||||
|
@ -213,28 +144,45 @@ HRESULT
|
|||
}
|
||||
|
||||
hr = pModuleInfo->SetRequestNotifications(
|
||||
pFactory,
|
||||
RQ_EXECUTE_REQUEST_HANDLER,
|
||||
0);
|
||||
pFactory,
|
||||
RQ_EXECUTE_REQUEST_HANDLER,
|
||||
0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
pFactory = NULL;
|
||||
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
||||
if(pApplicationManager == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pApplicationManager->Initialize();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
pGlobalModule = NULL;
|
||||
|
||||
g_pResponseHeaderHash = new RESPONSE_HEADER_HASH;
|
||||
if (g_pResponseHeaderHash == NULL)
|
||||
pGlobalModule = new ASPNET_CORE_GLOBAL_MODULE(pApplicationManager);
|
||||
if (pGlobalModule == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = g_pResponseHeaderHash->Initialize();
|
||||
hr = pModuleInfo->SetGlobalNotifications(
|
||||
pGlobalModule,
|
||||
GL_CONFIGURATION_CHANGE | GL_STOP_LISTENING);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
pGlobalModule = NULL;
|
||||
|
||||
hr = ALLOC_CACHE_HANDLER::StaticInitialize();
|
||||
if (FAILED(hr))
|
||||
|
@ -242,19 +190,12 @@ HRESULT
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
hr = FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (pGlobalModule != NULL)
|
||||
{
|
||||
delete pGlobalModule;
|
||||
pGlobalModule = NULL;
|
||||
}
|
||||
|
||||
if (pFactory != NULL)
|
||||
{
|
||||
|
|
|
@ -13,9 +13,17 @@ FILE_WATCHER::~FILE_WATCHER()
|
|||
{
|
||||
if (m_hChangeNotificationThread != NULL)
|
||||
{
|
||||
PostQueuedCompletionStatus(m_hCompletionPort, 0, FILE_WATCHER_SHUTDOWN_KEY, NULL);
|
||||
WaitForSingleObject(m_hChangeNotificationThread, INFINITE);
|
||||
CloseHandle(m_hChangeNotificationThread);
|
||||
m_hChangeNotificationThread = NULL;
|
||||
}
|
||||
|
||||
if (NULL != m_hCompletionPort)
|
||||
{
|
||||
CloseHandle(m_hCompletionPort);
|
||||
m_hCompletionPort = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -97,13 +105,13 @@ Win32 error
|
|||
&pOverlapped,
|
||||
INFINITE);
|
||||
|
||||
DBG_ASSERT(fSuccess);
|
||||
DBG_ASSERT(fSuccess);
|
||||
DebugPrint(1, "FILE_WATCHER::ChangeNotificationThread");
|
||||
dwErrorStatus = fSuccess ? ERROR_SUCCESS : GetLastError();
|
||||
|
||||
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
|
||||
{
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_ASSERT(pOverlapped != NULL);
|
||||
|
@ -117,6 +125,8 @@ Win32 error
|
|||
pOverlapped = NULL;
|
||||
cbCompletion = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -173,7 +183,7 @@ FILE_WATCHER_ENTRY::FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor) :
|
|||
_pFileMonitor(pFileMonitor),
|
||||
_hDirectory(INVALID_HANDLE_VALUE),
|
||||
_hImpersonationToken(NULL),
|
||||
_pApplication(NULL),
|
||||
_pApplicationInfo(NULL),
|
||||
_lStopMonitorCalled(0),
|
||||
_cRefs(1),
|
||||
_fIsValid(TRUE)
|
||||
|
@ -253,7 +263,7 @@ HRESULT
|
|||
// Othersie we have to cache the file info
|
||||
//
|
||||
if (cbCompletion == 0)
|
||||
{
|
||||
{
|
||||
fFileChanged = TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -266,9 +276,9 @@ HRESULT
|
|||
//
|
||||
// check whether the monitored file got changed
|
||||
//
|
||||
if (_wcsnicmp(pNotificationInfo->FileName,
|
||||
_strFileName.QueryStr(),
|
||||
pNotificationInfo->FileNameLength/sizeof(WCHAR)) == 0)
|
||||
if (_wcsnicmp(pNotificationInfo->FileName,
|
||||
_strFileName.QueryStr(),
|
||||
pNotificationInfo->FileNameLength / sizeof(WCHAR)) == 0)
|
||||
{
|
||||
fFileChanged = TRUE;
|
||||
break;
|
||||
|
@ -284,7 +294,7 @@ HRESULT
|
|||
{
|
||||
pNotificationInfo = (FILE_NOTIFY_INFORMATION*)
|
||||
((PBYTE)pNotificationInfo +
|
||||
pNotificationInfo->NextEntryOffset);
|
||||
pNotificationInfo->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +304,7 @@ HRESULT
|
|||
//
|
||||
// so far we only monitoring app_offline
|
||||
//
|
||||
_pApplication->UpdateAppOfflineFileHandle();
|
||||
_pApplicationInfo->UpdateAppOfflineFileHandle();
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
@ -314,7 +324,7 @@ FILE_WATCHER_ENTRY::Monitor(VOID)
|
|||
ReferenceFileWatcherEntry();
|
||||
ZeroMemory(&_overlapped, sizeof(_overlapped));
|
||||
|
||||
if(!ReadDirectoryChangesW(_hDirectory,
|
||||
if (!ReadDirectoryChangesW(_hDirectory,
|
||||
_buffDirectoryChanges.QueryPtr(),
|
||||
_buffDirectoryChanges.QuerySize(),
|
||||
FALSE, // Watching sub dirs. Set to False now as only monitoring app_offline
|
||||
|
@ -355,7 +365,7 @@ HRESULT
|
|||
FILE_WATCHER_ENTRY::Create(
|
||||
_In_ PCWSTR pszDirectoryToMonitor,
|
||||
_In_ PCWSTR pszFileNameToMonitor,
|
||||
_In_ APPLICATION* pApplication,
|
||||
_In_ APPLICATION_INFO* pApplicationInfo,
|
||||
_In_ HANDLE hImpersonationToken
|
||||
)
|
||||
{
|
||||
|
@ -364,7 +374,7 @@ FILE_WATCHER_ENTRY::Create(
|
|||
|
||||
if (pszDirectoryToMonitor == NULL ||
|
||||
pszFileNameToMonitor == NULL ||
|
||||
pApplication == NULL)
|
||||
pApplicationInfo == NULL)
|
||||
{
|
||||
DBG_ASSERT(FALSE);
|
||||
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
||||
|
@ -374,7 +384,7 @@ FILE_WATCHER_ENTRY::Create(
|
|||
//
|
||||
//remember the application
|
||||
//
|
||||
_pApplication = pApplication;
|
||||
_pApplicationInfo = pApplicationInfo;
|
||||
|
||||
if (FAILED(hr = _strFileName.Copy(pszFileNameToMonitor)))
|
||||
{
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#include "precomp.hxx"
|
||||
|
||||
ASPNET_CORE_GLOBAL_MODULE::ASPNET_CORE_GLOBAL_MODULE(
|
||||
APPLICATION_MANAGER* pApplicationManager)
|
||||
{
|
||||
m_pApplicationManager = pApplicationManager;
|
||||
}
|
||||
|
||||
//
|
||||
// Is called when IIS decided to terminate worker process
|
||||
// Shut down all core apps
|
||||
//
|
||||
GLOBAL_NOTIFICATION_STATUS
|
||||
ASPNET_CORE_GLOBAL_MODULE::OnGlobalStopListening(
|
||||
_In_ IGlobalStopListeningProvider * pProvider
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pProvider);
|
||||
|
||||
if (m_pApplicationManager != NULL)
|
||||
{
|
||||
// we should let application manager to shudown all allication
|
||||
// and dereference it as some requests may still reference to application manager
|
||||
m_pApplicationManager->ShutDown();
|
||||
m_pApplicationManager = NULL;
|
||||
}
|
||||
|
||||
// Return processing to the pipeline.
|
||||
return GL_NOTIFICATION_CONTINUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Is called when configuration changed
|
||||
// Recycled the corresponding core app if its configuration changed
|
||||
//
|
||||
GLOBAL_NOTIFICATION_STATUS
|
||||
ASPNET_CORE_GLOBAL_MODULE::OnGlobalConfigurationChange(
|
||||
_In_ IGlobalConfigurationChangeProvider * pProvider
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pProvider);
|
||||
|
||||
// Retrieve the path that has changed.
|
||||
PCWSTR pwszChangePath = pProvider->GetChangePath();
|
||||
|
||||
// Test for an error.
|
||||
if (NULL != pwszChangePath &&
|
||||
_wcsicmp(pwszChangePath, L"MACHINE") != 0 &&
|
||||
_wcsicmp(pwszChangePath, L"MACHINE/WEBROOT") != 0)
|
||||
{
|
||||
if (m_pApplicationManager != NULL)
|
||||
{
|
||||
m_pApplicationManager->RecycleApplication(pwszChangePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Return processing to the pipeline.
|
||||
return GL_NOTIFICATION_CONTINUE;
|
||||
}
|
|
@ -1,686 +0,0 @@
|
|||
// 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 "precomp.hxx"
|
||||
#include <algorithm>
|
||||
|
||||
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() :
|
||||
m_ProcessExitCode ( 0 ),
|
||||
m_fManagedAppLoaded ( FALSE ),
|
||||
m_fLoadManagedAppError ( FALSE ),
|
||||
m_fInitialized ( FALSE )
|
||||
{
|
||||
}
|
||||
|
||||
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||
{
|
||||
Recycle();
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_APPLICATION::OnAsyncCompletion(
|
||||
IHttpContext* pHttpContext,
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
IN_PROCESS_STORED_CONTEXT* pInProcessStoredContext = NULL;
|
||||
REQUEST_NOTIFICATION_STATUS dwRequestNotificationStatus = RQ_NOTIFICATION_CONTINUE;
|
||||
|
||||
hr = IN_PROCESS_STORED_CONTEXT::GetInProcessStoredContext(pHttpContext, &pInProcessStoredContext);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Finish the request as we couldn't get the callback
|
||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 19, hr);
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
else if (pInProcessStoredContext->QueryIsManagedRequestComplete())
|
||||
{
|
||||
// means PostCompletion has been called and this is the associated callback.
|
||||
dwRequestNotificationStatus = pInProcessStoredContext->QueryAsyncCompletionStatus();
|
||||
// TODO cleanup whatever disconnect listener there is
|
||||
return dwRequestNotificationStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Call the managed handler for async completion.
|
||||
return m_AsyncCompletionHandler(pInProcessStoredContext->QueryManagedHttpContext(), hrCompletionStatus, cbCompletion);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
|
||||
_In_ PFN_MANAGED_CONTEXT_HANDLER async_completion_handler,
|
||||
_In_ VOID* pvRequstHandlerContext,
|
||||
_In_ VOID* pvShutdownHandlerContext
|
||||
)
|
||||
{
|
||||
m_RequestHandler = request_handler;
|
||||
m_RequstHandlerContext = pvRequstHandlerContext;
|
||||
m_ShutdownHandler = shutdown_handler;
|
||||
m_ShutdownHandlerContext = pvShutdownHandlerContext;
|
||||
m_AsyncCompletionHandler = async_completion_handler;
|
||||
|
||||
// Initialization complete
|
||||
SetEvent(m_pInitalizeEvent);
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize is guarded by a lock inside APPLICATION_MANAGER::GetApplication
|
||||
// It ensures only one application will be initialized and singleton
|
||||
// Error wuill happen if you call Initialized outside APPLICATION_MANAGER::GetApplication
|
||||
//
|
||||
__override
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::Initialize(
|
||||
_In_ APPLICATION_MANAGER* pApplicationManager,
|
||||
_In_ ASPNETCORE_CONFIG* pConfiguration
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DBG_ASSERT(pApplicationManager != NULL);
|
||||
DBG_ASSERT(pConfiguration != NULL);
|
||||
|
||||
m_pConfiguration = pConfiguration;
|
||||
m_pApplicationManager = pApplicationManager;
|
||||
hr = m_applicationKey.Initialize(pConfiguration->QueryApplicationPath()->QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// check app_offline
|
||||
UpdateAppOfflineFileHandle();
|
||||
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
m_pFileWatcherEntry = new FILE_WATCHER_ENTRY(m_pApplicationManager->GetFileWatcher());
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
m_pInitalizeEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not set
|
||||
NULL); // name
|
||||
if (m_pInitalizeEvent == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
m_fInitialized = TRUE;
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::LoadManagedApplication()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD dwTimeout;
|
||||
DWORD dwResult;
|
||||
BOOL fLocked = FALSE;
|
||||
PCWSTR apsz[1];
|
||||
STACK_STRU(strEventMsg, 256);
|
||||
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
// Core CLR has already been loaded.
|
||||
// Cannot load more than once even there was a failure
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fLocked = TRUE;
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// If the debugger is attached, never timeout
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
dwTimeout = INFINITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwTimeout = m_pConfiguration->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)
|
||||
{
|
||||
// do we need kill the backend thread
|
||||
hr = HRESULT_FROM_WIN32(dwResult);
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwResult == WAIT_FAILED)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// The thread ended it means that something failed
|
||||
if (dwResult == WAIT_OBJECT_0)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
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 ?
|
||||
|
||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
m_pConfiguration->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfiguration->QueryApplicationFullPath()->QueryStr(),
|
||||
hr)))
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
//
|
||||
// not checking return code because if ReportEvent
|
||||
// fails, we cannot do anything.
|
||||
//
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
0,
|
||||
ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::Recycle(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (m_fInitialized)
|
||||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
DWORD dwTimeout = m_pConfiguration->QueryShutdownTimeLimitInMS();
|
||||
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
|
||||
if (!g_pHttpServer->IsCommandLineLaunch() &&
|
||||
!g_fRecycleProcessCalled &&
|
||||
(g_pHttpServer->GetAdminManager() != NULL))
|
||||
{
|
||||
// IIS scenario.
|
||||
// notify IIS first so that new request will be routed to new worker process
|
||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand");
|
||||
}
|
||||
|
||||
g_fRecycleProcessCalled = TRUE;
|
||||
|
||||
// First call into the managed server and shutdown
|
||||
if (m_ShutdownHandler != NULL)
|
||||
{
|
||||
m_ShutdownHandler(m_ShutdownHandlerContext);
|
||||
m_ShutdownHandler = NULL;
|
||||
}
|
||||
|
||||
if (m_hThread != NULL &&
|
||||
GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 &&
|
||||
dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
||||
if (WaitForSingleObject(m_hThread, dwTimeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
TerminateThread(m_hThread, STATUS_CONTROL_C_EXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
s_Application = NULL;
|
||||
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
if (g_pHttpServer && g_pHttpServer->IsCommandLineLaunch())
|
||||
{
|
||||
// IISExpress scenario
|
||||
// Can only call exit to terminate current process
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::OnAppOfflineHandleChange()
|
||||
{
|
||||
// only recycle the worker process after managed app was loaded
|
||||
// app_offline scenario managed application has not been loaded yet
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
Recycle();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_APPLICATION::ExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
)
|
||||
{
|
||||
if (m_RequestHandler != NULL)
|
||||
{
|
||||
return m_RequestHandler(pHttpContext, m_RequstHandlerContext);
|
||||
}
|
||||
|
||||
//
|
||||
// return error as the application did not register callback
|
||||
//
|
||||
if (ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::IsEnabled(pHttpContext->GetTraceContext()))
|
||||
{
|
||||
ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::RaiseEvent(pHttpContext->GetTraceContext(),
|
||||
NULL,
|
||||
E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||
}
|
||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_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;
|
||||
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 = 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());
|
||||
|
||||
if (hModule == NULL)
|
||||
{
|
||||
// .NET Core not installed (we can log a more detailed error message here)
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Get the entry point for main
|
||||
pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main");
|
||||
if (pProc == NULL)
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT; // better hrresult?
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// The first argument is mostly ignored
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Finished:
|
||||
//
|
||||
// this method is called by the background thread and should never exit unless shutdown
|
||||
//
|
||||
if (!g_fRecycleProcessCalled)
|
||||
{
|
||||
STRU strEventMsg;
|
||||
LPCWSTR apsz[1];
|
||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG,
|
||||
m_pConfiguration->QueryApplicationPath()->QueryStr(),
|
||||
m_pConfiguration->QueryApplicationFullPath()->QueryStr(),
|
||||
m_ProcessExitCode
|
||||
)))
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
//
|
||||
// not checking return code because if ReportEvent
|
||||
// fails, we cannot do anything.
|
||||
//
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
EVENTLOG_ERROR_TYPE,
|
||||
0,
|
||||
ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
// error. the thread exits after application started
|
||||
// Question: should we shutdown current worker process or keep the application in failure state?
|
||||
// for now, we reccylce to keep the same behavior as that of out-of-process
|
||||
if (m_fManagedAppLoaded)
|
||||
{
|
||||
Recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
)
|
||||
{
|
||||
|
||||
IN_PROCESS_APPLICATION *pApplication = (IN_PROCESS_APPLICATION*)pContext;
|
||||
DBG_ASSERT(pApplication != NULL);
|
||||
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::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;
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
|
||||
IN_PROCESS_STORED_CONTEXT::IN_PROCESS_STORED_CONTEXT(
|
||||
IHttpContext* pHttpContext,
|
||||
PVOID pMangedHttpContext
|
||||
)
|
||||
{
|
||||
// TODO if we want to go by IIS patterns, we should have these in a separate initialize function
|
||||
m_pManagedHttpContext = pMangedHttpContext;
|
||||
m_pHttpContext = pHttpContext;
|
||||
m_fManagedRequestComplete = FALSE;
|
||||
}
|
||||
|
||||
IN_PROCESS_STORED_CONTEXT::~IN_PROCESS_STORED_CONTEXT()
|
||||
{
|
||||
}
|
||||
|
||||
PVOID
|
||||
IN_PROCESS_STORED_CONTEXT::QueryManagedHttpContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_pManagedHttpContext;
|
||||
}
|
||||
|
||||
IHttpContext*
|
||||
IN_PROCESS_STORED_CONTEXT::QueryHttpContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_pHttpContext;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IN_PROCESS_STORED_CONTEXT::QueryIsManagedRequestComplete(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_fManagedRequestComplete;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_STORED_CONTEXT::IndicateManagedRequestComplete(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
m_fManagedRequestComplete = TRUE;
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_STORED_CONTEXT::QueryAsyncCompletionStatus(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_requestNotificationStatus;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_STORED_CONTEXT::SetAsyncCompletionStatus(
|
||||
REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
)
|
||||
{
|
||||
m_requestNotificationStatus = requestNotificationStatus;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_STORED_CONTEXT::GetInProcessStoredContext(
|
||||
IHttpContext* pHttpContext,
|
||||
IN_PROCESS_STORED_CONTEXT** ppInProcessStoredContext
|
||||
)
|
||||
{
|
||||
if (pHttpContext == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (ppInProcessStoredContext == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*ppInProcessStoredContext = (IN_PROCESS_STORED_CONTEXT*)pHttpContext->GetModuleContextContainer()->GetModuleContext(g_pModuleId);
|
||||
if (*ppInProcessStoredContext == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
IN_PROCESS_STORED_CONTEXT::SetInProcessStoredContext(
|
||||
IHttpContext* pHttpContext,
|
||||
IN_PROCESS_STORED_CONTEXT* pInProcessStoredContext
|
||||
)
|
||||
{
|
||||
if (pHttpContext == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
if (pInProcessStoredContext == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return pHttpContext->GetModuleContextContainer()->SetModuleContext(
|
||||
pInProcessStoredContext,
|
||||
g_pModuleId
|
||||
);
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
// 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 "precomp.hxx"
|
||||
|
||||
OUT_OF_PROCESS_APPLICATION::OUT_OF_PROCESS_APPLICATION()
|
||||
: m_pProcessManager(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
OUT_OF_PROCESS_APPLICATION::~OUT_OF_PROCESS_APPLICATION()
|
||||
{
|
||||
if (m_pProcessManager != NULL)
|
||||
{
|
||||
m_pProcessManager->ShutdownAllProcesses();
|
||||
m_pProcessManager->DereferenceProcessManager();
|
||||
m_pProcessManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Initialize is guarded by a lock inside APPLICATION_MANAGER::GetApplication
|
||||
// It ensures only one application will be initialized and singleton
|
||||
// Error will happen if you call Initialized outside APPLICATION_MANAGER::GetApplication
|
||||
//
|
||||
__override
|
||||
HRESULT
|
||||
OUT_OF_PROCESS_APPLICATION::Initialize(
|
||||
_In_ APPLICATION_MANAGER* pApplicationManager,
|
||||
_In_ ASPNETCORE_CONFIG* pConfiguration
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DBG_ASSERT(pApplicationManager != NULL);
|
||||
DBG_ASSERT(pConfiguration != NULL);
|
||||
|
||||
m_pApplicationManager = pApplicationManager;
|
||||
m_pConfiguration = pConfiguration;
|
||||
|
||||
hr = m_applicationKey.Initialize(pConfiguration->QueryApplicationPath()->QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (m_pProcessManager == NULL)
|
||||
{
|
||||
m_pProcessManager = new PROCESS_MANAGER;
|
||||
if (m_pProcessManager == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_pProcessManager->Initialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
m_pFileWatcherEntry = new FILE_WATCHER_ENTRY(pApplicationManager->GetFileWatcher());
|
||||
if (m_pFileWatcherEntry == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAppOfflineFileHandle();
|
||||
|
||||
Finished:
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (m_pFileWatcherEntry != NULL)
|
||||
{
|
||||
m_pFileWatcherEntry->DereferenceFileWatcherEntry();
|
||||
m_pFileWatcherEntry = NULL;
|
||||
}
|
||||
|
||||
if (m_pProcessManager != NULL)
|
||||
{
|
||||
m_pProcessManager->DereferenceProcessManager();
|
||||
m_pProcessManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
__override
|
||||
VOID
|
||||
OUT_OF_PROCESS_APPLICATION::OnAppOfflineHandleChange()
|
||||
{
|
||||
//
|
||||
// Sending signal to backend process for shutdown
|
||||
//
|
||||
if (m_pProcessManager != NULL)
|
||||
{
|
||||
m_pProcessManager->SendShutdownSignal();
|
||||
}
|
||||
}
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OUT_OF_PROCESS_APPLICATION::ExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
)
|
||||
{
|
||||
//
|
||||
// TODO:
|
||||
// Ideally we should wrap the fowaring logic inside FORWARDING_HANDLER inside this function
|
||||
// To achieve better abstraction. It is too risky to do it now
|
||||
//
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
|
@ -54,13 +54,6 @@
|
|||
#define WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS 111
|
||||
#endif
|
||||
|
||||
#define ASPNETCORE_EVENT_PROVIDER L"IIS AspNetCore Module"
|
||||
#define ASPNETCORE_IISEXPRESS_EVENT_PROVIDER L"IIS Express AspNetCore Module"
|
||||
|
||||
#define TIMESPAN_IN_MILLISECONDS(x) ((x)/((LONGLONG)(10000)))
|
||||
#define TIMESPAN_IN_SECONDS(x) ((TIMESPAN_IN_MILLISECONDS(x))/((LONGLONG)(1000)))
|
||||
#define TIMESPAN_IN_MINUTES(x) ((TIMESPAN_IN_SECONDS(x))/((LONGLONG)(60)))
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
template<typename T> inline T max(T a, T b)
|
||||
|
@ -97,43 +90,33 @@ inline bool IsSpace(char ch)
|
|||
#include <hashtable.h>
|
||||
#include "stringa.h"
|
||||
#include "stringu.h"
|
||||
//#include "treehash.h"
|
||||
|
||||
#include "dbgutil.h"
|
||||
#include "ahutil.h"
|
||||
#include "multisz.h"
|
||||
#include "multisza.h"
|
||||
#include "base64.h"
|
||||
#include "sttimer.h"
|
||||
#include <listentry.h>
|
||||
#include <datetime.h>
|
||||
#include <reftrace.h>
|
||||
#include <acache.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "environmentvariablehash.h"
|
||||
#include "..\aspnetcore_msg.h"
|
||||
#include "aspnetcore_event.h"
|
||||
#include "aspnetcoreconfig.h"
|
||||
#include "serverprocess.h"
|
||||
#include "processmanager.h"
|
||||
#include "..\..\CommonLib\environmentvariablehash.h"
|
||||
#include "..\..\CommonLib\aspnetcoreconfig.h"
|
||||
#include "..\..\CommonLib\application.h"
|
||||
#include "..\..\CommonLib\utility.h"
|
||||
#include "..\..\CommonLib\debugutil.h"
|
||||
#include "..\..\CommonLib\requesthandler.h"
|
||||
//#include "..\aspnetcore_msg.h"
|
||||
//#include "aspnetcore_event.h"
|
||||
#include "appoffline.h"
|
||||
#include "filewatcher.h"
|
||||
#include "application.h"
|
||||
#include "applicationinfo.h"
|
||||
#include "applicationmanager.h"
|
||||
#include "inprocessstoredcontext.h"
|
||||
#include "inprocessapplication.h"
|
||||
#include "outprocessapplication.h"
|
||||
#include "globalmodule.h"
|
||||
#include "resource.h"
|
||||
#include "path.h"
|
||||
#include "debugutil.h"
|
||||
#include "protocolconfig.h"
|
||||
#include "responseheaderhash.h"
|
||||
#include "forwarderconnection.h"
|
||||
#include "winhttphelper.h"
|
||||
#include "websockethandler.h"
|
||||
#include "forwardinghandler.h"
|
||||
#include "proxymodule.h"
|
||||
#include "fx_ver.h"
|
||||
|
||||
|
||||
FORCEINLINE
|
||||
DWORD
|
||||
|
@ -158,11 +141,15 @@ HRESULT_FROM_GETLASTERROR()
|
|||
: E_FAIL;
|
||||
}
|
||||
|
||||
extern BOOL g_fAsyncDisconnectAvailable;
|
||||
extern BOOL g_fWinHttpNonBlockingCallbackAvailable;
|
||||
extern PVOID g_pModuleId;
|
||||
extern BOOL g_fWebSocketSupported;
|
||||
extern BOOL g_fAspnetcoreRHAssemblyLoaded;
|
||||
extern BOOL g_fAspnetcoreRHLoadedError;
|
||||
extern BOOL g_fEnableReferenceCountTracing;
|
||||
extern DWORD g_dwActiveServerProcesses;
|
||||
extern DWORD g_OptionalWinHttpFlags;
|
||||
extern HMODULE g_hAspnetCoreRH;
|
||||
extern SRWLOCK g_srwLock;
|
||||
extern PCWSTR g_pwzAspnetcoreRequestHandlerName;
|
||||
|
||||
extern PFN_ASPNETCORE_CREATE_APPLICATION g_pfnAspNetCoreCreateApplication;
|
||||
extern PFN_ASPNETCORE_CREATE_REQUEST_HANDLER g_pfnAspNetCoreCreateRequestHandler;
|
||||
#pragma warning( error : 4091)
|
|
@ -1,294 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
|
||||
volatile BOOL PROCESS_MANAGER::sm_fWSAStartupDone = FALSE;
|
||||
|
||||
HRESULT
|
||||
PROCESS_MANAGER::Initialize(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
WSADATA wsaData;
|
||||
int result;
|
||||
BOOL fLocked = FALSE;
|
||||
|
||||
if( !sm_fWSAStartupDone )
|
||||
{
|
||||
AcquireSRWLockExclusive( &m_srwLock );
|
||||
fLocked = TRUE;
|
||||
|
||||
if( !sm_fWSAStartupDone )
|
||||
{
|
||||
if( (result = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 )
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32( result );
|
||||
goto Finished;
|
||||
}
|
||||
sm_fWSAStartupDone = TRUE;
|
||||
}
|
||||
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
fLocked = FALSE;
|
||||
}
|
||||
|
||||
m_dwRapidFailTickStart = GetTickCount();
|
||||
|
||||
if( m_hNULHandle == NULL )
|
||||
{
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
m_hNULHandle = CreateFileW( L"NUL",
|
||||
FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
if( m_hNULHandle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
hr = HRESULT_FROM_GETLASTERROR();
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if(fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
PROCESS_MANAGER::~PROCESS_MANAGER()
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
|
||||
if( m_ppServerProcessList != NULL )
|
||||
{
|
||||
for( DWORD i = 0; i < m_dwProcessesPerApplication; ++i )
|
||||
{
|
||||
if( m_ppServerProcessList[i] != NULL )
|
||||
{
|
||||
m_ppServerProcessList[i]->DereferenceServerProcess();
|
||||
m_ppServerProcessList[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_ppServerProcessList;
|
||||
m_ppServerProcessList = NULL;
|
||||
}
|
||||
|
||||
if( m_hNULHandle != NULL )
|
||||
{
|
||||
CloseHandle( m_hNULHandle );
|
||||
m_hNULHandle = NULL;
|
||||
}
|
||||
|
||||
if( sm_fWSAStartupDone )
|
||||
{
|
||||
WSACleanup();
|
||||
sm_fWSAStartupDone = FALSE;
|
||||
}
|
||||
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
PROCESS_MANAGER::GetProcess(
|
||||
_In_ IHttpContext *context,
|
||||
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fSharedLock = FALSE;
|
||||
BOOL fExclusiveLock = FALSE;
|
||||
PCWSTR apsz[1];
|
||||
STACK_STRU( strEventMsg, 256 );
|
||||
DWORD dwProcessIndex = 0;
|
||||
SERVER_PROCESS **ppSelectedServerProcess = NULL;
|
||||
|
||||
if (!m_fServerProcessListReady)
|
||||
{
|
||||
AcquireSRWLockExclusive( &m_srwLock );
|
||||
fExclusiveLock = TRUE;
|
||||
|
||||
if (!m_fServerProcessListReady)
|
||||
{
|
||||
m_dwProcessesPerApplication = pConfig->QueryProcessesPerApplication();
|
||||
m_ppServerProcessList = new SERVER_PROCESS*[m_dwProcessesPerApplication];
|
||||
if(m_ppServerProcessList == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
for(DWORD i=0;i<m_dwProcessesPerApplication;++i)
|
||||
{
|
||||
m_ppServerProcessList[i] = NULL;
|
||||
}
|
||||
}
|
||||
m_fServerProcessListReady = TRUE;
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
fExclusiveLock = FALSE;
|
||||
}
|
||||
|
||||
AcquireSRWLockShared( &m_srwLock );
|
||||
fSharedLock = TRUE;
|
||||
|
||||
//
|
||||
// round robin through to the next available process.
|
||||
//
|
||||
|
||||
dwProcessIndex = (DWORD) InterlockedIncrement64( (LONGLONG*) &m_dwRouteToProcessIndex );
|
||||
dwProcessIndex = dwProcessIndex % m_dwProcessesPerApplication;
|
||||
ppSelectedServerProcess = &m_ppServerProcessList[dwProcessIndex];
|
||||
|
||||
if( *ppSelectedServerProcess != NULL &&
|
||||
m_ppServerProcessList[dwProcessIndex]->IsReady() )
|
||||
{
|
||||
m_ppServerProcessList[dwProcessIndex]->ReferenceServerProcess();
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
ReleaseSRWLockShared( &m_srwLock );
|
||||
fSharedLock = FALSE;
|
||||
// should make the lock per process so that we can start processes simultaneously ?
|
||||
|
||||
if(m_ppServerProcessList[dwProcessIndex] == NULL || !m_ppServerProcessList[dwProcessIndex]->IsReady())
|
||||
{
|
||||
AcquireSRWLockExclusive( &m_srwLock );
|
||||
fExclusiveLock = TRUE;
|
||||
|
||||
if( m_ppServerProcessList[dwProcessIndex] != NULL )
|
||||
{
|
||||
if( !m_ppServerProcessList[dwProcessIndex]->IsReady() )
|
||||
{
|
||||
//
|
||||
// terminate existing process that is not ready
|
||||
// before creating new one.
|
||||
//
|
||||
|
||||
ShutdownProcessNoLock( m_ppServerProcessList[dwProcessIndex] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// server is already up and ready to serve requests.
|
||||
m_ppServerProcessList[dwProcessIndex]->ReferenceServerProcess();
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if( RapidFailsPerMinuteExceeded(pConfig->QueryRapidFailsPerMinute()) )
|
||||
{
|
||||
//
|
||||
// rapid fails per minute exceeded, do not create new process.
|
||||
//
|
||||
|
||||
if( SUCCEEDED( strEventMsg.SafeSnwprintf(
|
||||
ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG,
|
||||
pConfig->QueryRapidFailsPerMinute() ) ) )
|
||||
{
|
||||
apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
//
|
||||
// not checking return code because if ReportEvent
|
||||
// fails, we cannot do anything.
|
||||
//
|
||||
if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
{
|
||||
ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
EVENTLOG_INFORMATION_TYPE,
|
||||
0,
|
||||
ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
apsz,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if( m_ppServerProcessList[dwProcessIndex] == NULL )
|
||||
{
|
||||
m_ppServerProcessList[dwProcessIndex] = new SERVER_PROCESS();
|
||||
if( m_ppServerProcessList[dwProcessIndex] == NULL )
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_ppServerProcessList[dwProcessIndex]->Initialize(
|
||||
this,
|
||||
pConfig->QueryProcessPath(),
|
||||
pConfig->QueryArguments(),
|
||||
pConfig->QueryStartupTimeLimitInMS(),
|
||||
pConfig->QueryShutdownTimeLimitInMS(),
|
||||
pConfig->QueryWindowsAuthEnabled(),
|
||||
pConfig->QueryBasicAuthEnabled(),
|
||||
pConfig->QueryAnonymousAuthEnabled(),
|
||||
pConfig->QueryEnvironmentVariables(),
|
||||
pConfig->QueryStdoutLogEnabled(),
|
||||
pConfig->QueryStdoutLogFile()
|
||||
);
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_ppServerProcessList[dwProcessIndex]->StartProcess(context);
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_ppServerProcessList[dwProcessIndex]->IsReady() )
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32( ERROR_CREATE_FAILED );
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_ppServerProcessList[dwProcessIndex]->ReferenceServerProcess();
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
if(m_ppServerProcessList[dwProcessIndex] != NULL )
|
||||
{
|
||||
m_ppServerProcessList[dwProcessIndex]->DereferenceServerProcess();
|
||||
m_ppServerProcessList[dwProcessIndex] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( fSharedLock )
|
||||
{
|
||||
ReleaseSRWLockShared( &m_srwLock );
|
||||
fSharedLock = FALSE;
|
||||
}
|
||||
|
||||
if( fExclusiveLock )
|
||||
{
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
fExclusiveLock = FALSE;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
__override
|
||||
HRESULT
|
||||
CProxyModuleFactory::GetHttpModule(
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY::GetHttpModule(
|
||||
CHttpModule ** ppModule,
|
||||
IModuleAllocator * pAllocator
|
||||
)
|
||||
{
|
||||
CProxyModule *pModule = new (pAllocator) CProxyModule();
|
||||
ASPNET_CORE_PROXY_MODULE *pModule = new (pAllocator) ASPNET_CORE_PROXY_MODULE();
|
||||
if (pModule == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
|
@ -22,7 +22,7 @@ CProxyModuleFactory::GetHttpModule(
|
|||
|
||||
__override
|
||||
VOID
|
||||
CProxyModuleFactory::Terminate(
|
||||
ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
@ -41,39 +41,38 @@ Return value:
|
|||
|
||||
--*/
|
||||
{
|
||||
FORWARDING_HANDLER::StaticTerminate();
|
||||
/* FORWARDING_HANDLER::StaticTerminate();
|
||||
|
||||
WEBSOCKET_HANDLER::StaticTerminate();
|
||||
|
||||
if (g_pResponseHeaderHash != NULL)
|
||||
{
|
||||
g_pResponseHeaderHash->Clear();
|
||||
delete g_pResponseHeaderHash;
|
||||
g_pResponseHeaderHash = NULL;
|
||||
}
|
||||
WEBSOCKET_HANDLER::StaticTerminate();*/
|
||||
|
||||
ALLOC_CACHE_HANDLER::StaticTerminate();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CProxyModule::CProxyModule(
|
||||
) : m_pHandler(NULL)
|
||||
ASPNET_CORE_PROXY_MODULE::ASPNET_CORE_PROXY_MODULE(
|
||||
) : m_pApplicationInfo(NULL), m_pHandler(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CProxyModule::~CProxyModule()
|
||||
ASPNET_CORE_PROXY_MODULE::~ASPNET_CORE_PROXY_MODULE()
|
||||
{
|
||||
if (m_pApplicationInfo != NULL)
|
||||
{
|
||||
m_pApplicationInfo->DereferenceApplicationInfo();
|
||||
m_pApplicationInfo = NULL;
|
||||
}
|
||||
|
||||
if (m_pHandler != NULL)
|
||||
{
|
||||
m_pHandler->DereferenceForwardingHandler();
|
||||
m_pHandler->DereferenceRequestHandler();
|
||||
m_pHandler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
CProxyModule::OnExecuteRequestHandler(
|
||||
ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
||||
IHttpContext * pHttpContext,
|
||||
IHttpEventProvider *
|
||||
)
|
||||
|
@ -81,47 +80,105 @@ CProxyModule::OnExecuteRequestHandler(
|
|||
HRESULT hr = S_OK;
|
||||
ASPNETCORE_CONFIG *pConfig = NULL;
|
||||
APPLICATION_MANAGER *pApplicationManager = NULL;
|
||||
APPLICATION *pApplication = NULL;
|
||||
hr = ASPNETCORE_CONFIG::GetConfig(pHttpContext, &pConfig);
|
||||
REQUEST_NOTIFICATION_STATUS retVal = RQ_NOTIFICATION_CONTINUE;
|
||||
APPLICATION* pApplication = NULL;
|
||||
STACK_STRU(struFileName, 256);
|
||||
|
||||
hr = ASPNETCORE_CONFIG::GetConfig(g_pHttpServer, g_pModuleId, pHttpContext, &pConfig);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Failed;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
||||
if (pApplicationManager == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Failed;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pApplicationManager->GetApplication(
|
||||
pHttpContext,
|
||||
pConfig,
|
||||
&pApplication);
|
||||
hr = pApplicationManager->GetApplicationInfo(
|
||||
g_pHttpServer,
|
||||
pConfig,
|
||||
&m_pApplicationInfo);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Failed;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_pHandler = new FORWARDING_HANDLER(pHttpContext, pApplication);
|
||||
|
||||
if (m_pHandler == NULL)
|
||||
// app_offline check to avoid loading aspnetcorerh.dll unnecessarily
|
||||
if (m_pApplicationInfo->AppOfflineFound())
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Failed;
|
||||
// servicing app_offline
|
||||
HTTP_DATA_CHUNK DataChunk;
|
||||
IHttpResponse *pResponse = NULL;
|
||||
APP_OFFLINE_HTM *pAppOfflineHtm = NULL;
|
||||
|
||||
pResponse = pHttpContext->GetResponse();
|
||||
pAppOfflineHtm = m_pApplicationInfo->QueryAppOfflineHtm();
|
||||
DBG_ASSERT(pAppOfflineHtm);
|
||||
DBG_ASSERT(pResponse);
|
||||
|
||||
// Ignore failure hresults as nothing we can do
|
||||
// Set fTrySkipCustomErrors to true as we want client see the offline content
|
||||
pResponse->SetStatus(503, "Service Unavailable", 0, hr, NULL, TRUE);
|
||||
pResponse->SetHeader("Content-Type",
|
||||
"text/html",
|
||||
(USHORT)strlen("text/html"),
|
||||
FALSE
|
||||
);
|
||||
|
||||
DataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||
DataChunk.FromMemory.pBuffer = (PVOID)pAppOfflineHtm->m_Contents.QueryStr();
|
||||
DataChunk.FromMemory.BufferLength = pAppOfflineHtm->m_Contents.QueryCB();
|
||||
pResponse->WriteEntityChunkByReference(&DataChunk);
|
||||
|
||||
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
return m_pHandler->OnExecuteRequestHandler();
|
||||
// make sure assmebly is loaded and application is created
|
||||
|
||||
Failed:
|
||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr);
|
||||
return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
hr = m_pApplicationInfo->EnsureApplicationCreated();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
pApplication = m_pApplicationInfo->QueryApplication();
|
||||
DBG_ASSERT(pApplication);
|
||||
|
||||
// make sure application is in running state
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Create RequestHandler and process the request
|
||||
hr = m_pApplicationInfo->QueryCreateRequestHandler()(pHttpContext,
|
||||
(HTTP_MODULE_ID*) &g_pModuleId,
|
||||
pApplication,
|
||||
&m_pHandler);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
retVal = m_pHandler->OnExecuteRequestHandler();
|
||||
|
||||
Finished:
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr);
|
||||
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
CProxyModule::OnAsyncCompletion(
|
||||
ASPNET_CORE_PROXY_MODULE::OnAsyncCompletion(
|
||||
IHttpContext *,
|
||||
DWORD,
|
||||
BOOL,
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{55494E58-E061-4C4C-A0A8-837008E72F85}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NewCommon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>C:\AspNetCoreModule\src\IISLib;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>
|
||||
</AdditionalIncludeDirectories>
|
||||
<AdditionalUsingDirectories>
|
||||
</AdditionalUsingDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>..\iislib</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="application.h" />
|
||||
<ClInclude Include="aspnetcoreconfig.h" />
|
||||
<ClInclude Include="debugutil.h" />
|
||||
<ClInclude Include="environmentvariablehash.h" />
|
||||
<ClInclude Include="fx_ver.h" />
|
||||
<ClInclude Include="hostfxr_utility.h" />
|
||||
<ClInclude Include="requesthandler.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="utility.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="application.cpp" />
|
||||
<ClCompile Include="aspnetcoreconfig.cxx" />
|
||||
<ClCompile Include="fx_ver.cxx" />
|
||||
<ClCompile Include="hostfxr_utility.cpp" />
|
||||
<ClCompile Include="requesthandler.cxx" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utility.cxx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
||||
<Project>{4787a64f-9a3e-4867-a55a-70cb4b2b2ffe}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
APPLICATION::APPLICATION(
|
||||
_In_ IHttpServer* pHttpServer,
|
||||
_In_ ASPNETCORE_CONFIG* pConfig) :
|
||||
m_cRefs(1),
|
||||
m_pHttpServer(pHttpServer),
|
||||
m_pConfig(pConfig),
|
||||
m_status(APPLICATION_STATUS::UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
APPLICATION::~APPLICATION()
|
||||
{
|
||||
}
|
||||
|
||||
APPLICATION_STATUS
|
||||
APPLICATION::QueryStatus()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
ASPNETCORE_CONFIG*
|
||||
APPLICATION::QueryConfig()
|
||||
{
|
||||
return m_pConfig;
|
||||
}
|
||||
|
||||
VOID
|
||||
APPLICATION::ReferenceApplication()
|
||||
const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
VOID
|
||||
APPLICATION::DereferenceApplication()
|
||||
const
|
||||
{
|
||||
DBG_ASSERT(m_cRefs != 0);
|
||||
|
||||
LONG cRefs = 0;
|
||||
if ((cRefs = InterlockedDecrement(&m_cRefs)) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
enum APPLICATION_STATUS
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
RUNNING,
|
||||
FAUL
|
||||
};
|
||||
|
||||
class ASPNETCORE_CONFIG;
|
||||
|
||||
class APPLICATION
|
||||
{
|
||||
public:
|
||||
APPLICATION(
|
||||
_In_ IHttpServer* pHttpServer,
|
||||
_In_ ASPNETCORE_CONFIG* pConfig);
|
||||
|
||||
virtual
|
||||
VOID
|
||||
ShutDown() = 0;
|
||||
|
||||
virtual
|
||||
~APPLICATION();
|
||||
|
||||
APPLICATION_STATUS
|
||||
QueryStatus();
|
||||
|
||||
ASPNETCORE_CONFIG*
|
||||
QueryConfig();
|
||||
|
||||
VOID
|
||||
ReferenceApplication()
|
||||
const;
|
||||
|
||||
VOID
|
||||
DereferenceApplication()
|
||||
const;
|
||||
|
||||
protected:
|
||||
mutable LONG m_cRefs;
|
||||
APPLICATION_STATUS m_status;
|
||||
IHttpServer* m_pHttpServer;
|
||||
ASPNETCORE_CONFIG* m_pConfig;
|
||||
};
|
|
@ -1,56 +1,47 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include "stdafx.h"
|
||||
#include "aspnetcoreconfig.h"
|
||||
|
||||
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
||||
{
|
||||
if (QueryHostingModel() == HOSTING_IN_PROCESS &&
|
||||
!g_fRecycleProcessCalled &&
|
||||
(g_pHttpServer->GetAdminManager() != NULL))
|
||||
{
|
||||
// There is a bug in IHttpServer::RecycleProcess. It will hit AV when worker process
|
||||
// has already been in recycling state.
|
||||
// To workaround, do null check on GetAdminManager(). If it is NULL, worker process is in recycling
|
||||
// Do not call RecycleProcess again
|
||||
|
||||
// RecycleProcess can olny be called once
|
||||
// In case of configuration change for in-process app
|
||||
// We want notify IIS first to let new request routed to new worker process
|
||||
|
||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Configuration Change");
|
||||
}
|
||||
|
||||
// It's safe for us to set this g_fRecycleProcessCalled
|
||||
// as in_process scenario will always recycle the worker process for configuration change
|
||||
g_fRecycleProcessCalled = TRUE;
|
||||
|
||||
m_struApplicationFullPath.Reset();
|
||||
if (m_pEnvironmentVariables != NULL)
|
||||
{
|
||||
m_pEnvironmentVariables->Clear();
|
||||
delete m_pEnvironmentVariables;
|
||||
m_pEnvironmentVariables = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_struApplication.IsEmpty())
|
||||
{
|
||||
APPLICATION_MANAGER::GetInstance()->RecycleApplication(m_struApplication.QueryStr());
|
||||
}
|
||||
VOID
|
||||
ASPNETCORE_CONFIG::ReferenceConfiguration(
|
||||
VOID
|
||||
) const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
if (QueryHostingModel() == HOSTING_IN_PROCESS &&
|
||||
g_pHttpServer->IsCommandLineLaunch())
|
||||
|
||||
VOID
|
||||
ASPNETCORE_CONFIG::DereferenceConfiguration(
|
||||
VOID
|
||||
) const
|
||||
{
|
||||
DBG_ASSERT(m_cRefs != 0);
|
||||
LONG cRefs = 0;
|
||||
if ((cRefs = InterlockedDecrement(&m_cRefs)) == 0)
|
||||
{
|
||||
// IISExpress scenario, only option is to call exit in case configuration change
|
||||
// as CLR or application may change
|
||||
exit(0);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ASPNETCORE_CONFIG::GetConfig(
|
||||
_In_ IHttpServer *pHttpServer,
|
||||
_In_ HTTP_MODULE_ID pModuleId,
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
@ -67,7 +58,7 @@ ASPNETCORE_CONFIG::GetConfig(
|
|||
|
||||
// potential bug if user sepcific config at virtual dir level
|
||||
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)
|
||||
pHttpApplication->GetModuleContextContainer()->GetModuleContext(g_pModuleId);
|
||||
pHttpApplication->GetModuleContextContainer()->GetModuleContext(pModuleId);
|
||||
|
||||
if (pAspNetCoreConfig != NULL)
|
||||
{
|
||||
|
@ -83,14 +74,14 @@ ASPNETCORE_CONFIG::GetConfig(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pAspNetCoreConfig->Populate(pHttpContext);
|
||||
hr = pAspNetCoreConfig->Populate(pHttpServer, pHttpContext);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pHttpApplication->GetModuleContextContainer()->
|
||||
SetModuleContext(pAspNetCoreConfig, g_pModuleId);
|
||||
SetModuleContext(pAspNetCoreConfig, pModuleId);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_ASSIGNED))
|
||||
|
@ -99,7 +90,7 @@ ASPNETCORE_CONFIG::GetConfig(
|
|||
|
||||
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)pHttpApplication->
|
||||
GetModuleContextContainer()->
|
||||
GetModuleContext(g_pModuleId);
|
||||
GetModuleContext(pModuleId);
|
||||
|
||||
_ASSERT(pAspNetCoreConfig != NULL);
|
||||
|
||||
|
@ -137,11 +128,11 @@ Finished:
|
|||
|
||||
HRESULT
|
||||
ASPNETCORE_CONFIG::Populate(
|
||||
IHttpServer *pHttpServer,
|
||||
IHttpContext *pHttpContext
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STACK_STRU(strSiteConfigPath, 256);
|
||||
STRU strEnvName;
|
||||
STRU strEnvValue;
|
||||
STRU strExpandedEnvValue;
|
||||
|
@ -160,6 +151,10 @@ ASPNETCORE_CONFIG::Populate(
|
|||
DWORD dwCounter = 0;
|
||||
DWORD dwPosition = 0;
|
||||
WCHAR* pszPath = NULL;
|
||||
BSTR bstrWindowAuthSection = NULL;
|
||||
BSTR bstrBasicAuthSection = NULL;
|
||||
BSTR bstrAnonymousAuthSection = NULL;
|
||||
BSTR bstrAspNetCoreSection = NULL;
|
||||
|
||||
m_pEnvironmentVariables = new ENVIRONMENT_VAR_HASH();
|
||||
if (m_pEnvironmentVariables == NULL)
|
||||
|
@ -174,20 +169,20 @@ ASPNETCORE_CONFIG::Populate(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
pAdminManager = g_pHttpServer->GetAdminManager();
|
||||
hr = strSiteConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
||||
pAdminManager = pHttpServer->GetAdminManager();
|
||||
hr = m_struConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_struApplicationFullPath.Copy(pHttpContext->GetApplication()->GetApplicationPhysicalPath());
|
||||
hr = m_struApplicationPhysicalPath.Copy(pHttpContext->GetApplication()->GetApplicationPhysicalPath());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
pszPath = strSiteConfigPath.QueryStr();
|
||||
pszPath = m_struConfigPath.QueryStr();
|
||||
while (pszPath[dwPosition] != NULL)
|
||||
{
|
||||
if (pszPath[dwPosition] == '/')
|
||||
|
@ -214,8 +209,15 @@ ASPNETCORE_CONFIG::Populate(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pAdminManager->GetAdminSection(CS_WINDOWS_AUTHENTICATION_SECTION,
|
||||
strSiteConfigPath.QueryStr(),
|
||||
bstrWindowAuthSection = SysAllocString(CS_WINDOWS_AUTHENTICATION_SECTION);
|
||||
if (bstrWindowAuthSection == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pAdminManager->GetAdminSection(bstrWindowAuthSection,
|
||||
m_struConfigPath.QueryStr(),
|
||||
&pWindowsAuthenticationElement);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -235,8 +237,14 @@ ASPNETCORE_CONFIG::Populate(
|
|||
}
|
||||
}
|
||||
|
||||
hr = pAdminManager->GetAdminSection(CS_BASIC_AUTHENTICATION_SECTION,
|
||||
strSiteConfigPath.QueryStr(),
|
||||
bstrBasicAuthSection = SysAllocString(CS_BASIC_AUTHENTICATION_SECTION);
|
||||
if (bstrBasicAuthSection == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
hr = pAdminManager->GetAdminSection(bstrBasicAuthSection,
|
||||
m_struConfigPath.QueryStr(),
|
||||
&pBasicAuthenticationElement);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -252,9 +260,14 @@ ASPNETCORE_CONFIG::Populate(
|
|||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
hr = pAdminManager->GetAdminSection(CS_ANONYMOUS_AUTHENTICATION_SECTION,
|
||||
strSiteConfigPath.QueryStr(),
|
||||
bstrAnonymousAuthSection = SysAllocString(CS_ANONYMOUS_AUTHENTICATION_SECTION);
|
||||
if (bstrAnonymousAuthSection == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
hr = pAdminManager->GetAdminSection(bstrAnonymousAuthSection,
|
||||
m_struConfigPath.QueryStr(),
|
||||
&pAnonymousAuthenticationElement);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -271,8 +284,14 @@ ASPNETCORE_CONFIG::Populate(
|
|||
}
|
||||
}
|
||||
|
||||
hr = pAdminManager->GetAdminSection(CS_ASPNETCORE_SECTION,
|
||||
strSiteConfigPath.QueryStr(),
|
||||
bstrAspNetCoreSection = SysAllocString(CS_ASPNETCORE_SECTION);
|
||||
if (bstrAspNetCoreSection == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
hr = pAdminManager->GetAdminSection(bstrAspNetCoreSection,
|
||||
m_struConfigPath.QueryStr(),
|
||||
&pAspNetCoreElement);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -402,13 +421,13 @@ ASPNETCORE_CONFIG::Populate(
|
|||
{
|
||||
goto Finished;
|
||||
}
|
||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||
CS_ASPNETCORE_STDOUT_LOG_FILE,
|
||||
&m_struStdoutLogFile);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
||||
CS_ASPNETCORE_STDOUT_LOG_FILE,
|
||||
&m_struStdoutLogFile);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = GetElementChildByName(pAspNetCoreElement,
|
||||
CS_ASPNETCORE_ENVIRONMENT_VARIABLES,
|
|
@ -34,11 +34,13 @@
|
|||
#define MIN_PORT 1025
|
||||
#define MAX_PORT 48000
|
||||
|
||||
#define HEX_TO_ASCII(c) ((CHAR)(((c) < 10) ? ((c) + '0') : ((c) + 'a' - 10)))
|
||||
#define TIMESPAN_IN_MILLISECONDS(x) ((x)/((LONGLONG)(10000)))
|
||||
#define TIMESPAN_IN_SECONDS(x) ((TIMESPAN_IN_MILLISECONDS(x))/((LONGLONG)(1000)))
|
||||
#define TIMESPAN_IN_MINUTES(x) ((TIMESPAN_IN_SECONDS(x))/((LONGLONG)(60)))
|
||||
|
||||
extern HTTP_MODULE_ID g_pModuleId;
|
||||
extern IHttpServer * g_pHttpServer;
|
||||
extern BOOL g_fRecycleProcessCalled;
|
||||
//#define HEX_TO_ASCII(c) ((CHAR)(((c) < 10) ? ((c) + '0') : ((c) + 'a' - 10)))
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
enum APP_HOSTING_MODEL
|
||||
{
|
||||
|
@ -57,14 +59,16 @@ public:
|
|||
VOID
|
||||
CleanupStoredContext()
|
||||
{
|
||||
delete this;
|
||||
DereferenceConfiguration();
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetConfig(
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
_In_ IHttpServer *pHttpServer,
|
||||
_In_ HTTP_MODULE_ID pModuleId,
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
||||
);
|
||||
|
||||
ENVIRONMENT_VAR_HASH*
|
||||
|
@ -132,11 +136,11 @@ public:
|
|||
}
|
||||
|
||||
STRU*
|
||||
QueryApplicationFullPath(
|
||||
QueryApplicationPhysicalPath(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return &m_struApplicationFullPath;
|
||||
return &m_struApplicationPhysicalPath;
|
||||
}
|
||||
|
||||
STRU*
|
||||
|
@ -149,30 +153,22 @@ public:
|
|||
|
||||
STRU*
|
||||
QueryProcessPath(
|
||||
VOID
|
||||
)
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return &m_struProcessPath;
|
||||
}
|
||||
|
||||
APP_HOSTING_MODEL
|
||||
QueryHostingModel(
|
||||
VOID
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_hostingModel;
|
||||
}
|
||||
|
||||
STRU*
|
||||
QueryHostingModelStr(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return &m_strHostingModel;
|
||||
}
|
||||
|
||||
BOOL
|
||||
QueryStdoutLogEnabled()
|
||||
QueryStdoutLogEnabled()
|
||||
{
|
||||
return m_fStdoutLogEnabled;
|
||||
}
|
||||
|
@ -213,6 +209,36 @@ public:
|
|||
return &m_struStdoutLogFile;
|
||||
}
|
||||
|
||||
STRU*
|
||||
QueryConfigPath()
|
||||
{
|
||||
return &m_struConfigPath;
|
||||
}
|
||||
|
||||
STRU*
|
||||
QueryHostfxrPath()
|
||||
{
|
||||
return &m_struHostFxrPath;
|
||||
}
|
||||
|
||||
BOOL
|
||||
QueryIsStandAloneApplication(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_fIsStandAloneApplication;
|
||||
}
|
||||
|
||||
VOID
|
||||
ReferenceConfiguration(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
VOID
|
||||
DereferenceConfiguration(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
|
@ -221,33 +247,40 @@ private:
|
|||
ASPNETCORE_CONFIG():
|
||||
m_fStdoutLogEnabled( FALSE ),
|
||||
m_pEnvironmentVariables( NULL ),
|
||||
m_cRefs( 1 ),
|
||||
m_hostingModel( HOSTING_UNKNOWN )
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Populate(
|
||||
IHttpServer *pHttpServer,
|
||||
IHttpContext *pHttpContext
|
||||
);
|
||||
|
||||
mutable LONG m_cRefs;
|
||||
|
||||
DWORD m_dwRequestTimeoutInMS;
|
||||
DWORD m_dwStartupTimeLimitInMS;
|
||||
DWORD m_dwShutdownTimeLimitInMS;
|
||||
DWORD m_dwRapidFailsPerMinute;
|
||||
DWORD m_dwProcessesPerApplication;
|
||||
STRU m_struApplication;
|
||||
STRU m_struArguments;
|
||||
STRU m_struProcessPath;
|
||||
STRU m_struStdoutLogFile;
|
||||
STRU m_struApplicationFullPath;
|
||||
STRU m_strHostingModel;
|
||||
STRU m_struApplication;
|
||||
STRU m_struApplicationPhysicalPath;
|
||||
STRU m_struApplicationVirtualPath;
|
||||
STRU m_struConfigPath;
|
||||
STRU m_strHostingModel;
|
||||
STRU m_struHostFxrPath;
|
||||
BOOL m_fStdoutLogEnabled;
|
||||
BOOL m_fForwardWindowsAuthToken;
|
||||
BOOL m_fDisableStartUpErrorPage;
|
||||
BOOL m_fWindowsAuthEnabled;
|
||||
BOOL m_fBasicAuthEnabled;
|
||||
BOOL m_fAnonymousAuthEnabled;
|
||||
BOOL m_fIsStandAloneApplication;
|
||||
APP_HOSTING_MODEL m_hostingModel;
|
||||
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
||||
};
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ASPNETCORE_DEBUG_FLAG_INFO 0x00000001
|
||||
#define ASPNETCORE_DEBUG_FLAG_WARNING 0x00000002
|
||||
#define ASPNETCORE_DEBUG_FLAG_ERROR 0x00000004
|
|
@ -0,0 +1,192 @@
|
|||
// 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 "stdafx.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;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
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:
|
||||
// Application/
|
||||
// hostfxr.dll
|
||||
// Application.exe
|
||||
// Application.dll
|
||||
// etc.
|
||||
// We get the full path to hostfxr.dll and Application.dll and run hostfxr_main,
|
||||
// passing in Application.dll.
|
||||
// Assuming we don't need Application.exe as the dll is the actual application.
|
||||
//
|
||||
HRESULT
|
||||
HOSTFXR_UTILITY::GetStandaloneHostfxrLocation(
|
||||
STRU* struHostfxrPath,
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE hFileHandle = INVALID_HANDLE_VALUE;
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
|
||||
// Get the full path to the exe and check if it exists
|
||||
if (FAILED(hr = UTILITY::ConvertPathToFullPath(L"\\hostfxr.dll",
|
||||
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;
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Get the System PATH value.
|
||||
if (!UTILITY::GetSystemPathVariable(L"PATH", &struSystemPathVariable))
|
||||
{
|
||||
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)
|
||||
{
|
||||
dwCopyLength = (DWORD) wcsnlen_s(pszDotnetLocation, 260);
|
||||
|
||||
// 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);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (dwCopyLength > 0 && pszDotnetLocation[dwCopyLength - 1] != L'\\')
|
||||
{
|
||||
hr = strDotnetExeLocation.Append(L"\\");
|
||||
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)
|
||||
{
|
||||
// could not find dotnet.exe, error out
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(L"host\\fxr");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (!UTILITY::DirectoryExists(struHostfxrPath))
|
||||
{
|
||||
// error, not found the folder
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Find all folders under host\\fxr\\ for version numbers.
|
||||
hr = strHostFxrSearchExpression.Copy(struHostfxrPath);
|
||||
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?
|
||||
UTILITY::FindDotNetFolders(strHostFxrSearchExpression.QueryStr(), &vVersionFolders);
|
||||
|
||||
if (vVersionFolders.size() == 0)
|
||||
{
|
||||
// no core framework was found
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = UTILITY::FindHighestDotNetVersion(vVersionFolders, &strHighestDotnetVersion);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
hr = struHostfxrPath->Append(L"\\");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(strHighestDotnetVersion.QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
|
||||
}
|
||||
|
||||
hr = struHostfxrPath->Append(L"\\hostfxr.dll");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class HOSTFXR_UTILITY
|
||||
{
|
||||
public:
|
||||
HOSTFXR_UTILITY();
|
||||
~HOSTFXR_UTILITY();
|
||||
|
||||
static
|
||||
HRESULT
|
||||
FindHostFxrDll(
|
||||
ASPNETCORE_CONFIG *pConfig,
|
||||
STRU* struHostFxrDllLocation,
|
||||
BOOL* fStandAlone
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetStandaloneHostfxrLocation(
|
||||
STRU* struHostfxrPath,
|
||||
ASPNETCORE_CONFIG *pConfig
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
GetPortableHostfxrLocation(
|
||||
STRU* struHostfxrPath
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
REQUEST_HANDLER::REQUEST_HANDLER(
|
||||
_In_ IHttpContext *pW3Context,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication)
|
||||
: m_cRefs(1)
|
||||
{
|
||||
m_pW3Context = pW3Context;
|
||||
m_pApplication = pApplication;
|
||||
m_pModuleId = *pModuleId;
|
||||
}
|
||||
|
||||
|
||||
REQUEST_HANDLER::~REQUEST_HANDLER()
|
||||
{
|
||||
}
|
||||
|
||||
VOID
|
||||
REQUEST_HANDLER::ReferenceRequestHandler(
|
||||
VOID
|
||||
) const
|
||||
{
|
||||
InterlockedIncrement(&m_cRefs);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
REQUEST_HANDLER::DereferenceRequestHandler(
|
||||
VOID
|
||||
) const
|
||||
{
|
||||
DBG_ASSERT(m_cRefs != 0);
|
||||
|
||||
LONG cRefs = 0;
|
||||
if ((cRefs = InterlockedDecrement(&m_cRefs)) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "application.h"
|
||||
|
||||
//
|
||||
// Abstract class
|
||||
//
|
||||
class REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
REQUEST_HANDLER(
|
||||
_In_ IHttpContext *pW3Context,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication
|
||||
);
|
||||
|
||||
virtual
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnExecuteRequestHandler() = 0;
|
||||
|
||||
virtual
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
) = 0;
|
||||
|
||||
virtual
|
||||
VOID
|
||||
TerminateRequest(
|
||||
bool fClientInitiated
|
||||
) = 0;
|
||||
|
||||
virtual
|
||||
~REQUEST_HANDLER(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
ReferenceRequestHandler(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
virtual
|
||||
VOID
|
||||
DereferenceRequestHandler(
|
||||
VOID
|
||||
) const;
|
||||
|
||||
protected:
|
||||
mutable LONG m_cRefs;
|
||||
IHttpContext* m_pW3Context;
|
||||
APPLICATION* m_pApplication;
|
||||
HTTP_MODULE_ID m_pModuleId;
|
||||
};
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include"stdafx.h"
|
||||
|
||||
// static
|
||||
HRESULT
|
||||
PATH::SplitUrl(
|
||||
UTILITY::SplitUrl(
|
||||
PCWSTR pszDestinationUrl,
|
||||
BOOL *pfSecure,
|
||||
STRU *pstrDestination,
|
||||
|
@ -95,7 +95,7 @@ Return Value:
|
|||
|
||||
// static
|
||||
HRESULT
|
||||
PATH::UnEscapeUrl(
|
||||
UTILITY::UnEscapeUrl(
|
||||
PCWSTR pszUrl,
|
||||
DWORD cchUrl,
|
||||
bool fCopyQuery,
|
||||
|
@ -151,7 +151,7 @@ PATH::UnEscapeUrl(
|
|||
|
||||
// static
|
||||
HRESULT
|
||||
PATH::UnEscapeUrl(
|
||||
UTILITY::UnEscapeUrl(
|
||||
PCWSTR pszUrl,
|
||||
DWORD cchUrl,
|
||||
STRU * pstrResult
|
||||
|
@ -231,7 +231,7 @@ PATH::UnEscapeUrl(
|
|||
}
|
||||
|
||||
HRESULT
|
||||
PATH::EscapeAbsPath(
|
||||
UTILITY::EscapeAbsPath(
|
||||
IHttpRequest * pRequest,
|
||||
STRU * strEscapedUrl
|
||||
)
|
||||
|
@ -269,7 +269,7 @@ Finished:
|
|||
|
||||
// static
|
||||
bool
|
||||
PATH::IsValidAttributeNameChar(
|
||||
UTILITY::IsValidAttributeNameChar(
|
||||
WCHAR ch
|
||||
)
|
||||
{
|
||||
|
@ -282,7 +282,7 @@ PATH::IsValidAttributeNameChar(
|
|||
|
||||
// static
|
||||
bool
|
||||
PATH::FindInMultiString(
|
||||
UTILITY::FindInMultiString(
|
||||
PCWSTR pszMultiString,
|
||||
PCWSTR pszStringToFind
|
||||
)
|
||||
|
@ -301,7 +301,7 @@ PATH::FindInMultiString(
|
|||
|
||||
// static
|
||||
bool
|
||||
PATH::IsValidQueryStringName(
|
||||
UTILITY::IsValidQueryStringName(
|
||||
PCWSTR pszName
|
||||
)
|
||||
{
|
||||
|
@ -322,7 +322,7 @@ PATH::IsValidQueryStringName(
|
|||
|
||||
// static
|
||||
bool
|
||||
PATH::IsValidHeaderName(
|
||||
UTILITY::IsValidHeaderName(
|
||||
PCWSTR pszName
|
||||
)
|
||||
{
|
||||
|
@ -342,7 +342,7 @@ PATH::IsValidHeaderName(
|
|||
}
|
||||
|
||||
HRESULT
|
||||
PATH::IsPathUnc(
|
||||
UTILITY::IsPathUnc(
|
||||
__in LPCWSTR pszPath,
|
||||
__out BOOL * pfIsUnc
|
||||
)
|
||||
|
@ -373,7 +373,7 @@ Finished:
|
|||
}
|
||||
|
||||
HRESULT
|
||||
PATH::ConvertPathToFullPath(
|
||||
UTILITY::ConvertPathToFullPath(
|
||||
_In_ LPCWSTR pszPath,
|
||||
_In_ LPCWSTR pszRootPath,
|
||||
_Out_ STRU* pStruFullPath
|
||||
|
@ -384,7 +384,7 @@ PATH::ConvertPathToFullPath(
|
|||
LPWSTR pszFullPath = NULL;
|
||||
|
||||
// if relative path, prefix with root path and then convert to absolute path.
|
||||
if( pszPath[0] == L'.' )
|
||||
if ( pszPath[0] == L'.' )
|
||||
{
|
||||
hr = strFileFullPath.Copy(pszRootPath);
|
||||
if(FAILED(hr))
|
||||
|
@ -403,13 +403,13 @@ PATH::ConvertPathToFullPath(
|
|||
}
|
||||
|
||||
hr = strFileFullPath.Append( pszPath );
|
||||
if(FAILED(hr))
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
pszFullPath = new WCHAR[ strFileFullPath.QueryCCH() + 1];
|
||||
if( pszFullPath == NULL )
|
||||
if ( pszFullPath == NULL )
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
|
@ -425,18 +425,185 @@ PATH::ConvertPathToFullPath(
|
|||
|
||||
// convert to canonical path
|
||||
hr = MakePathCanonicalizationProof( pszFullPath, pStruFullPath );
|
||||
if(FAILED(hr))
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if( pszFullPath != NULL )
|
||||
if ( pszFullPath != NULL )
|
||||
{
|
||||
delete[] pszFullPath;
|
||||
pszFullPath = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UTILITY::EnsureDirectoryPathExist(
|
||||
_In_ LPCWSTR pszPath
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
STRU struPath;
|
||||
DWORD dwPosition = 0;
|
||||
BOOL fDone = FALSE;
|
||||
BOOL fUnc = FALSE;
|
||||
|
||||
struPath.Copy(pszPath);
|
||||
hr = IsPathUnc(pszPath, &fUnc);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
if (fUnc)
|
||||
{
|
||||
// "\\?\UNC\"
|
||||
dwPosition = 8;
|
||||
}
|
||||
else if (struPath.IndexOf(L'?', 0) != -1)
|
||||
{
|
||||
// sceanrio "\\?\"
|
||||
dwPosition = 4;
|
||||
}
|
||||
while (!fDone)
|
||||
{
|
||||
dwPosition = struPath.IndexOf(L'\\', dwPosition + 1);
|
||||
if (dwPosition == -1)
|
||||
{
|
||||
// not found '/'
|
||||
fDone = TRUE;
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwPosition ==0)
|
||||
{
|
||||
hr = ERROR_INTERNAL_ERROR;
|
||||
goto Finished;
|
||||
}
|
||||
else if (struPath.QueryStr()[dwPosition-1] == L':')
|
||||
{
|
||||
// skip volume case
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
struPath.QueryStr()[dwPosition] = L'\0';
|
||||
}
|
||||
|
||||
if (!CreateDirectory(struPath.QueryStr(), NULL) &&
|
||||
ERROR_ALREADY_EXISTS != GetLastError())
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
fDone = TRUE;
|
||||
goto Finished;
|
||||
}
|
||||
struPath.QueryStr()[dwPosition] = L'\\';
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UTILITY::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;
|
||||
}
|
||||
|
||||
BOOL
|
||||
UTILITY::DirectoryExists(
|
||||
_In_ STRU *pstrPath
|
||||
)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
|
||||
if (pstrPath->IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
_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);
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
class PATH
|
||||
class UTILITY
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -79,17 +79,41 @@ public:
|
|||
_Out_ STRU* pStrFullPath
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
PATH() {}
|
||||
~PATH() {}
|
||||
static
|
||||
HRESULT
|
||||
EnsureDirectoryPathExist(
|
||||
_In_ LPCWSTR pszPath
|
||||
);
|
||||
|
||||
static
|
||||
CHAR
|
||||
ToHexDigit(
|
||||
UINT nDigit
|
||||
)
|
||||
{
|
||||
return static_cast<CHAR>(nDigit > 9 ? nDigit - 10 + 'A' : nDigit + '0');
|
||||
}
|
||||
BOOL
|
||||
DirectoryExists(
|
||||
_In_ STRU *pstrPath
|
||||
);
|
||||
|
||||
static
|
||||
BOOL
|
||||
GetSystemPathVariable(
|
||||
_In_ PCWSTR pszEnvironmentVariable,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
FindDotNetFolders(
|
||||
_In_ PCWSTR pszPath,
|
||||
_Out_ std::vector<std::wstring> *pvFolders
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
FindHighestDotNetVersion(
|
||||
_In_ std::vector<std::wstring> vFolders,
|
||||
_Out_ STRU *pstrResult
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
UTILITY() {}
|
||||
~UTILITY() {}
|
||||
};
|
|
@ -23,7 +23,7 @@
|
|||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>IISLib</RootNamespace>
|
||||
<ProjectName>IISLib</ProjectName>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
@ -78,6 +78,8 @@
|
|||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -94,6 +96,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -111,6 +114,7 @@
|
|||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -130,6 +134,7 @@
|
|||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ShowIncludes>false</ShowIncludes>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include <windows.h>
|
||||
#include <ahadmin.h>
|
||||
#pragma warning( disable:4127 )
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <atlcomcli.h>
|
||||
#include <strsafe.h>
|
||||
#include <intsafe.h>
|
||||
|
@ -16,3 +19,4 @@
|
|||
#include "ahutil.h"
|
||||
#include "acache.h"
|
||||
//#include "base64.hxx"
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1,287 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\Build\Build.Settings" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{D57EA297-6DC2-4BC0-8C91-334863327863}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>RequestHandler</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>RequestHandler</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>aspnetcorerh</TargetName>
|
||||
<OutDir>$(SolutionDir)artifacts\build\AspNetCore\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>aspnetcorerh</TargetName>
|
||||
<OutDir>$(SolutionDir)artifacts\build\AspNetCore\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>aspnetcorerh</TargetName>
|
||||
<OutDir>$(SolutionDir)artifacts\build\AspNetCore\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>aspnetcorerh</TargetName>
|
||||
<OutDir>$(SolutionDir)artifacts\build\AspNetCore\bin\$(Configuration)\$(Platform)</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;REQUESTHANDLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..\IISLib;..\CommonLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ahadmin.lib;rpcrt4.lib;winhttp.lib;pdh.lib;ws2_32.lib;wbemuuid.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;REQUESTHANDLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..\IISLib;..\CommonLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ahadmin.lib;rpcrt4.lib;winhttp.lib;pdh.lib;ws2_32.lib;wbemuuid.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;REQUESTHANDLER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..\IISLib;..\CommonLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;winhttp.lib;odbc32.lib;ws2_32.lib;odbccp32.lib;wbemuuid.lib;iphlpapi.lib;pdh.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;REQUESTHANDLER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>precomp.hxx</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..\IISLib;..\CommonLib;.\Inc</AdditionalIncludeDirectories>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PreprocessKeepComments>false</PreprocessKeepComments>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
<StructMemberAlignment>8Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;ahadmin.lib;rpcrt4.lib;winhttp.lib;pdh.lib;ws2_32.lib;wbemuuid.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="aspnetcore_event.h" />
|
||||
<ClInclude Include="aspnetcore_msg.h" />
|
||||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="sttimer.h" />
|
||||
<ClInclude Include="outofprocess\forwarderconnection.h" />
|
||||
<ClInclude Include="outofprocess\processmanager.h" />
|
||||
<ClInclude Include="outofprocess\protocolconfig.h" />
|
||||
<ClInclude Include="outofprocess\responseheaderhash.h" />
|
||||
<ClInclude Include="outofprocess\serverprocess.h" />
|
||||
<ClInclude Include="outofprocess\websockethandler.h" />
|
||||
<ClInclude Include="outofprocess\winhttphelper.h" />
|
||||
<ClInclude Include="precomp.hxx" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include=".\inprocess\inprocessapplication.h" />
|
||||
<ClInclude Include=".\inprocess\inprocesshandler.h" />
|
||||
<ClInclude Include=".\outofprocess\forwardinghandler.h" />
|
||||
<ClInclude Include=".\outofprocess\outprocessapplication.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cxx" />
|
||||
<ClCompile Include=".\inprocess\inprocessapplication.cpp" />
|
||||
<ClCompile Include=".\inprocess\inprocesshandler.cpp" />
|
||||
<ClCompile Include=".\outofprocess\forwardinghandler.cpp" />
|
||||
<ClCompile Include=".\outofprocess\outprocessapplication.cpp" />
|
||||
<ClCompile Include="managedexports.cxx" />
|
||||
<ClCompile Include="outofprocess\forwarderconnection.cxx" />
|
||||
<ClCompile Include="outofprocess\processmanager.cxx" />
|
||||
<ClCompile Include="outofprocess\protocolconfig.cxx" />
|
||||
<ClCompile Include="outofprocess\responseheaderhash.cxx" />
|
||||
<ClCompile Include="outofprocess\serverprocess.cxx" />
|
||||
<ClCompile Include="outofprocess\websockethandler.cxx" />
|
||||
<ClCompile Include="outofprocess\winhttphelper.cxx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="aspnetcore_msg.mc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">mc %(FullPath)</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compiling Event Messages ...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).rc;%(Filename).h;MSG0409.bin</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommonLib\CommonLib.vcxproj">
|
||||
<Project>{55494e58-e061-4c4c-a0a8-837008e72f85}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
||||
<Project>{4787a64f-9a3e-4867-a55a-70cb4b2b2ffe}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="RequestHandler.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Source.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,109 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cxx" />
|
||||
<ClCompile Include=".\inprocess\inprocessapplication.cpp">
|
||||
<Filter>InProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include=".\inprocess\inprocesshandler.cpp">
|
||||
<Filter>InProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="managedexports.cxx">
|
||||
<Filter>InProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include=".\outofprocess\forwardinghandler.cpp">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include=".\outofprocess\outprocessapplication.cpp">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\processmanager.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\protocolconfig.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\serverprocess.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\forwarderconnection.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\responseheaderhash.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\websockethandler.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outofprocess\winhttphelper.cxx">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="precomp.hxx" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include=".\inprocess\inprocessapplication.h">
|
||||
<Filter>InProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include=".\inprocess\inprocesshandler.h">
|
||||
<Filter>InProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include=".\outofprocess\forwardinghandler.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\forwarderconnection.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\responseheaderhash.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include=".\outofprocess\outprocessapplication.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\processmanager.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\protocolconfig.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\serverprocess.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\responseheaderhash.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\websockethandler.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outofprocess\winhttphelper.h">
|
||||
<Filter>OutOfProcess</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="disconnectcontext.h" />
|
||||
<ClInclude Include="aspnetcore_event.h" />
|
||||
<ClInclude Include="sttimer.h" />
|
||||
<ClInclude Include="aspnetcore_msg.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="RequestHandler.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Source.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="RequestHandler.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Source.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="InProcess">
|
||||
<UniqueIdentifier>{e567abb5-bac5-4f05-a320-5e25dcfc0000}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="OutOfProcess">
|
||||
<UniqueIdentifier>{5568209f-269e-4d0a-bbb7-ba14f874ccb7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="aspnetcore_msg.mc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Двоичный файл не отображается.
|
@ -0,0 +1,6 @@
|
|||
LIBRARY aspnetcorerh
|
||||
|
||||
EXPORTS
|
||||
CreateApplication
|
||||
CreateRequestHandler
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) .NET Foundation. All rights reserved.
|
||||
Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
Module Name:
|
||||
|
||||
aspnetcore_msg.mc
|
||||
|
||||
Abstract:
|
||||
|
||||
Asp.Net Core Module localizable messages.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _ASPNETCORE_MSG_H_
|
||||
#define _ASPNETCORE_MSG_H_
|
||||
|
||||
//
|
||||
// Values are 32 bit values laid out as follows:
|
||||
//
|
||||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
// +---+-+-+-----------------------+-------------------------------+
|
||||
// |Sev|C|R| Facility | Code |
|
||||
// +---+-+-+-----------------------+-------------------------------+
|
||||
//
|
||||
// where
|
||||
//
|
||||
// Sev - is the severity code
|
||||
//
|
||||
// 00 - Success
|
||||
// 01 - Informational
|
||||
// 10 - Warning
|
||||
// 11 - Error
|
||||
//
|
||||
// C - is the Customer code flag
|
||||
//
|
||||
// R - is a reserved bit
|
||||
//
|
||||
// Facility - is the facility code
|
||||
//
|
||||
// Code - is the facility's status code
|
||||
//
|
||||
//
|
||||
// Define the facility codes
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Define the severity codes
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_PROCESS_START_ERROR
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_ERROR ((DWORD)0x000003E8L)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_PROCESS_START_SUCCESS
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS ((DWORD)0x000003E9L)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_PROCESS_CRASH
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_PROCESS_CRASH ((DWORD)0x000003EAL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED ((DWORD)0x000003EBL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_CONFIG_ERROR
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_CONFIG_ERROR ((DWORD)0x000003ECL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE ((DWORD)0x000003EDL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST ((DWORD)0x000003EEL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_LOAD_CLR_FALIURE
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE ((DWORD)0x000003EFL)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP ((DWORD)0x000003F0L)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR ((DWORD)0x000003F1L)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_ADD_APPLICATION_ERROR
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR ((DWORD)0x000003F2L)
|
||||
|
||||
//
|
||||
// MessageId: ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT
|
||||
//
|
||||
// MessageText:
|
||||
//
|
||||
// %1
|
||||
//
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT ((DWORD)0x000003F3L)
|
||||
|
||||
|
||||
#endif // _ASPNETCORE_MODULE_MSG_H_
|
|
@ -0,0 +1,2 @@
|
|||
LANGUAGE 0x9,0x1
|
||||
1 11 "MSG00001.bin"
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
class ASYNC_DISCONNECT_CONTEXT : public IHttpConnectionStoredContext
|
||||
{
|
||||
public:
|
||||
ASYNC_DISCONNECT_CONTEXT()
|
||||
{
|
||||
m_pHandler = NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
CleanupStoredContext()
|
||||
{
|
||||
DBG_ASSERT(m_pHandler == NULL);
|
||||
delete this;
|
||||
}
|
||||
|
||||
VOID
|
||||
NotifyDisconnect()
|
||||
{
|
||||
REQUEST_HANDLER *pInitialValue = (REQUEST_HANDLER*)
|
||||
InterlockedExchangePointer((PVOID*)&m_pHandler, NULL);
|
||||
|
||||
if (pInitialValue != NULL)
|
||||
{
|
||||
pInitialValue->TerminateRequest(TRUE);
|
||||
pInitialValue->DereferenceRequestHandler();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
SetHandler(
|
||||
REQUEST_HANDLER *pHandler
|
||||
)
|
||||
{
|
||||
//
|
||||
// Take a reference on the forwarding handler.
|
||||
// This reference will be released on either of two conditions:
|
||||
//
|
||||
// 1. When the request processing ends, in which case a ResetHandler()
|
||||
// is called.
|
||||
//
|
||||
// 2. When a disconnect notification arrives.
|
||||
//
|
||||
// We need to make sure that only one of them ends up dereferencing
|
||||
// the object.
|
||||
//
|
||||
|
||||
DBG_ASSERT(pHandler != NULL);
|
||||
DBG_ASSERT(m_pHandler == NULL);
|
||||
|
||||
pHandler->ReferenceRequestHandler();
|
||||
InterlockedExchangePointer((PVOID*)&m_pHandler, pHandler);
|
||||
}
|
||||
|
||||
VOID
|
||||
ResetHandler(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
REQUEST_HANDLER *pInitialValue = (REQUEST_HANDLER*)
|
||||
InterlockedExchangePointer((PVOID*)&m_pHandler, NULL);
|
||||
|
||||
if (pInitialValue != NULL)
|
||||
{
|
||||
pInitialValue->DereferenceRequestHandler();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
~ASYNC_DISCONNECT_CONTEXT()
|
||||
{}
|
||||
|
||||
REQUEST_HANDLER * m_pHandler;
|
||||
};
|
|
@ -0,0 +1,340 @@
|
|||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "precomp.hxx"
|
||||
#include <IPHlpApi.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
BOOL g_fNsiApiNotSupported = FALSE;
|
||||
BOOL g_fWebSocketSupported = FALSE;
|
||||
BOOL g_fEnableReferenceCountTracing = FALSE;
|
||||
BOOL g_fOutOfProcessInitialize = FALSE;
|
||||
BOOL g_fOutOfProcessInitializeError = FALSE;
|
||||
BOOL g_fWinHttpNonBlockingCallbackAvailable = FALSE;
|
||||
DWORD g_OptionalWinHttpFlags = 0;
|
||||
DWORD g_dwAspNetCoreDebugFlags = 0;
|
||||
DWORD g_dwDebugFlags = 0;
|
||||
DWORD g_dwTlsIndex = TLS_OUT_OF_INDEXES;
|
||||
SRWLOCK g_srwLockRH;
|
||||
HINTERNET g_hWinhttpSession = NULL;
|
||||
IHttpServer * g_pHttpServer = NULL;
|
||||
HINSTANCE g_hWinHttpModule;
|
||||
|
||||
|
||||
VOID
|
||||
InitializeGlobalConfiguration(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HKEY hKey;
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\Microsoft\\IIS Extensions\\IIS AspNetCore Module\\Parameters",
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey) == NO_ERROR)
|
||||
{
|
||||
DWORD dwType;
|
||||
DWORD dwData;
|
||||
DWORD cbData;
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"OptionalWinHttpFlags",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD))
|
||||
{
|
||||
g_OptionalWinHttpFlags = dwData;
|
||||
}
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"EnableReferenceCountTracing",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD) && (dwData == 1 || dwData == 0))
|
||||
{
|
||||
g_fEnableReferenceCountTracing = !!dwData;
|
||||
}
|
||||
|
||||
cbData = sizeof(dwData);
|
||||
if ((RegQueryValueEx(hKey,
|
||||
L"DebugFlags",
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&dwData,
|
||||
&cbData) == NO_ERROR) &&
|
||||
(dwType == REG_DWORD))
|
||||
{
|
||||
g_dwAspNetCoreDebugFlags = dwData;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
DWORD dwResult = GetExtendedTcpTable(NULL,
|
||||
&dwSize,
|
||||
FALSE,
|
||||
AF_INET,
|
||||
TCP_TABLE_OWNER_PID_LISTENER,
|
||||
0);
|
||||
if (dwResult != NO_ERROR && dwResult != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
g_fNsiApiNotSupported = TRUE;
|
||||
}
|
||||
|
||||
// WebSocket is supported on Win8 and above only
|
||||
// todo: test on win7
|
||||
g_fWebSocketSupported = IsWindows8OrGreater();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Global initialization routine for OutOfProcess
|
||||
//
|
||||
HRESULT
|
||||
EnsureOutOfProcessInitializtion( IHttpServer* pServer)
|
||||
{
|
||||
|
||||
DBG_ASSERT(pServer);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
|
||||
g_pHttpServer = pServer;
|
||||
|
||||
if (g_fOutOfProcessInitializeError)
|
||||
{
|
||||
hr = E_NOT_VALID_STATE;
|
||||
goto Finished;
|
||||
}
|
||||
if (!g_fOutOfProcessInitialize)
|
||||
{
|
||||
AcquireSRWLockExclusive(&g_srwLockRH);
|
||||
fLocked = TRUE;
|
||||
if (g_fOutOfProcessInitializeError)
|
||||
{
|
||||
hr = E_NOT_VALID_STATE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (g_fOutOfProcessInitialize)
|
||||
{
|
||||
// Done by another thread
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Initialze some global variables here
|
||||
InitializeGlobalConfiguration();
|
||||
|
||||
g_hWinHttpModule = GetModuleHandle(TEXT("winhttp.dll"));
|
||||
|
||||
hr = WINHTTP_HELPER::StaticInitialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND))
|
||||
{
|
||||
g_fWebSocketSupported = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
g_hWinhttpSession = WinHttpOpen(L"",
|
||||
WINHTTP_ACCESS_TYPE_NO_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
WINHTTP_FLAG_ASYNC);
|
||||
if (g_hWinhttpSession == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
//
|
||||
// Don't set non-blocking callbacks WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS,
|
||||
// as we will call WinHttpQueryDataAvailable to get response on the same thread
|
||||
// that we received callback from Winhttp on completing sending/forwarding the request
|
||||
//
|
||||
|
||||
//
|
||||
// Setup the callback function
|
||||
//
|
||||
if (WinHttpSetStatusCallback(g_hWinhttpSession,
|
||||
FORWARDING_HANDLER::OnWinHttpCompletion,
|
||||
(WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS |
|
||||
WINHTTP_CALLBACK_STATUS_SENDING_REQUEST),
|
||||
NULL) == WINHTTP_INVALID_STATUS_CALLBACK)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure we see the redirects (rather than winhttp doing it
|
||||
// automatically)
|
||||
//
|
||||
DWORD dwRedirectOption = WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
|
||||
if (!WinHttpSetOption(g_hWinhttpSession,
|
||||
WINHTTP_OPTION_REDIRECT_POLICY,
|
||||
&dwRedirectOption,
|
||||
sizeof(dwRedirectOption)))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
g_dwTlsIndex = TlsAlloc();
|
||||
if (g_dwTlsIndex == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
||||
hr = FORWARDING_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = WEBSOCKET_HANDLER::StaticInitialize(g_fEnableReferenceCountTracing);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
if (FAILED(hr))
|
||||
{
|
||||
g_fOutOfProcessInitializeError = TRUE;
|
||||
}
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&g_srwLockRH);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
InitializeSRWLock(&g_srwLockRH);
|
||||
// Initialze some global variables here
|
||||
InitializeGlobalConfiguration();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
__stdcall
|
||||
CreateApplication(
|
||||
_In_ IHttpServer *pServer,
|
||||
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||
_Out_ APPLICATION **ppApplication
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
APPLICATION *pApplication = NULL;
|
||||
|
||||
//REQUEST_HANDLER::StaticInitialize(pServer);
|
||||
|
||||
if (pConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
||||
{
|
||||
pApplication = new IN_PROCESS_APPLICATION(pServer, pConfig);
|
||||
if (pApplication == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else if (pConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_OUT_PROCESS)
|
||||
{
|
||||
hr = EnsureOutOfProcessInitializtion(pServer);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
pApplication = new OUT_OF_PROCESS_APPLICATION(pServer, pConfig);
|
||||
if (pApplication == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = ((OUT_OF_PROCESS_APPLICATION*)pApplication)->Initialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
delete pApplication;
|
||||
pApplication = NULL;
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
*ppApplication = pApplication;
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
__stdcall
|
||||
CreateRequestHandler(
|
||||
_In_ IHttpContext *pHttpContext,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication,
|
||||
_Out_ REQUEST_HANDLER **pRequestHandler
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
REQUEST_HANDLER* pHandler = NULL;
|
||||
ASPNETCORE_CONFIG* pConfig = pApplication->QueryConfig();
|
||||
DBG_ASSERT(pConfig);
|
||||
|
||||
if (pConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
||||
{
|
||||
pHandler = new IN_PROCESS_HANDLER(pHttpContext, pModuleId, pApplication);
|
||||
}
|
||||
else if (pConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_OUT_PROCESS)
|
||||
{
|
||||
pHandler = new FORWARDING_HANDLER(pHttpContext, pModuleId, pApplication);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (pHandler == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pRequestHandler = pHandler;
|
||||
}
|
||||
return hr;
|
||||
}
|
|
@ -0,0 +1,889 @@
|
|||
#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(
|
||||
IHttpServer* pHttpServer,
|
||||
ASPNETCORE_CONFIG* pConfig) :
|
||||
APPLICATION(pHttpServer, pConfig),
|
||||
m_ProcessExitCode(0),
|
||||
m_fManagedAppLoaded(FALSE),
|
||||
m_fLoadManagedAppError(FALSE),
|
||||
m_fInitialized(FALSE),
|
||||
m_fRecycleProcessCalled(FALSE),
|
||||
m_hLogFileHandle(INVALID_HANDLE_VALUE),
|
||||
m_fDoneStdRedirect(FALSE)
|
||||
{
|
||||
// is it guaranteed that we have already checked app offline at this point?
|
||||
// If so, I don't think there is much to do here.
|
||||
DBG_ASSERT(pHttpServer != NULL);
|
||||
DBG_ASSERT(pConfig != NULL);
|
||||
InitializeSRWLock(&m_srwLock);
|
||||
|
||||
// TODO we can probably initialized as I believe we are the only ones calling recycle.
|
||||
m_fInitialized = TRUE;
|
||||
m_status = APPLICATION_STATUS::RUNNING;
|
||||
}
|
||||
|
||||
IN_PROCESS_APPLICATION::~IN_PROCESS_APPLICATION()
|
||||
{
|
||||
Recycle();
|
||||
}
|
||||
|
||||
__override
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ShutDown()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
// This is the same function as before, TODO configrm if we need to change anything for configuration.
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::Recycle(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (m_fInitialized)
|
||||
{
|
||||
DWORD dwThreadStatus = 0;
|
||||
DWORD dwTimeout = m_pConfig->QueryShutdownTimeLimitInMS();
|
||||
HANDLE handle = NULL;
|
||||
WIN32_FIND_DATA fileData;
|
||||
|
||||
if (m_pStdFile != NULL)
|
||||
{
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
fclose(m_pStdFile);
|
||||
}
|
||||
|
||||
if (m_hLogFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_Timer.CancelTimer();
|
||||
CloseHandle(m_hLogFileHandle);
|
||||
m_hLogFileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// delete empty log file, if logging is not enabled
|
||||
handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
|
||||
if (handle != INVALID_HANDLE_VALUE &&
|
||||
fileData.nFileSizeHigh &&
|
||||
fileData.nFileSizeLow == 0) // skip check of nFileSizeHigh
|
||||
{
|
||||
FindClose(handle);
|
||||
// no need to check whether the deletion succeeds
|
||||
// as nothing can be done
|
||||
DeleteFile(m_struLogFilePath.QueryStr());
|
||||
}
|
||||
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
|
||||
if (!m_pHttpServer->IsCommandLineLaunch() &&
|
||||
!m_fRecycleProcessCalled &&
|
||||
(m_pHttpServer->GetAdminManager() != NULL))
|
||||
{
|
||||
// IIS scenario.
|
||||
// notify IIS first so that new request will be routed to new worker process
|
||||
m_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand");
|
||||
}
|
||||
|
||||
m_fRecycleProcessCalled = TRUE;
|
||||
|
||||
// First call into the managed server and shutdown
|
||||
if (m_ShutdownHandler != NULL)
|
||||
{
|
||||
m_ShutdownHandler(m_ShutdownHandlerContext);
|
||||
m_ShutdownHandler = NULL;
|
||||
}
|
||||
|
||||
if (m_hThread != NULL &&
|
||||
GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 &&
|
||||
dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
// wait for gracefullshut down, i.e., the exit of the background thread or timeout
|
||||
if (WaitForSingleObject(m_hThread, dwTimeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
// if the thread is still running, we need kill it first before exit to avoid AV
|
||||
if (GetExitCodeThread(m_hThread, &dwThreadStatus) != 0 && dwThreadStatus == STILL_ACTIVE)
|
||||
{
|
||||
TerminateThread(m_hThread, STATUS_CONTROL_C_EXIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
s_Application = NULL;
|
||||
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
if (m_pHttpServer && m_pHttpServer->IsCommandLineLaunch())
|
||||
{
|
||||
// IISExpress scenario
|
||||
// Can only call exit to terminate current process
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_APPLICATION::OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus,
|
||||
IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS dwRequestNotificationStatus = RQ_NOTIFICATION_CONTINUE;
|
||||
|
||||
if (pInProcessHandler->QueryIsManagedRequestComplete())
|
||||
{
|
||||
// means PostCompletion has been called and this is the associated callback.
|
||||
dwRequestNotificationStatus = pInProcessHandler->QueryAsyncCompletionStatus();
|
||||
// TODO cleanup whatever disconnect listener there is
|
||||
return dwRequestNotificationStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Call the managed handler for async completion.
|
||||
return m_AsyncCompletionHandler(pInProcessHandler->QueryManagedHttpContext(), hrCompletionStatus, cbCompletion);
|
||||
}
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_APPLICATION::OnExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
if (m_RequestHandler != NULL)
|
||||
{
|
||||
return m_RequestHandler(pInProcessHandler, m_RequestHandlerContext);
|
||||
}
|
||||
|
||||
//
|
||||
// return error as the application did not register callback
|
||||
//
|
||||
if (ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::IsEnabled(pHttpContext->GetTraceContext()))
|
||||
{
|
||||
ANCMEvents::ANCM_EXECUTE_REQUEST_FAIL::RaiseEvent(pHttpContext->GetTraceContext(),
|
||||
NULL,
|
||||
(ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||
}
|
||||
|
||||
pHttpContext->GetResponse()->SetStatus(500,
|
||||
"Internal Server Error",
|
||||
0,
|
||||
(ULONG)E_APPLICATION_ACTIVATION_EXEC_FAILURE);
|
||||
|
||||
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,
|
||||
_In_ PFN_SHUTDOWN_HANDLER shutdown_handler,
|
||||
_In_ PFN_MANAGED_CONTEXT_HANDLER async_completion_handler,
|
||||
_In_ VOID* pvRequstHandlerContext,
|
||||
_In_ VOID* pvShutdownHandlerContext
|
||||
)
|
||||
{
|
||||
m_RequestHandler = request_handler;
|
||||
m_RequestHandlerContext = pvRequstHandlerContext;
|
||||
m_ShutdownHandler = shutdown_handler;
|
||||
m_ShutdownHandlerContext = pvShutdownHandlerContext;
|
||||
m_AsyncCompletionHandler = async_completion_handler;
|
||||
|
||||
// Initialization complete
|
||||
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
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fLocked = FALSE;
|
||||
STRU struPath;
|
||||
|
||||
SYSTEMTIME systemTime;
|
||||
SECURITY_ATTRIBUTES saAttr = { 0 };
|
||||
|
||||
if (!m_fDoneStdRedirect)
|
||||
{
|
||||
// Have not set stdout yet, redirect stdout to log file
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fLocked = TRUE;
|
||||
if (!m_fDoneStdRedirect)
|
||||
{
|
||||
hr = UTILITY::ConvertPathToFullPath(
|
||||
m_pConfig->QueryStdoutLogFile()->QueryStr(),
|
||||
m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
&struPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = UTILITY::EnsureDirectoryPathExist(struPath.QueryStr());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
GetSystemTime(&systemTime);
|
||||
hr = m_struLogFilePath.SafeSnwprintf(L"%s_%d%02d%02d%02d%02d%02d_%d.log",
|
||||
struPath.QueryStr(),
|
||||
systemTime.wYear,
|
||||
systemTime.wMonth,
|
||||
systemTime.wDay,
|
||||
systemTime.wHour,
|
||||
systemTime.wMinute,
|
||||
systemTime.wSecond,
|
||||
GetCurrentProcessId());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
m_hLogFileHandle = CreateFileW(m_struLogFilePath.QueryStr(),
|
||||
FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (m_hLogFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
//
|
||||
// best effort
|
||||
// no need to capture the error code as nothing we can do here
|
||||
// in case mamanged layer exits abnormally, may not be able to capture the log content as it is buffered.
|
||||
//
|
||||
if (!GetConsoleWindow())
|
||||
{
|
||||
//
|
||||
// SetStdHandle works as w3wp does not have Console
|
||||
// Current process does not have a console
|
||||
//
|
||||
SetStdHandle(STD_ERROR_HANDLE, m_hLogFileHandle);
|
||||
if (m_pConfig->QueryStdoutLogEnabled())
|
||||
{
|
||||
SetStdHandle(STD_OUTPUT_HANDLE, m_hLogFileHandle);
|
||||
// not work
|
||||
// AllocConsole() does not help
|
||||
// *stdout = *m_pStdFile;
|
||||
// *stderr = *m_pStdFile;
|
||||
// _dup2(_fileno(m_pStdFile), _fileno(stdout));
|
||||
// _dup2(_fileno(m_pStdFile), _fileno(stderr));
|
||||
// this one cannot capture the process start failure
|
||||
// _wfreopen_s(&m_pStdFile, struLogFileName.QueryStr(), L"w", stdout);
|
||||
|
||||
// Periodically flush the log content to file
|
||||
m_Timer.InitializeTimer(STTIMER::TimerCallback, &m_struLogFilePath, 3000, 3000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The process has console, e.g., IIS Express scenario
|
||||
CloseHandle(m_hLogFileHandle);
|
||||
m_hLogFileHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (m_pConfig->QueryStdoutLogEnabled())
|
||||
{
|
||||
if (_wfopen_s(&m_pStdFile, m_struLogFilePath.QueryStr(), L"w") == 0)
|
||||
{
|
||||
// known issue: error info may not be capture when process crashes during buffering
|
||||
// even we disabled FILE buffering
|
||||
setvbuf(m_pStdFile, NULL, _IONBF, 0);
|
||||
_dup2(_fileno(m_pStdFile), _fileno(stdout));
|
||||
_dup2(_fileno(m_pStdFile), _fileno(stderr));
|
||||
}
|
||||
// not work for console scenario
|
||||
// close and AllocConsole does not help
|
||||
//_wfreopen_s(&m_pStdFile, struLogFileName.QueryStr(), L"w", stdout);
|
||||
// SetStdHandle(STD_ERROR_HANDLE, m_hLogFileHandle);
|
||||
// SetStdHandle(STD_OUTPUT_HANDLE, m_hLogFileHandle);
|
||||
//*stdout = *m_pStdFile;
|
||||
//*stderr = *m_pStdFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete the file as log is disabled
|
||||
WIN32_FIND_DATA fileData;
|
||||
HANDLE handle = FindFirstFile(m_struLogFilePath.QueryStr(), &fileData);
|
||||
if (handle != INVALID_HANDLE_VALUE &&
|
||||
fileData.nFileSizeHigh == 0 &&
|
||||
fileData.nFileSizeLow == 0)
|
||||
{
|
||||
FindClose(handle);
|
||||
// no need to check whether the deletion succeeds
|
||||
// as nothing can be done
|
||||
DeleteFile(m_struLogFilePath.QueryStr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
m_fDoneStdRedirect = TRUE;
|
||||
if (fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
if (FAILED(hr) && m_pConfig->QueryStdoutLogEnabled())
|
||||
{
|
||||
//todo log an warning
|
||||
//STRU strEventMsg;
|
||||
//LPCWSTR apsz[1];
|
||||
|
||||
//if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
// ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG,
|
||||
// m_struLogFilePath.QueryStr(),
|
||||
// HRESULT_FROM_GETLASTERROR())))
|
||||
//{
|
||||
// apsz[0] = strEventMsg.QueryStr();
|
||||
// //
|
||||
// // not checking return code because if ReportEvent
|
||||
// // fails, we cannot do anything.
|
||||
// //
|
||||
// if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
// {
|
||||
// ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
// EVENTLOG_WARNING_TYPE,
|
||||
// 0,
|
||||
// ASPNETCORE_EVENT_CONFIG_ERROR,
|
||||
// NULL,
|
||||
// 1,
|
||||
// 0,
|
||||
// apsz,
|
||||
// NULL);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// Will be called by the inprocesshandler
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::LoadManagedApplication
|
||||
(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
DWORD dwTimeout;
|
||||
DWORD dwResult;
|
||||
BOOL fLocked = FALSE;
|
||||
//PCWSTR apsz[1];
|
||||
//STACK_STRU(strEventMsg, 256);
|
||||
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
// Core CLR has already been loaded.
|
||||
// Cannot load more than once even there was a failure
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Set up stdout redirect
|
||||
SetStdOut();
|
||||
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fLocked = TRUE;
|
||||
if (m_fManagedAppLoaded || m_fLoadManagedAppError)
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_pInitalizeEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not set
|
||||
NULL); // name
|
||||
|
||||
if (m_pInitalizeEvent == NULL)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// If the debugger is attached, never timeout
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
dwTimeout = INFINITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwTimeout = m_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)
|
||||
{
|
||||
// kill the backend thread as loading dotnet timedout
|
||||
TerminateThread(m_hThread, 0);
|
||||
hr = HRESULT_FROM_WIN32(dwResult);
|
||||
goto Finished;
|
||||
}
|
||||
else if (dwResult == WAIT_FAILED)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// The thread ended it means that something failed
|
||||
if (dwResult == WAIT_OBJECT_0)
|
||||
{
|
||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
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 ?
|
||||
|
||||
// TODO
|
||||
//if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
// ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG,
|
||||
// m_pConfiguration->QueryApplicationPath()->QueryStr(),
|
||||
// m_pConfiguration->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
// hr)))
|
||||
//{
|
||||
// apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
// //
|
||||
// // not checking return code because if ReportEvent
|
||||
// // fails, we cannot do anything.
|
||||
// //
|
||||
// if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
// {
|
||||
// ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
// EVENTLOG_ERROR_TYPE,
|
||||
// 0,
|
||||
// ASPNETCORE_EVENT_LOAD_CLR_FALIURE,
|
||||
// NULL,
|
||||
// 1,
|
||||
// 0,
|
||||
// apsz,
|
||||
// NULL);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// static
|
||||
VOID
|
||||
IN_PROCESS_APPLICATION::ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
)
|
||||
{
|
||||
|
||||
IN_PROCESS_APPLICATION *pApplication = (IN_PROCESS_APPLICATION*)pContext;
|
||||
DBG_ASSERT(pApplication != NULL);
|
||||
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;
|
||||
|
||||
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());
|
||||
|
||||
if (hModule == NULL)
|
||||
{
|
||||
// .NET Core not installed (we can log a more detailed error message here)
|
||||
hr = ERROR_BAD_ENVIRONMENT;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
// Get the entry point for main
|
||||
pProc = (hostfxr_main_fn)GetProcAddress(hModule, "hostfxr_main");
|
||||
if (pProc == NULL)
|
||||
{
|
||||
hr = ERROR_BAD_ENVIRONMENT; // better hrresult?
|
||||
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
|
||||
// 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;
|
||||
|
||||
RunDotnetApplication(argv, pProc);
|
||||
|
||||
Finished:
|
||||
//
|
||||
// this method is called by the background thread and should never exit unless shutdown
|
||||
//
|
||||
if (!m_fRecycleProcessCalled)
|
||||
{
|
||||
//STRU strEventMsg;
|
||||
//LPCWSTR apsz[1];
|
||||
//if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
||||
// ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG,
|
||||
// m_pConfig->QueryApplicationPath()->QueryStr(),
|
||||
// m_pConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
||||
// m_ProcessExitCode
|
||||
//)))
|
||||
//{
|
||||
// apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
// //
|
||||
// // not checking return code because if ReportEvent
|
||||
// // fails, we cannot do anything.
|
||||
// //
|
||||
// if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
// {
|
||||
// ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
// EVENTLOG_ERROR_TYPE,
|
||||
// 0,
|
||||
// ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT,
|
||||
// NULL,
|
||||
// 1,
|
||||
// 0,
|
||||
// apsz,
|
||||
// NULL);
|
||||
// }
|
||||
// // error. the thread exits after application started
|
||||
// // Question: should we shutdown current worker process or keep the application in failure state?
|
||||
// // for now, we reccylce to keep the same behavior as that of out-of-process
|
||||
//}
|
||||
if (m_fManagedAppLoaded)
|
||||
{
|
||||
Recycle();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
HRESULT
|
||||
IN_PROCESS_APPLICATION::RunDotnetApplication(PCWSTR* argv, hostfxr_main_fn pProc)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
__try
|
||||
{
|
||||
m_ProcessExitCode = pProc(2, argv);
|
||||
}
|
||||
__except (FilterException(GetExceptionCode(), GetExceptionInformation()))
|
||||
{
|
||||
// TODO Log error message here.
|
||||
hr = E_FAIL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// static
|
||||
INT
|
||||
IN_PROCESS_APPLICATION::FilterException(unsigned int, struct _EXCEPTION_POINTERS*)
|
||||
{
|
||||
// We assume that any exception is a failure as the applicaiton didn't start or there was a startup error.
|
||||
// TODO, log error based on exception code.
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
|
@ -4,37 +4,21 @@
|
|||
#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 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);
|
||||
|
||||
#include "application.h"
|
||||
typedef DWORD(*hostfxr_main_fn) (CONST DWORD argc, CONST WCHAR* argv[]);
|
||||
|
||||
class IN_PROCESS_APPLICATION : public APPLICATION
|
||||
{
|
||||
public:
|
||||
IN_PROCESS_APPLICATION();
|
||||
IN_PROCESS_APPLICATION(IHttpServer* pHttpServer, ASPNETCORE_CONFIG *pConfig);
|
||||
|
||||
~IN_PROCESS_APPLICATION();
|
||||
|
||||
__override
|
||||
HRESULT
|
||||
Initialize(_In_ APPLICATION_MANAGER* pApplicationManager,
|
||||
_In_ ASPNETCORE_CONFIG* pConfiguration);
|
||||
|
||||
VOID
|
||||
Recycle(
|
||||
VOID
|
||||
);
|
||||
|
||||
__override
|
||||
VOID OnAppOfflineHandleChange();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
ExecuteRequest(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
);
|
||||
ShutDown();
|
||||
|
||||
VOID
|
||||
SetCallbackHandles(
|
||||
|
@ -45,6 +29,11 @@ public:
|
|||
_In_ VOID* pvShutdownHandlerContext
|
||||
);
|
||||
|
||||
VOID
|
||||
Recycle(
|
||||
VOID
|
||||
);
|
||||
|
||||
// Executes the .NET Core process
|
||||
HRESULT
|
||||
ExecuteApplication(
|
||||
|
@ -53,14 +42,31 @@ public:
|
|||
|
||||
HRESULT
|
||||
LoadManagedApplication(
|
||||
VOID
|
||||
);
|
||||
VOID
|
||||
);
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnAsyncCompletion(
|
||||
IHttpContext* pHttpContext,
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
HRESULT hrCompletionStatus,
|
||||
IN_PROCESS_HANDLER* pInProcessHandler
|
||||
);
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnExecuteRequest
|
||||
(
|
||||
IHttpContext* pHttpContext,
|
||||
IN_PROCESS_HANDLER* pInProcessHandler
|
||||
);
|
||||
|
||||
static
|
||||
INT
|
||||
FilterException(unsigned int code, struct _EXCEPTION_POINTERS *ep);
|
||||
|
||||
HRESULT
|
||||
RunDotnetApplication(
|
||||
PCWSTR* argv,
|
||||
hostfxr_main_fn pProc
|
||||
);
|
||||
|
||||
static
|
||||
|
@ -72,14 +78,13 @@ public:
|
|||
return s_Application;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// Thread executing the .NET Core process
|
||||
HANDLE m_hThread;
|
||||
|
||||
// The request handler callback from managed code
|
||||
PFN_REQUEST_HANDLER m_RequestHandler;
|
||||
VOID* m_RequstHandlerContext;
|
||||
VOID* m_RequestHandlerContext;
|
||||
|
||||
// The shutdown handler callback from managed code
|
||||
PFN_SHUTDOWN_HANDLER m_ShutdownHandler;
|
||||
|
@ -90,6 +95,10 @@ private:
|
|||
// The event that gets triggered when managed initialization is complete
|
||||
HANDLE m_pInitalizeEvent;
|
||||
|
||||
// The std log file handle
|
||||
HANDLE m_hLogFileHandle;
|
||||
STRU m_struLogFilePath;
|
||||
|
||||
// The exit code of the .NET Core process
|
||||
INT m_ProcessExitCode;
|
||||
|
||||
|
@ -97,9 +106,20 @@ private:
|
|||
BOOL m_fLoadManagedAppError;
|
||||
BOOL m_fInitialized;
|
||||
BOOL m_fIsWebSocketsConnection;
|
||||
BOOL m_fDoneStdRedirect;
|
||||
BOOL m_fRecycleProcessCalled;
|
||||
|
||||
FILE* m_pStdFile;
|
||||
STTIMER m_Timer;
|
||||
SRWLOCK m_srwLock;
|
||||
|
||||
static IN_PROCESS_APPLICATION* s_Application;
|
||||
|
||||
VOID
|
||||
SetStdOut(
|
||||
VOID
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
FindDotNetFolders(
|
||||
|
@ -117,7 +137,7 @@ private:
|
|||
static
|
||||
BOOL
|
||||
DirectoryExists(
|
||||
_In_ STRU *pstrPath //todo: this does not need to be stru, can be PCWSTR
|
||||
_In_ STRU *pstrPath //todo: this does not need to be stru, can be PCWSTR
|
||||
);
|
||||
|
||||
static BOOL
|
||||
|
@ -131,5 +151,4 @@ private:
|
|||
ExecuteAspNetCoreProcess(
|
||||
_In_ LPVOID pContext
|
||||
);
|
||||
|
||||
};
|
|
@ -0,0 +1,146 @@
|
|||
#include "..\precomp.hxx"
|
||||
|
||||
IN_PROCESS_HANDLER::IN_PROCESS_HANDLER(
|
||||
_In_ IHttpContext *pW3Context,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication
|
||||
): REQUEST_HANDLER(pW3Context, pModuleId, pApplication)
|
||||
{
|
||||
m_fManagedRequestComplete = FALSE;
|
||||
}
|
||||
|
||||
IN_PROCESS_HANDLER::~IN_PROCESS_HANDLER()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_HANDLER::OnExecuteRequestHandler()
|
||||
{
|
||||
// First get the in process Application
|
||||
HRESULT hr;
|
||||
hr = ((IN_PROCESS_APPLICATION*)m_pApplication)->LoadManagedApplication();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// TODO remove com_error?
|
||||
/*_com_error err(hr);
|
||||
if (ANCMEvents::ANCM_START_APPLICATION_FAIL::IsEnabled(m_pW3Context->GetTraceContext()))
|
||||
{
|
||||
ANCMEvents::ANCM_START_APPLICATION_FAIL::RaiseEvent(
|
||||
m_pW3Context->GetTraceContext(),
|
||||
NULL,
|
||||
err.ErrorMessage());
|
||||
}
|
||||
*/
|
||||
//fInternalError = TRUE;
|
||||
m_pW3Context->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr);
|
||||
return REQUEST_NOTIFICATION_STATUS::RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
|
||||
// FREB log
|
||||
|
||||
if (ANCMEvents::ANCM_START_APPLICATION_SUCCESS::IsEnabled(m_pW3Context->GetTraceContext()))
|
||||
{
|
||||
ANCMEvents::ANCM_START_APPLICATION_SUCCESS::RaiseEvent(
|
||||
m_pW3Context->GetTraceContext(),
|
||||
NULL,
|
||||
L"InProcess Application");
|
||||
}
|
||||
|
||||
//SetHttpSysDisconnectCallback();
|
||||
return ((IN_PROCESS_APPLICATION*)m_pApplication)->OnExecuteRequest(m_pW3Context, this);
|
||||
}
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_HANDLER::OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (FAILED(hrCompletionStatus))
|
||||
{
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For now we are assuming we are in our own self contained box.
|
||||
// TODO refactor Finished and Failure sections to handle in process and out of process failure.
|
||||
// TODO verify that websocket's OnAsyncCompletion is not calling this.
|
||||
IN_PROCESS_APPLICATION* application = (IN_PROCESS_APPLICATION*)m_pApplication;
|
||||
if (application == NULL)
|
||||
{
|
||||
hr = E_FAIL;
|
||||
return RQ_NOTIFICATION_FINISH_REQUEST;
|
||||
}
|
||||
|
||||
return application->OnAsyncCompletion(cbCompletion, hrCompletionStatus, this);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_HANDLER::TerminateRequest(
|
||||
bool fClientInitiated
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(fClientInitiated);
|
||||
//todo
|
||||
}
|
||||
|
||||
PVOID
|
||||
IN_PROCESS_HANDLER::QueryManagedHttpContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_pManagedHttpContext;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IN_PROCESS_HANDLER::QueryIsManagedRequestComplete(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_fManagedRequestComplete;
|
||||
}
|
||||
|
||||
IHttpContext*
|
||||
IN_PROCESS_HANDLER::QueryHttpContext(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_pW3Context;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_HANDLER::IndicateManagedRequestComplete(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
m_fManagedRequestComplete = TRUE;
|
||||
}
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
IN_PROCESS_HANDLER::QueryAsyncCompletionStatus(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_requestNotificationStatus;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_HANDLER::SetAsyncCompletionStatus(
|
||||
REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
)
|
||||
{
|
||||
m_requestNotificationStatus = requestNotificationStatus;
|
||||
}
|
||||
|
||||
VOID
|
||||
IN_PROCESS_HANDLER::SetManangedHttpContext(
|
||||
PVOID pManagedHttpContext
|
||||
)
|
||||
{
|
||||
m_pManagedHttpContext = pManagedHttpContext;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#pragma once
|
||||
|
||||
class IN_PROCESS_HANDLER : public REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
IN_PROCESS_HANDLER(
|
||||
|
||||
_In_ IHttpContext *pW3Context,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication);
|
||||
|
||||
~IN_PROCESS_HANDLER();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnExecuteRequestHandler();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
);
|
||||
|
||||
__override
|
||||
VOID
|
||||
TerminateRequest(
|
||||
bool fClientInitiated
|
||||
|
||||
);
|
||||
|
||||
PVOID
|
||||
QueryManagedHttpContext(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
SetManangedHttpContext(
|
||||
PVOID pManagedHttpContext
|
||||
);
|
||||
|
||||
IHttpContext*
|
||||
QueryHttpContext(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOL
|
||||
QueryIsManagedRequestComplete(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
IndicateManagedRequestComplete(
|
||||
VOID
|
||||
);
|
||||
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
QueryAsyncCompletionStatus(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
SetAsyncCompletionStatus(
|
||||
REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
);
|
||||
|
||||
private:
|
||||
PVOID m_pManagedHttpContext;
|
||||
IHttpContext* m_pHttpContext;
|
||||
BOOL m_fManagedRequestComplete;
|
||||
REQUEST_NOTIFICATION_STATUS m_requestNotificationStatus;
|
||||
};
|
|
@ -28,83 +28,64 @@ register_callbacks(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HTTP_REQUEST*
|
||||
http_get_raw_request(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
return pHttpContext->GetRequest()->GetRawHttpRequest();
|
||||
return pInProcessHandler->QueryHttpContext()->GetRequest()->GetRawHttpRequest();
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HTTP_RESPONSE*
|
||||
http_get_raw_response(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
return pHttpContext->GetResponse()->GetRawHttpResponse();
|
||||
return pInProcessHandler->QueryHttpContext()->GetResponse()->GetRawHttpResponse();
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT VOID http_set_response_status_code(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ USHORT statusCode,
|
||||
_In_ PCSTR pszReason
|
||||
)
|
||||
{
|
||||
pHttpContext->GetResponse()->SetStatus(statusCode, pszReason);
|
||||
pInProcessHandler->QueryHttpContext()->GetResponse()->SetStatus(statusCode, pszReason);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_post_completion(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
DWORD cbBytes
|
||||
)
|
||||
{
|
||||
return pHttpContext->PostCompletion(cbBytes);
|
||||
return pInProcessHandler->QueryHttpContext()->PostCompletion(cbBytes);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_set_completion_status(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ REQUEST_NOTIFICATION_STATUS requestNotificationStatus
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
IN_PROCESS_STORED_CONTEXT* pInProcessStoredContext = NULL;
|
||||
|
||||
hr = IN_PROCESS_STORED_CONTEXT::GetInProcessStoredContext(
|
||||
pHttpContext,
|
||||
&pInProcessStoredContext
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
pInProcessStoredContext->IndicateManagedRequestComplete();
|
||||
pInProcessStoredContext->SetAsyncCompletionStatus(requestNotificationStatus);
|
||||
pInProcessHandler->IndicateManagedRequestComplete();
|
||||
pInProcessHandler->SetAsyncCompletionStatus(requestNotificationStatus);
|
||||
return hr;
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_set_managed_context(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ PVOID pvManagedContext
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
IN_PROCESS_STORED_CONTEXT* pInProcessStoredContext = new IN_PROCESS_STORED_CONTEXT(pHttpContext, pvManagedContext);
|
||||
if (pInProcessStoredContext == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
hr = IN_PROCESS_STORED_CONTEXT::SetInProcessStoredContext(pHttpContext, pInProcessStoredContext);
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_ASSIGNED))
|
||||
{
|
||||
hr = S_OK;
|
||||
}
|
||||
// todo: should we consider changing the signature
|
||||
HRESULT hr = S_OK;
|
||||
pInProcessHandler->SetManangedHttpContext(pvManagedContext);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -112,11 +93,11 @@ http_set_managed_context(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
VOID
|
||||
http_indicate_completion(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ REQUEST_NOTIFICATION_STATUS notificationStatus
|
||||
)
|
||||
{
|
||||
pHttpContext->IndicateCompletion(notificationStatus);
|
||||
pInProcessHandler->QueryHttpContext()->IndicateCompletion(notificationStatus);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
|
@ -153,7 +134,7 @@ http_get_application_properties(
|
|||
{
|
||||
ASPNETCORE_CONFIG* pConfiguration = NULL;
|
||||
IN_PROCESS_APPLICATION* pApplication = IN_PROCESS_APPLICATION::GetInstance();
|
||||
|
||||
|
||||
if (pApplication == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
|
@ -161,7 +142,7 @@ http_get_application_properties(
|
|||
|
||||
pConfiguration = pApplication->QueryConfig();
|
||||
|
||||
pIISCofigurationData->pwzFullApplicationPath = SysAllocString(pConfiguration->QueryApplicationFullPath()->QueryStr());
|
||||
pIISCofigurationData->pwzFullApplicationPath = SysAllocString(pConfiguration->QueryApplicationPhysicalPath()->QueryStr());
|
||||
pIISCofigurationData->pwzVirtualApplicationPath = SysAllocString(pConfiguration->QueryApplicationVirtualPath()->QueryStr());
|
||||
pIISCofigurationData->fWindowsAuthEnabled = pConfiguration->QueryWindowsAuthEnabled();
|
||||
pIISCofigurationData->fBasicAuthEnabled = pConfiguration->QueryBasicAuthEnabled();
|
||||
|
@ -173,7 +154,7 @@ http_get_application_properties(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_read_request_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_Out_ CHAR* pvBuffer,
|
||||
_In_ DWORD dwCbBuffer,
|
||||
_Out_ DWORD* pdwBytesReceived,
|
||||
|
@ -182,7 +163,7 @@ http_read_request_bytes(
|
|||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (pHttpContext == NULL)
|
||||
if (pInProcessHandler == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -190,7 +171,7 @@ http_read_request_bytes(
|
|||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
IHttpRequest *pHttpRequest = (IHttpRequest*)pHttpContext->GetRequest();
|
||||
IHttpRequest *pHttpRequest = (IHttpRequest*)pInProcessHandler->QueryHttpContext()->GetRequest();
|
||||
|
||||
BOOL fAsync = TRUE;
|
||||
|
||||
|
@ -213,13 +194,13 @@ http_read_request_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_write_response_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ HTTP_DATA_CHUNK* pDataChunks,
|
||||
_In_ DWORD dwChunks,
|
||||
_In_ BOOL* pfCompletionExpected
|
||||
)
|
||||
{
|
||||
IHttpResponse *pHttpResponse = (IHttpResponse*)pHttpContext->GetResponse();
|
||||
IHttpResponse *pHttpResponse = (IHttpResponse*)pInProcessHandler->QueryHttpContext()->GetResponse();
|
||||
BOOL fAsync = TRUE;
|
||||
BOOL fMoreData = TRUE;
|
||||
DWORD dwBytesSent = 0;
|
||||
|
@ -238,11 +219,11 @@ http_write_response_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_flush_response_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_Out_ BOOL* pfCompletionExpected
|
||||
)
|
||||
{
|
||||
IHttpResponse *pHttpResponse = (IHttpResponse*)pHttpContext->GetResponse();
|
||||
IHttpResponse *pHttpResponse = (IHttpResponse*)pInProcessHandler->QueryHttpContext()->GetResponse();
|
||||
|
||||
BOOL fAsync = TRUE;
|
||||
BOOL fMoreData = TRUE;
|
||||
|
@ -259,7 +240,7 @@ http_flush_response_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_websockets_read_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ CHAR* pvBuffer,
|
||||
_In_ DWORD cbBuffer,
|
||||
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||
|
@ -268,7 +249,7 @@ http_websockets_read_bytes(
|
|||
_In_ BOOL* pfCompletionPending
|
||||
)
|
||||
{
|
||||
IHttpRequest3 *pHttpRequest = (IHttpRequest3*)pHttpContext->GetRequest();
|
||||
IHttpRequest3 *pHttpRequest = (IHttpRequest3*)pInProcessHandler->QueryHttpContext()->GetRequest();
|
||||
|
||||
BOOL fAsync = TRUE;
|
||||
|
||||
|
@ -293,7 +274,7 @@ http_websockets_read_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_websockets_write_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ HTTP_DATA_CHUNK* pDataChunks,
|
||||
_In_ DWORD dwChunks,
|
||||
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||
|
@ -301,7 +282,7 @@ http_websockets_write_bytes(
|
|||
_In_ BOOL* pfCompletionExpected
|
||||
)
|
||||
{
|
||||
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pHttpContext->GetResponse();
|
||||
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pInProcessHandler->QueryHttpContext()->GetResponse();
|
||||
|
||||
BOOL fAsync = TRUE;
|
||||
BOOL fMoreData = TRUE;
|
||||
|
@ -323,13 +304,13 @@ http_websockets_write_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_websockets_flush_bytes(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ PFN_ASYNC_COMPLETION pfnCompletionCallback,
|
||||
_In_ VOID* pvCompletionContext,
|
||||
_In_ BOOL* pfCompletionExpected
|
||||
)
|
||||
{
|
||||
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pHttpContext->GetResponse();
|
||||
IHttpResponse2 *pHttpResponse = (IHttpResponse2*)pInProcessHandler->QueryHttpContext()->GetResponse();
|
||||
|
||||
BOOL fAsync = TRUE;
|
||||
BOOL fMoreData = TRUE;
|
||||
|
@ -348,16 +329,16 @@ http_websockets_flush_bytes(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_enable_websockets(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
if (!g_fWebSocketSupported)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
//if (!g_fWebSocketSupported)
|
||||
//{
|
||||
// return E_FAIL;
|
||||
//}
|
||||
|
||||
((IHttpContext3*)pHttpContext)->EnableFullDuplex();
|
||||
((IHttpResponse2*)pHttpContext->GetResponse())->DisableBuffering();
|
||||
((IHttpContext3*)pInProcessHandler->QueryHttpContext())->EnableFullDuplex();
|
||||
((IHttpResponse2*)pInProcessHandler->QueryHttpContext()->GetResponse())->DisableBuffering();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -365,51 +346,50 @@ http_enable_websockets(
|
|||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_cancel_io(
|
||||
_In_ IHttpContext* pHttpContext
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler
|
||||
)
|
||||
{
|
||||
return pHttpContext->CancelIo();
|
||||
return pInProcessHandler->QueryHttpContext()->CancelIo();
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_response_set_unknown_header(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ PCSTR pszHeaderName,
|
||||
_In_ PCSTR pszHeaderValue,
|
||||
_In_ USHORT usHeaderValueLength,
|
||||
_In_ BOOL fReplace
|
||||
)
|
||||
{
|
||||
return pHttpContext->GetResponse()->SetHeader( pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace );
|
||||
return pInProcessHandler->QueryHttpContext()->GetResponse()->SetHeader(pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_response_set_known_header(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ HTTP_HEADER_ID dwHeaderId,
|
||||
_In_ PCSTR pszHeaderValue,
|
||||
_In_ USHORT usHeaderValueLength,
|
||||
_In_ BOOL fReplace
|
||||
)
|
||||
{
|
||||
return pHttpContext->GetResponse()->SetHeader( dwHeaderId, pszHeaderValue, usHeaderValueLength, fReplace );
|
||||
return pInProcessHandler->QueryHttpContext()->GetResponse()->SetHeader(dwHeaderId, pszHeaderValue, usHeaderValueLength, fReplace);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_get_authentication_information(
|
||||
_In_ IHttpContext* pHttpContext,
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_Out_ BSTR* pstrAuthType,
|
||||
_Out_ VOID** pvToken
|
||||
)
|
||||
{
|
||||
*pstrAuthType = SysAllocString(pHttpContext->GetUser()->GetAuthenticationType());
|
||||
*pvToken = pHttpContext->GetUser()->GetPrimaryToken();
|
||||
*pstrAuthType = SysAllocString(pInProcessHandler->QueryHttpContext()->GetUser()->GetAuthenticationType());
|
||||
*pvToken = pInProcessHandler->QueryHttpContext()->GetUser()->GetPrimaryToken();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
// End of export
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
FORWARDER_CONNECTION::FORWARDER_CONNECTION(
|
||||
VOID
|
||||
|
@ -23,7 +23,7 @@ FORWARDER_CONNECTION::Initialize(
|
|||
goto Finished;
|
||||
}
|
||||
|
||||
m_hConnection = WinHttpConnect(FORWARDING_HANDLER::sm_hSession,
|
||||
m_hConnection = WinHttpConnect(g_hWinhttpSession,
|
||||
L"127.0.0.1",
|
||||
(USHORT) dwPort,
|
||||
0);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,199 @@
|
|||
#pragma once
|
||||
|
||||
extern DWORD g_OptionalWinHttpFlags;
|
||||
|
||||
|
||||
enum FORWARDING_REQUEST_STATUS
|
||||
{
|
||||
FORWARDER_START,
|
||||
FORWARDER_SENDING_REQUEST,
|
||||
FORWARDER_RECEIVING_RESPONSE,
|
||||
FORWARDER_RECEIVED_WEBSOCKET_RESPONSE,
|
||||
FORWARDER_DONE,
|
||||
FORWARDER_FINISH_REQUEST
|
||||
};
|
||||
|
||||
|
||||
class FORWARDING_HANDLER : public REQUEST_HANDLER
|
||||
{
|
||||
public:
|
||||
FORWARDING_HANDLER(
|
||||
|
||||
_In_ IHttpContext *pW3Context,
|
||||
_In_ HTTP_MODULE_ID *pModuleId,
|
||||
_In_ APPLICATION *pApplication);
|
||||
|
||||
~FORWARDING_HANDLER();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnExecuteRequestHandler();
|
||||
|
||||
__override
|
||||
REQUEST_NOTIFICATION_STATUS
|
||||
OnAsyncCompletion(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus
|
||||
);
|
||||
|
||||
VOID
|
||||
SetStatus(
|
||||
FORWARDING_REQUEST_STATUS status
|
||||
)
|
||||
{
|
||||
m_RequestStatus = status;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
CALLBACK
|
||||
FORWARDING_HANDLER::OnWinHttpCompletion(
|
||||
HINTERNET hRequest,
|
||||
DWORD_PTR dwContext,
|
||||
DWORD dwInternetStatus,
|
||||
LPVOID lpvStatusInformation,
|
||||
DWORD dwStatusInformationLength
|
||||
);
|
||||
|
||||
static
|
||||
HRESULT
|
||||
StaticInitialize(
|
||||
BOOL fEnableReferenceCountTracing
|
||||
);
|
||||
|
||||
static
|
||||
VOID
|
||||
StaticTerminate();
|
||||
|
||||
VOID
|
||||
TerminateRequest(
|
||||
bool fClientInitiated
|
||||
);
|
||||
|
||||
private:
|
||||
HRESULT
|
||||
CreateWinHttpRequest(
|
||||
_In_ const IHttpRequest * pRequest,
|
||||
_In_ const PROTOCOL_CONFIG * pProtocol,
|
||||
_In_ HINTERNET hConnect,
|
||||
_Inout_ STRU * pstrUrl,
|
||||
// _In_ ASPNETCORE_CONFIG* pAspNetCoreConfig,
|
||||
_In_ SERVER_PROCESS* pServerProcess
|
||||
);
|
||||
|
||||
VOID
|
||||
FORWARDING_HANDLER::OnWinHttpCompletionInternal(
|
||||
_In_ HINTERNET hRequest,
|
||||
_In_ DWORD dwInternetStatus,
|
||||
_In_ LPVOID lpvStatusInformation,
|
||||
_In_ DWORD dwStatusInformationLength
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionSendRequestOrWriteComplete(
|
||||
HINTERNET hRequest,
|
||||
DWORD dwInternetStatus,
|
||||
_Out_ bool * pfClientError,
|
||||
_Out_ bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusHeadersAvailable(
|
||||
HINTERNET hRequest,
|
||||
_Out_ bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusDataAvailable(
|
||||
HINTERNET hRequest,
|
||||
DWORD dwBytes,
|
||||
_Out_ bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnWinHttpCompletionStatusReadComplete(
|
||||
_In_ IHttpResponse * pResponse,
|
||||
DWORD dwStatusInformationLength,
|
||||
_Out_ bool * pfAnotherCompletionExpected
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnSendingRequest(
|
||||
DWORD cbCompletion,
|
||||
HRESULT hrCompletionStatus,
|
||||
_Out_ bool * pfClientError
|
||||
);
|
||||
|
||||
HRESULT
|
||||
OnReceivingResponse();
|
||||
|
||||
BYTE *
|
||||
GetNewResponseBuffer(
|
||||
DWORD dwBufferSize
|
||||
);
|
||||
|
||||
VOID
|
||||
FreeResponseBuffers();
|
||||
|
||||
HRESULT
|
||||
SetStatusAndHeaders(
|
||||
PCSTR pszHeaders,
|
||||
DWORD cchHeaders
|
||||
);
|
||||
|
||||
HRESULT
|
||||
DoReverseRewrite(
|
||||
_In_ IHttpResponse *pResponse
|
||||
);
|
||||
|
||||
HRESULT
|
||||
GetHeaders(
|
||||
_In_ const PROTOCOL_CONFIG * pProtocol,
|
||||
_In_ bool fForwardWindowsAuthToken,
|
||||
_In_ SERVER_PROCESS* pServerProcess,
|
||||
_Out_ PCWSTR * ppszHeaders,
|
||||
_Inout_ DWORD * pcchHeaders
|
||||
);
|
||||
|
||||
DWORD m_Signature;
|
||||
//
|
||||
// WinHTTP request handle is protected using a read-write lock.
|
||||
//
|
||||
SRWLOCK m_RequestLock;
|
||||
HINTERNET m_hRequest;
|
||||
FORWARDING_REQUEST_STATUS m_RequestStatus;
|
||||
|
||||
bool m_fWebSocketEnabled;
|
||||
bool m_fResponseHeadersReceivedAndSet;
|
||||
bool m_fResetConnection;
|
||||
bool m_fHandleClosedDueToClient;
|
||||
bool m_fFinishRequest;
|
||||
bool m_fHasError;
|
||||
BOOL m_fDoReverseRewriteHeaders;
|
||||
PCSTR m_pszOriginalHostHeader;
|
||||
PCWSTR m_pszHeaders;
|
||||
DWORD m_cchHeaders;
|
||||
DWORD m_BytesToReceive;
|
||||
DWORD m_BytesToSend;
|
||||
DWORD m_cchLastSend;
|
||||
DWORD m_cEntityBuffers;
|
||||
DWORD m_cBytesBuffered;
|
||||
DWORD m_cMinBufferLimit;
|
||||
ULONGLONG m_cContentLength;
|
||||
WEBSOCKET_HANDLER * m_pWebSocket;
|
||||
ASYNC_DISCONNECT_CONTEXT * m_pDisconnect;
|
||||
|
||||
BYTE * m_pEntityBuffer;
|
||||
static const SIZE_T INLINE_ENTITY_BUFFERS = 8;
|
||||
BUFFER_T<BYTE*, INLINE_ENTITY_BUFFERS> m_buffEntityBuffers;
|
||||
|
||||
static ALLOC_CACHE_HANDLER * sm_pAlloc;
|
||||
static PROTOCOL_CONFIG sm_ProtocolConfig;
|
||||
static RESPONSE_HEADER_HASH * sm_pResponseHeaderHash;
|
||||
//
|
||||
// Reference cout tracing for debugging purposes.
|
||||
//
|
||||
static TRACE_LOG * sm_pTraceLog;
|
||||
|
||||
static STRA sm_pStra502ErrorMsg;
|
||||
};
|
|
@ -0,0 +1,66 @@
|
|||
#include "..\precomp.hxx"
|
||||
|
||||
OUT_OF_PROCESS_APPLICATION::OUT_OF_PROCESS_APPLICATION(
|
||||
IHttpServer* pHttpServer,
|
||||
ASPNETCORE_CONFIG* pConfig) :
|
||||
APPLICATION(pHttpServer, pConfig)
|
||||
{
|
||||
m_status = APPLICATION_STATUS::RUNNING;
|
||||
m_pProcessManager = NULL;
|
||||
//todo
|
||||
}
|
||||
|
||||
OUT_OF_PROCESS_APPLICATION::~OUT_OF_PROCESS_APPLICATION()
|
||||
{
|
||||
if (m_pProcessManager != NULL)
|
||||
{
|
||||
m_pProcessManager->ShutdownAllProcesses();
|
||||
m_pProcessManager->DereferenceProcessManager();
|
||||
m_pProcessManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
OUT_OF_PROCESS_APPLICATION::Initialize(
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (m_pProcessManager == NULL)
|
||||
{
|
||||
m_pProcessManager = new PROCESS_MANAGER;
|
||||
if (m_pProcessManager == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = m_pProcessManager->Initialize();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
OUT_OF_PROCESS_APPLICATION::GetProcess(
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
)
|
||||
{
|
||||
return m_pProcessManager->GetProcess(m_pConfig, ppServerProcess);
|
||||
}
|
||||
|
||||
__override
|
||||
VOID
|
||||
OUT_OF_PROCESS_APPLICATION::ShutDown()
|
||||
{
|
||||
if (m_pProcessManager != NULL)
|
||||
{
|
||||
m_pProcessManager->ShutdownAllProcesses();
|
||||
m_pProcessManager->DereferenceProcessManager();
|
||||
m_pProcessManager = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
class OUT_OF_PROCESS_APPLICATION : public APPLICATION
|
||||
{
|
||||
|
||||
public:
|
||||
OUT_OF_PROCESS_APPLICATION(IHttpServer* pHttpServer, ASPNETCORE_CONFIG *pConfig);
|
||||
|
||||
~OUT_OF_PROCESS_APPLICATION();
|
||||
|
||||
HRESULT
|
||||
Initialize();
|
||||
|
||||
HRESULT
|
||||
GetProcess(
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
);
|
||||
|
||||
__override
|
||||
VOID
|
||||
ShutDown();
|
||||
|
||||
private:
|
||||
PROCESS_MANAGER * m_pProcessManager;
|
||||
};
|
|
@ -0,0 +1,296 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
volatile BOOL PROCESS_MANAGER::sm_fWSAStartupDone = FALSE;
|
||||
|
||||
HRESULT
|
||||
PROCESS_MANAGER::Initialize(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
WSADATA wsaData;
|
||||
int result;
|
||||
BOOL fLocked = FALSE;
|
||||
|
||||
if( !sm_fWSAStartupDone )
|
||||
{
|
||||
AcquireSRWLockExclusive( &m_srwLock );
|
||||
fLocked = TRUE;
|
||||
|
||||
if( !sm_fWSAStartupDone )
|
||||
{
|
||||
if( (result = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0 )
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32( result );
|
||||
goto Finished;
|
||||
}
|
||||
sm_fWSAStartupDone = TRUE;
|
||||
}
|
||||
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
fLocked = FALSE;
|
||||
}
|
||||
|
||||
m_dwRapidFailTickStart = GetTickCount();
|
||||
|
||||
if( m_hNULHandle == NULL )
|
||||
{
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
m_hNULHandle = CreateFileW( L"NUL",
|
||||
FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ,
|
||||
&saAttr,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
if( m_hNULHandle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
Finished:
|
||||
|
||||
if(fLocked)
|
||||
{
|
||||
ReleaseSRWLockExclusive( &m_srwLock );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
PROCESS_MANAGER::~PROCESS_MANAGER()
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
|
||||
//if( m_ppServerProcessList != NULL )
|
||||
//{
|
||||
// for( DWORD i = 0; i < m_dwProcessesPerApplication; ++i )
|
||||
// {
|
||||
// if( m_ppServerProcessList[i] != NULL )
|
||||
// {
|
||||
// m_ppServerProcessList[i]->DereferenceServerProcess();
|
||||
// m_ppServerProcessList[i] = NULL;
|
||||
// }
|
||||
// }
|
||||
|
||||
// delete[] m_ppServerProcessList;
|
||||
// m_ppServerProcessList = NULL;
|
||||
//}
|
||||
|
||||
//if( m_hNULHandle != NULL )
|
||||
//{
|
||||
// CloseHandle( m_hNULHandle );
|
||||
// m_hNULHandle = NULL;
|
||||
//}
|
||||
|
||||
//if( sm_fWSAStartupDone )
|
||||
//{
|
||||
// WSACleanup();
|
||||
// sm_fWSAStartupDone = FALSE;
|
||||
//}
|
||||
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
PROCESS_MANAGER::GetProcess(
|
||||
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fSharedLock = FALSE;
|
||||
BOOL fExclusiveLock = FALSE;
|
||||
//PCWSTR apsz[1];
|
||||
STACK_STRU(strEventMsg, 256);
|
||||
DWORD dwProcessIndex = 0;
|
||||
SERVER_PROCESS *pSelectedServerProcess = NULL;
|
||||
|
||||
if (!m_fServerProcessListReady)
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = TRUE;
|
||||
|
||||
if (!m_fServerProcessListReady)
|
||||
{
|
||||
m_dwProcessesPerApplication = pConfig->QueryProcessesPerApplication();
|
||||
m_ppServerProcessList = new SERVER_PROCESS*[m_dwProcessesPerApplication];
|
||||
if (m_ppServerProcessList == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < m_dwProcessesPerApplication; ++i)
|
||||
{
|
||||
m_ppServerProcessList[i] = NULL;
|
||||
}
|
||||
}
|
||||
m_fServerProcessListReady = TRUE;
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = FALSE;
|
||||
}
|
||||
|
||||
AcquireSRWLockShared(&m_srwLock);
|
||||
fSharedLock = TRUE;
|
||||
|
||||
//
|
||||
// round robin through to the next available process.
|
||||
//
|
||||
dwProcessIndex = (DWORD)InterlockedIncrement64((LONGLONG*)&m_dwRouteToProcessIndex);
|
||||
dwProcessIndex = dwProcessIndex % m_dwProcessesPerApplication;
|
||||
|
||||
if (m_ppServerProcessList[dwProcessIndex] != NULL &&
|
||||
m_ppServerProcessList[dwProcessIndex]->IsReady())
|
||||
{
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
ReleaseSRWLockShared(&m_srwLock);
|
||||
fSharedLock = FALSE;
|
||||
|
||||
// should make the lock per process so that we can start processes simultaneously ?
|
||||
if (m_ppServerProcessList[dwProcessIndex] == NULL ||
|
||||
!m_ppServerProcessList[dwProcessIndex]->IsReady())
|
||||
{
|
||||
AcquireSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = TRUE;
|
||||
|
||||
if (m_ppServerProcessList[dwProcessIndex] != NULL)
|
||||
{
|
||||
if (!m_ppServerProcessList[dwProcessIndex]->IsReady())
|
||||
{
|
||||
//
|
||||
// terminate existing process that is not ready
|
||||
// before creating new one.
|
||||
//
|
||||
|
||||
//todo:
|
||||
//ShutdownProcessNoLock( m_ppServerProcessList[dwProcessIndex] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// server is already up and ready to serve requests.
|
||||
//m_ppServerProcessList[dwProcessIndex]->ReferenceServerProcess();
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (RapidFailsPerMinuteExceeded(pConfig->QueryRapidFailsPerMinute()))
|
||||
{
|
||||
//
|
||||
// rapid fails per minute exceeded, do not create new process.
|
||||
//
|
||||
|
||||
//if( SUCCEEDED( strEventMsg.SafeSnwprintf(
|
||||
// ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG,
|
||||
// pConfig->QueryRapidFailsPerMinute() ) ) )
|
||||
//{
|
||||
// apsz[0] = strEventMsg.QueryStr();
|
||||
|
||||
// //
|
||||
// // not checking return code because if ReportEvent
|
||||
// // fails, we cannot do anything.
|
||||
// //
|
||||
// if (FORWARDING_HANDLER::QueryEventLog() != NULL)
|
||||
// {
|
||||
// ReportEventW(FORWARDING_HANDLER::QueryEventLog(),
|
||||
// EVENTLOG_INFORMATION_TYPE,
|
||||
// 0,
|
||||
// ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED,
|
||||
// NULL,
|
||||
// 1,
|
||||
// 0,
|
||||
// apsz,
|
||||
// NULL);
|
||||
// }
|
||||
//}
|
||||
|
||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_DISABLED);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
if (m_ppServerProcessList[dwProcessIndex] == NULL)
|
||||
{
|
||||
|
||||
pSelectedServerProcess = new SERVER_PROCESS();
|
||||
if (pSelectedServerProcess == NULL)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
|
||||
hr = pSelectedServerProcess->Initialize(
|
||||
this, //ProcessManager
|
||||
pConfig->QueryProcessPath(), //
|
||||
pConfig->QueryArguments(), //
|
||||
pConfig->QueryStartupTimeLimitInMS(),
|
||||
pConfig->QueryShutdownTimeLimitInMS(),
|
||||
pConfig->QueryWindowsAuthEnabled(),
|
||||
pConfig->QueryBasicAuthEnabled(),
|
||||
pConfig->QueryAnonymousAuthEnabled(),
|
||||
pConfig->QueryEnvironmentVariables(),
|
||||
pConfig->QueryStdoutLogEnabled(),
|
||||
pConfig->QueryStdoutLogFile(),
|
||||
pConfig->QueryApplicationPhysicalPath(), // physical path
|
||||
pConfig->QueryApplicationPath(), // app path
|
||||
pConfig->QueryApplicationVirtualPath() // App relative virtual path
|
||||
);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
hr = pSelectedServerProcess->StartProcess();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pSelectedServerProcess->IsReady())
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_CREATE_FAILED);
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
m_ppServerProcessList[dwProcessIndex] = pSelectedServerProcess;
|
||||
pSelectedServerProcess = NULL;
|
||||
|
||||
}
|
||||
*ppServerProcess = m_ppServerProcessList[dwProcessIndex];
|
||||
|
||||
Finished:
|
||||
|
||||
if (fSharedLock)
|
||||
{
|
||||
ReleaseSRWLockShared(&m_srwLock);
|
||||
fSharedLock = FALSE;
|
||||
}
|
||||
|
||||
if (fExclusiveLock)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&m_srwLock);
|
||||
fExclusiveLock = FALSE;
|
||||
}
|
||||
|
||||
if (pSelectedServerProcess != NULL)
|
||||
{
|
||||
delete pSelectedServerProcess;
|
||||
pSelectedServerProcess = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#define ONE_MINUTE_IN_MILLISECONDS 60000
|
||||
class SERVER_PROCESS;
|
||||
|
||||
class PROCESS_MANAGER
|
||||
{
|
||||
|
@ -29,7 +30,6 @@ public:
|
|||
|
||||
HRESULT
|
||||
GetProcess(
|
||||
_In_ IHttpContext *context,
|
||||
_In_ ASPNETCORE_CONFIG *pConfig,
|
||||
_Out_ SERVER_PROCESS **ppServerProcess
|
||||
);
|
||||
|
@ -104,6 +104,8 @@ public:
|
|||
m_fServerProcessListReady(FALSE),
|
||||
m_cRefs( 1 )
|
||||
{
|
||||
m_ppServerProcessList = NULL;
|
||||
m_fServerProcessListReady = FALSE;
|
||||
InitializeSRWLock( &m_srwLock );
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
HRESULT
|
||||
PROTOCOL_CONFIG::Initialize()
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "aspnetcoreconfig.h"
|
||||
|
||||
class PROTOCOL_CONFIG
|
||||
{
|
||||
public:
|
|
@ -1,9 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
|
||||
RESPONSE_HEADER_HASH * g_pResponseHeaderHash = NULL;
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
HEADER_RECORD RESPONSE_HEADER_HASH::sm_rgHeaders[] =
|
||||
{
|
|
@ -106,5 +106,3 @@ private:
|
|||
RESPONSE_HEADER_HASH(const RESPONSE_HEADER_HASH &);
|
||||
void operator=(const RESPONSE_HEADER_HASH &);
|
||||
};
|
||||
|
||||
extern RESPONSE_HEADER_HASH * g_pResponseHeaderHash;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -23,7 +23,6 @@
|
|||
#define ASPNETCORE_IIS_AUTH_NONE L"none"
|
||||
|
||||
class PROCESS_MANAGER;
|
||||
class FORWARDER_CONNECTION;
|
||||
|
||||
class SERVER_PROCESS
|
||||
{
|
||||
|
@ -42,14 +41,14 @@ public:
|
|||
_In_ BOOL fAnonymousAuthEnabled,
|
||||
_In_ ENVIRONMENT_VAR_HASH* pEnvironmentVariables,
|
||||
_In_ BOOL fStdoutLogEnabled,
|
||||
_In_ STRU *pstruStdoutLogFile
|
||||
_In_ STRU *pstruStdoutLogFile,
|
||||
_In_ STRU *pszAppPhysicalPath,
|
||||
_In_ STRU *pszAppPath,
|
||||
_In_ STRU *pszAppVirtualPath
|
||||
);
|
||||
|
||||
|
||||
HRESULT
|
||||
StartProcess(
|
||||
_In_ IHttpContext *context
|
||||
);
|
||||
StartProcess( VOID );
|
||||
|
||||
HRESULT
|
||||
SetWindowsAuthToken(
|
||||
|
@ -70,7 +69,7 @@ public:
|
|||
VOID
|
||||
);
|
||||
|
||||
DWORD
|
||||
DWORD
|
||||
GetPort()
|
||||
{
|
||||
return m_dwPort;
|
||||
|
@ -90,7 +89,6 @@ public:
|
|||
)
|
||||
{
|
||||
_ASSERT(m_cRefs != 0 );
|
||||
|
||||
if (InterlockedDecrement(&m_cRefs) == 0)
|
||||
{
|
||||
delete this;
|
||||
|
@ -100,7 +98,15 @@ public:
|
|||
virtual
|
||||
~SERVER_PROCESS();
|
||||
|
||||
HRESULT
|
||||
static
|
||||
VOID
|
||||
CALLBACK
|
||||
ProcessHandleCallback(
|
||||
_In_ PVOID pContext,
|
||||
_In_ BOOL
|
||||
);
|
||||
|
||||
HRESULT
|
||||
HandleProcessExit(
|
||||
VOID
|
||||
);
|
||||
|
@ -113,38 +119,11 @@ public:
|
|||
return m_pForwarderConnection;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
CALLBACK
|
||||
TimerCallback(
|
||||
_In_ PTP_CALLBACK_INSTANCE Instance,
|
||||
_In_ PVOID Context,
|
||||
_In_ PTP_TIMER Timer
|
||||
);
|
||||
|
||||
LPCWSTR
|
||||
QueryPortStr()
|
||||
{
|
||||
return m_struPort.QueryStr();
|
||||
}
|
||||
|
||||
LPCWSTR
|
||||
QueryFullLogPath()
|
||||
{
|
||||
return m_struFullLogFile.QueryStr();
|
||||
}
|
||||
|
||||
LPCSTR
|
||||
QueryGuid()
|
||||
{
|
||||
return m_straGuid.QueryStr();
|
||||
}
|
||||
|
||||
DWORD
|
||||
QueryProcessGroupId()
|
||||
{
|
||||
return m_dwProcessId;
|
||||
}
|
||||
};
|
||||
|
||||
VOID
|
||||
SendSignal(
|
||||
|
@ -165,8 +144,7 @@ private:
|
|||
|
||||
HRESULT
|
||||
SetupStdHandles(
|
||||
_In_ IHttpContext *context,
|
||||
_In_ LPSTARTUPINFOW pStartupInfo
|
||||
_Inout_ LPSTARTUPINFOW pStartupInfo
|
||||
);
|
||||
|
||||
HRESULT
|
||||
|
@ -184,6 +162,7 @@ private:
|
|||
|
||||
HRESULT
|
||||
GetChildProcessHandles(
|
||||
VOID
|
||||
);
|
||||
|
||||
HRESULT
|
||||
|
@ -193,7 +172,6 @@ private:
|
|||
|
||||
HRESULT
|
||||
SetupAppPath(
|
||||
IHttpContext* pContext,
|
||||
ENVIRONMENT_VAR_HASH* pEnvironmentVarTable
|
||||
);
|
||||
|
||||
|
@ -220,8 +198,7 @@ private:
|
|||
|
||||
HRESULT
|
||||
PostStartCheck(
|
||||
const STRU* const pStruCommandline,
|
||||
STRU* pStruErrorMessage
|
||||
VOID
|
||||
);
|
||||
|
||||
HRESULT
|
||||
|
@ -230,28 +207,6 @@ private:
|
|||
DWORD dwExcludedPort
|
||||
);
|
||||
|
||||
DWORD
|
||||
GetNumberOfDigits(
|
||||
_In_ DWORD dwNumber
|
||||
)
|
||||
{
|
||||
DWORD digits = 0;
|
||||
|
||||
if( dwNumber == 0 )
|
||||
{
|
||||
digits = 1;
|
||||
goto Finished;
|
||||
}
|
||||
|
||||
while( dwNumber > 0)
|
||||
{
|
||||
dwNumber = dwNumber / 10;
|
||||
digits ++;
|
||||
}
|
||||
Finished:
|
||||
return digits;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
SendShutDownSignal(
|
||||
|
@ -286,10 +241,12 @@ private:
|
|||
STRU m_struFullLogFile;
|
||||
STRU m_ProcessPath;
|
||||
STRU m_Arguments;
|
||||
STRU m_struAppPath;
|
||||
STRU m_struAppFullPath;
|
||||
STRU m_struAppVirtualPath; // e.g., '/' for site
|
||||
STRU m_struAppFullPath; // e.g., /LM/W3SVC/4/ROOT/Inproc
|
||||
STRU m_struPhysicalPath; // e.g., c:/test/mysite
|
||||
STRU m_struPort;
|
||||
STRU m_pszRootApplicationPath;
|
||||
STRU m_struCommandLine;
|
||||
|
||||
volatile LONG m_lStopping;
|
||||
volatile BOOL m_fReady;
|
||||
mutable LONG m_cRefs;
|
|
@ -27,7 +27,7 @@ This prevents the need for data buffering at the Asp.Net Core Module level.
|
|||
|
||||
--*/
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
SRWLOCK WEBSOCKET_HANDLER::sm_RequestsListLock;
|
||||
|
||||
|
@ -48,7 +48,6 @@ WEBSOCKET_HANDLER::WEBSOCKET_HANDLER() :
|
|||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::WEBSOCKET_HANDLER");
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&_RequestLock, 1000);
|
||||
|
||||
InsertRequest();
|
||||
}
|
||||
|
||||
|
@ -103,7 +102,6 @@ WEBSOCKET_HANDLER::StaticInitialize(
|
|||
// If tracing is enabled, keep track of all websocket requests
|
||||
// for debugging purposes.
|
||||
//
|
||||
|
||||
InitializeListHead (&sm_RequestsListHead);
|
||||
sm_pTraceLog = CreateRefTraceLog( 10000, 0 );
|
||||
}
|
||||
|
@ -137,9 +135,7 @@ WEBSOCKET_HANDLER::InsertRequest(
|
|||
if (g_fEnableReferenceCountTracing)
|
||||
{
|
||||
AcquireSRWLockExclusive(&sm_RequestsListLock);
|
||||
|
||||
InsertTailList(&sm_RequestsListHead, &_listEntry);
|
||||
|
||||
ReleaseSRWLockExclusive( &sm_RequestsListLock);
|
||||
}
|
||||
}
|
||||
|
@ -153,9 +149,7 @@ WEBSOCKET_HANDLER::RemoveRequest(
|
|||
if (g_fEnableReferenceCountTracing)
|
||||
{
|
||||
AcquireSRWLockExclusive(&sm_RequestsListLock);
|
||||
|
||||
RemoveEntryList(&_listEntry);
|
||||
|
||||
ReleaseSRWLockExclusive( &sm_RequestsListLock);
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +160,6 @@ WEBSOCKET_HANDLER::IncrementOutstandingIo(
|
|||
)
|
||||
{
|
||||
InterlockedIncrement(&_dwOutstandingIo);
|
||||
|
||||
if (sm_pTraceLog)
|
||||
{
|
||||
WriteRefTraceLog(sm_pTraceLog, _dwOutstandingIo, this);
|
||||
|
@ -213,8 +206,8 @@ WEBSOCKET_HANDLER::IndicateCompletionToIIS(
|
|||
|
||||
--*/
|
||||
{
|
||||
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::IndicateCompletionToIIS");
|
||||
/*DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::IndicateCompletionToIIS");*/
|
||||
|
||||
_pHandler->SetStatus(FORWARDER_DONE);
|
||||
|
||||
|
@ -254,14 +247,12 @@ Routine Description:
|
|||
_pHandler = pHandler;
|
||||
|
||||
EnterCriticalSection(&_RequestLock);
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::ProcessRequest");
|
||||
|
||||
//
|
||||
// Cache the points to IHttpContext3
|
||||
//
|
||||
|
||||
hr = HttpGetExtendedInterface(g_pHttpServer,
|
||||
pHttpContext,
|
||||
&_pHttpContext);
|
||||
|
@ -285,7 +276,6 @@ Routine Description:
|
|||
//
|
||||
// Get Handle to Winhttp's websocket context.
|
||||
//
|
||||
|
||||
_hWebSocketRequest = WINHTTP_HELPER::sm_pfnWinHttpWebSocketCompleteUpgrade(
|
||||
hRequest,
|
||||
(DWORD_PTR) pHandler);
|
||||
|
@ -331,7 +321,6 @@ Routine Description:
|
|||
//
|
||||
// Initiate Read on IIS
|
||||
//
|
||||
|
||||
hr = DoIisWebSocketReceive();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -374,7 +363,6 @@ Routine Description:
|
|||
--*/
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DWORD dwBufferSize = RECEIVE_BUFFER_SIZE;
|
||||
BOOL fUtf8Encoded;
|
||||
BOOL fFinalFragment;
|
||||
|
@ -398,10 +386,8 @@ Routine Description:
|
|||
if (FAILED(hr))
|
||||
{
|
||||
DecrementOutstandingIo();
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoIisWebSocketSend failed with %08x", hr);
|
||||
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
@ -438,12 +424,9 @@ Routine Description:
|
|||
if (dwError != NO_ERROR)
|
||||
{
|
||||
DecrementOutstandingIo();
|
||||
|
||||
hr = HRESULT_FROM_WIN32(dwError);
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR,
|
||||
"WEBSOCKET_HANDLER::DoWinHttpWebSocketReceive failed with %08x", hr);
|
||||
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
@ -463,7 +446,6 @@ Routine Description:
|
|||
--*/
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
BOOL fUtf8Encoded = FALSE;
|
||||
BOOL fFinalFragment = FALSE;
|
||||
BOOL fClose = FALSE;
|
||||
|
@ -498,7 +480,6 @@ Routine Description:
|
|||
//
|
||||
// Convert close reason to WCHAR
|
||||
//
|
||||
|
||||
hr = strCloseReason.CopyA((PCSTR)&_WinHttpReceiveBuffer,
|
||||
dwReceived);
|
||||
if (FAILED(hr))
|
||||
|
@ -517,7 +498,6 @@ Routine Description:
|
|||
//
|
||||
// Send close to IIS.
|
||||
//
|
||||
|
||||
hr = _pWebSocketContext->SendConnectionClose(
|
||||
TRUE,
|
||||
uStatus,
|
||||
|
@ -542,7 +522,6 @@ Routine Description:
|
|||
//
|
||||
// Do the Send.
|
||||
//
|
||||
|
||||
hr = _pWebSocketContext->WriteFragment(
|
||||
&_WinHttpReceiveBuffer,
|
||||
&cbData,
|
||||
|
@ -552,7 +531,6 @@ Routine Description:
|
|||
OnWriteIoCompletion,
|
||||
this,
|
||||
NULL);
|
||||
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
|
@ -598,7 +576,6 @@ Routine Description:
|
|||
//
|
||||
// Get Close status from IIS.
|
||||
//
|
||||
|
||||
hr = _pWebSocketContext->GetCloseStatus(&uStatus,
|
||||
&pszReason);
|
||||
|
||||
|
@ -610,7 +587,6 @@ Routine Description:
|
|||
//
|
||||
// Convert status to UTF8
|
||||
//
|
||||
|
||||
hr = strCloseReason.CopyWToUTF8Unescaped(pszReason);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -622,7 +598,6 @@ Routine Description:
|
|||
//
|
||||
// Send Close.
|
||||
//
|
||||
|
||||
dwError = WINHTTP_HELPER::sm_pfnWinHttpWebSocketShutdown(
|
||||
_hWebSocketRequest,
|
||||
uStatus,
|
||||
|
@ -635,7 +610,6 @@ Routine Description:
|
|||
// Call will complete asynchronously, return.
|
||||
// ignore error.
|
||||
//
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend IO_PENDING");
|
||||
|
||||
|
@ -648,7 +622,6 @@ Routine Description:
|
|||
//
|
||||
// Call completed synchronously.
|
||||
//
|
||||
|
||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
||||
"WEBSOCKET_HANDLER::DoWinhttpWebSocketSend Shutdown successful.");
|
||||
}
|
||||
|
@ -810,7 +783,6 @@ Finished:
|
|||
// The handler object can be gone after this call.
|
||||
// do not reference it after this statement.
|
||||
//
|
||||
|
||||
DecrementOutstandingIo();
|
||||
|
||||
return hr;
|
||||
|
@ -841,7 +813,6 @@ WEBSOCKET_HANDLER::OnWinHttpIoError(
|
|||
hr, pCompletionStatus->AsyncResult.dwResult);
|
||||
|
||||
Cleanup(ServerDisconnect);
|
||||
|
||||
DecrementOutstandingIo();
|
||||
|
||||
return hr;
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
extern IHttpServer * g_pHttpServer;
|
||||
class FORWARDING_HANDLER;
|
||||
|
||||
class WEBSOCKET_HANDLER
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#include "precomp.hxx"
|
||||
#include "..\precomp.hxx"
|
||||
|
||||
PFN_WINHTTP_WEBSOCKET_COMPLETE_UPGRADE
|
||||
WINHTTP_HELPER::sm_pfnWinHttpWebSocketCompleteUpgrade;
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
#pragma warning( disable : 4091)
|
||||
|
||||
//
|
||||
// System related headers
|
||||
//
|
||||
#define _WINSOCKAPI_
|
||||
|
||||
#define NTDDI_VERSION 0x06010000
|
||||
#define WINVER 0x0601
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include <windows.h>
|
||||
#include <atlbase.h>
|
||||
#include <pdh.h>
|
||||
#include <vector>
|
||||
#include <Shlobj.h>
|
||||
#include <httpserv.h>
|
||||
#include <winhttp.h>
|
||||
#include <httptrace.h>
|
||||
#include <cstdlib>
|
||||
#include <reftrace.h>
|
||||
#include <wchar.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
// This should remove our issue of compiling for win7 without header files.
|
||||
// We force the Windows 8 version check logic in iiswebsocket.h to succeed even though we're compiling for Windows 7.
|
||||
// Then, we set the version defines back to Windows 7 to for the remainder of the compilation.
|
||||
#undef NTDDI_VERSION
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define NTDDI_VERSION 0x06020000
|
||||
#define WINVER 0x0602
|
||||
#define _WIN32_WINNT 0x0602
|
||||
#include <iiswebsocket.h>
|
||||
#undef NTDDI_VERSION
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
|
||||
#define NTDDI_VERSION 0x06010000
|
||||
#define WINVER 0x0601
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include "..\IISLib\acache.h"
|
||||
#include "..\IISLib\multisz.h"
|
||||
#include "..\IISLib\multisza.h"
|
||||
#include "..\IISLib\base64.h"
|
||||
#include "..\IISLib\listentry.h"
|
||||
#include "..\CommonLib\fx_ver.h"
|
||||
#include "..\CommonLib\debugutil.h"
|
||||
#include "..\CommonLib\requesthandler.h"
|
||||
#include "..\CommonLib\aspnetcoreconfig.h"
|
||||
#include "..\CommonLib\utility.h"
|
||||
#include "..\CommonLib\application.h"
|
||||
#include "aspnetcore_event.h"
|
||||
#include "aspnetcore_msg.h"
|
||||
#include "disconnectcontext.h"
|
||||
#include "sttimer.h"
|
||||
#include "resource.h"
|
||||
#include ".\inprocess\InProcessHandler.h"
|
||||
#include ".\inprocess\inprocessapplication.h"
|
||||
#include ".\outofprocess\responseheaderhash.h"
|
||||
#include ".\outofprocess\protocolconfig.h"
|
||||
#include ".\outofprocess\forwarderconnection.h"
|
||||
#include ".\outofprocess\serverprocess.h"
|
||||
#include ".\outofprocess\processmanager.h"
|
||||
#include ".\outofprocess\websockethandler.h"
|
||||
#include ".\outofprocess\forwardinghandler.h"
|
||||
#include ".\outofprocess\outprocessapplication.h"
|
||||
#include ".\outofprocess\winhttphelper.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
template<typename T> inline T max(T a, T b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
template<typename T> inline T min(T a, T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ASPNETCORE_EVENT_PROVIDER L"IIS AspNetCore Module"
|
||||
#define ASPNETCORE_IISEXPRESS_EVENT_PROVIDER L"IIS Express AspNetCore Module"
|
||||
|
||||
inline bool IsSpace(char ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 32: // ' '
|
||||
case 9: // '\t'
|
||||
case 10: // '\n'
|
||||
case 13: // '\r'
|
||||
case 11: // '\v'
|
||||
case 12: // '\f'
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
extern BOOL g_fAsyncDisconnectAvailable;
|
||||
extern BOOL g_fWinHttpNonBlockingCallbackAvailable;
|
||||
extern BOOL g_fWebSocketSupported;
|
||||
extern BOOL g_fNsiApiNotSupported;
|
||||
extern BOOL g_fEnableReferenceCountTracing;
|
||||
extern DWORD g_dwActiveServerProcesses;
|
||||
extern DWORD g_OptionalWinHttpFlags;
|
||||
extern SRWLOCK g_srwLockRH;
|
||||
extern HINTERNET g_hWinhttpSession;
|
||||
extern DWORD g_dwTlsIndex;
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IDS_INVALID_PROPERTY 1000
|
||||
#define IDS_SERVER_ERROR 1001
|
||||
|
||||
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and is listening on port '%d'."
|
||||
#define ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED_MSG L"Maximum rapid fail count per minute of '%d' exceeded."
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_INTERNAL_ERROR_MSG L"Application '%s' failed to parse processPath and arguments due to internal error, ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_POSTCREATE_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s'but failed to get its status, ErrorCode = '0x%x'."
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s', ErrorCode = '0x%x' processStatus code '%x'."
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_WRONGPORT_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but failed to listen on the given port '%d'"
|
||||
#define ASPNETCORE_EVENT_PROCESS_START_NOTREADY_ERROR_MSG L"Application '%s' with physical root '%s' created process with commandline '%s' but either crashed or did not reponse or did not listen on the given port '%d', ErrorCode = '0x%x'"
|
||||
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = %d."
|
||||
#define ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown process '%d'."
|
||||
#define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST_MSG L"Sent shutdown HTTP message to process '%d' and received http status '%d'."
|
||||
#define ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG L"Application '%s' with physical root '%s' failed to load clr and managed application, ErrorCode = '0x%x."
|
||||
#define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG L"Only one inprocess application is allowed per IIS application pool. Please assign the application '%s' to a different IIS application pool."
|
||||
#define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG L"Mixed hosting model is not supported. Application '%s' configured with different hostingModel value '%s' other than the one of running application(s)."
|
||||
#define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG L"Failed to start application '%s', ErrorCode '0x%x'."
|
||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x."
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _STTIMER_H
|
||||
#define _STTIMER_H
|
||||
|
||||
|
@ -111,6 +113,41 @@ public:
|
|||
fInCanel = FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
CALLBACK
|
||||
TimerCallback(
|
||||
_In_ PTP_CALLBACK_INSTANCE Instance,
|
||||
_In_ PVOID Context,
|
||||
_In_ PTP_TIMER Timer
|
||||
)
|
||||
{
|
||||
Instance;
|
||||
Timer;
|
||||
STRU* pstruLogFilePath = (STRU*)Context;
|
||||
HANDLE hStdoutHandle = NULL;
|
||||
SECURITY_ATTRIBUTES saAttr = { 0 };
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
hStdoutHandle = CreateFileW(pstruLogFilePath->QueryStr(),
|
||||
FILE_READ_DATA,
|
||||
FILE_SHARE_WRITE,
|
||||
&saAttr,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hStdoutHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
CloseHandle(hStdoutHandle);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
VOID
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
|
||||
|
||||
#define FileVersion 7,1,1987,0
|
||||
#define FileVersionStr "7.1.1987.0\0"
|
||||
#define ProductVersion 7,1,1987,0
|
||||
#define ProductVersionStr "7.1.1987.0\0"
|
||||
#define PlatformToolset "v141\0"
|
Загрузка…
Ссылка в новой задаче