Merge in 'release/2.1' changes
This commit is contained in:
commit
e8c63f6cf9
|
|
@ -14,9 +14,5 @@ jobs:
|
||||||
jobDisplayName: "Build and test: Windows"
|
jobDisplayName: "Build and test: Windows"
|
||||||
agentOs: Windows
|
agentOs: Windows
|
||||||
beforeBuild:
|
beforeBuild:
|
||||||
- powershell: "& ./src/IISIntegration/tools/UpdateIISExpressCertificate.ps1"
|
- powershell: "& ./src/Servers/IIS/tools/UpdateIISExpressCertificate.ps1"
|
||||||
displayName: Setup IISExpress test certificates
|
displayName: Setup IISExpress test certificates
|
||||||
- template: jobs/iisintegration-job.yml
|
|
||||||
parameters:
|
|
||||||
variables:
|
|
||||||
_FolderName: IISIntegration
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ jobs:
|
||||||
jobName: 'IISIntegration'
|
jobName: 'IISIntegration'
|
||||||
jobDisplayName: 'IISIntegration'
|
jobDisplayName: 'IISIntegration'
|
||||||
beforeBuild:
|
beforeBuild:
|
||||||
- powershell: "& ./src/IISIntegration/tools/UpdateIISExpressCertificate.ps1; & ./src/IISIntegration/tools/SetupTestEnvironment.ps1 Setup"
|
- powershell: "& ./src/servers/IIS/tools/UpdateIISExpressCertificate.ps1; & ./src/servers/IIS/tools/SetupTestEnvironment.ps1 Setup"
|
||||||
displayName: Prepare repo
|
displayName: Prepare repo
|
||||||
afterBuild:
|
afterBuild:
|
||||||
- powershell: "& ./src/IISIntegration/tools/SetupTestEnvironment.ps1 Shutdown"
|
- powershell: "& ./src/servers/IIS/tools/SetupTestEnvironment.ps1 Shutdown"
|
||||||
displayName: Stop AppVerifier
|
displayName: Stop AppVerifier
|
||||||
condition: always()
|
condition: always()
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
|
|
@ -16,5 +16,5 @@ jobs:
|
||||||
inputs:
|
inputs:
|
||||||
artifactName: logs
|
artifactName: logs
|
||||||
artifactType: Container
|
artifactType: Container
|
||||||
pathtoPublish: src/IISIntegration/artifacts/logs
|
pathtoPublish: src/servers/IIS/artifacts/logs
|
||||||
buildDirectory: src/IISIntegration
|
buildDirectory: src/servers/IIS
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,4 @@ scripts/tmp/
|
||||||
.tools/
|
.tools/
|
||||||
launchSettings.json
|
launchSettings.json
|
||||||
korebuild-lock.txt
|
korebuild-lock.txt
|
||||||
|
.gradle/
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,7 @@
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.Antiforgery" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.Antiforgery" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.App" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.App" Category="ship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" AllMetapackage="true" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" AllMetapackage="true" Category="ship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.AspNetCoreModule" Category="noship" Condition=" '$(OS)' == 'Windows_NT' " />
|
<PackageArtifact Include="Microsoft.AspNetCore.AspNetCoreModuleV1" Category="noship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.AspNetCoreModuleV1" Category="noship" Condition=" '$(OS)' == 'Windows_NT' " />
|
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.Abstractions" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.Abstractions" AllMetapackage="true" AppMetapackage="true" Category="ship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Category="ship" />
|
||||||
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Category="ship" />
|
<PackageArtifact Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Category="ship" />
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<RepositoryBuildOrder Include="Razor" Order="6" RootPath="$(RepositoryRoot)src\Razor\" />
|
<RepositoryBuildOrder Include="Razor" Order="6" RootPath="$(RepositoryRoot)src\Razor\" />
|
||||||
<RepositoryBuildOrder Include="EntityFrameworkCore" Order="8" />
|
<RepositoryBuildOrder Include="EntityFrameworkCore" Order="8" />
|
||||||
<RepositoryBuildOrder Include="IISIntegration" Order="10" RootPath="$(RepositoryRoot)src\IISIntegration\" />
|
|
||||||
<RepositoryBuildOrder Include="ServerTests" Order="11" RootPath="$(RepositoryRoot)src\ServerTests\" />
|
<RepositoryBuildOrder Include="ServerTests" Order="11" RootPath="$(RepositoryRoot)src\ServerTests\" />
|
||||||
<RepositoryBuildOrder Include="Security" Order="13" RootPath="$(RepositoryRoot)src\Security\" />
|
<RepositoryBuildOrder Include="Security" Order="13" RootPath="$(RepositoryRoot)src\Security\" />
|
||||||
<RepositoryBuildOrder Include="MetaPackages" Order="13" RootPath="$(RepositoryRoot)src\MetaPackages\" />
|
<RepositoryBuildOrder Include="MetaPackages" Order="13" RootPath="$(RepositoryRoot)src\MetaPackages\" />
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
$(RepositoryRoot)src\Tools\dotnet-watch\test\TestProjects\**\*.csproj
|
$(RepositoryRoot)src\Tools\dotnet-watch\test\TestProjects\**\*.csproj
|
||||||
" />
|
" />
|
||||||
|
|
||||||
|
<ProjectToBuild Include="@(NativeProjects)" Condition="'$(OS)' == 'Windows_NT'"/>
|
||||||
<ProjectToBuild Include="
|
<ProjectToBuild Include="
|
||||||
$(RepositoryRoot)src\Features\JsonPatch\**\*.*proj;
|
$(RepositoryRoot)src\Features\JsonPatch\**\*.*proj;
|
||||||
$(RepositoryRoot)src\DataProtection\**\*.*proj;
|
$(RepositoryRoot)src\DataProtection\**\*.*proj;
|
||||||
|
|
@ -71,7 +72,8 @@
|
||||||
$(RepositoryRoot)src\Hosting\**\*.*proj;
|
$(RepositoryRoot)src\Hosting\**\*.*proj;
|
||||||
$(RepositoryRoot)src\Http\**\*.*proj;
|
$(RepositoryRoot)src\Http\**\*.*proj;
|
||||||
$(RepositoryRoot)src\Html\**\*.*proj;
|
$(RepositoryRoot)src\Html\**\*.*proj;
|
||||||
$(RepositoryRoot)src\Servers\**\*.*proj;
|
$(RepositoryRoot)src\Servers\**\*.csproj;
|
||||||
|
$(RepositoryRoot)src\Servers\**\*.pkgproj;
|
||||||
$(RepositoryRoot)src\Tools\**\*.*proj;
|
$(RepositoryRoot)src\Tools\**\*.*proj;
|
||||||
$(RepositoryRoot)src\Middleware\**\*.*proj;
|
$(RepositoryRoot)src\Middleware\**\*.*proj;
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Repository Include="IISIntegration" RootPath="$(RepositoryRoot)src\IISIntegration\" />
|
|
||||||
<Repository Include="MetaPackages" PatchPolicy="CascadeVersions" RootPath="$(RepositoryRoot)src\MetaPackages\" />
|
<Repository Include="MetaPackages" PatchPolicy="CascadeVersions" RootPath="$(RepositoryRoot)src\MetaPackages\" />
|
||||||
<Repository Include="Scaffolding" PatchPolicy="AlwaysUpdate" />
|
<Repository Include="Scaffolding" PatchPolicy="AlwaysUpdate" />
|
||||||
<Repository Include="Templating" PatchPolicy="AlwaysUpdateAndCascadeVersions" RootPath="$(RepositoryRoot)src\Templating\" />
|
<Repository Include="Templating" PatchPolicy="AlwaysUpdateAndCascadeVersions" RootPath="$(RepositoryRoot)src\Templating\" />
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,25 @@
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="[2.1.1, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="[2.1.1, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<!-- Package: Microsoft.AspNetCore.Server.IISIntegration-->
|
||||||
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.IISIntegration' ">
|
||||||
|
<BaselinePackageVersion>2.1.2</BaselinePackageVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.IISIntegration' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.HttpOverrides" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
|
||||||
|
<BaselinePackageReference Include="System.Buffers" Version="[4.5.0, )" />
|
||||||
|
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.5.2, )" />
|
||||||
|
<BaselinePackageReference Include="System.Memory" Version="[4.5.1, )" />
|
||||||
|
<BaselinePackageReference Include="System.Numerics.Vectors" Version="[4.5.0, )" />
|
||||||
|
<BaselinePackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="[4.5.2, )" />
|
||||||
|
<BaselinePackageReference Include="System.Security.Principal.Windows" Version="[4.5.1, )" />
|
||||||
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.JsonPatch-->
|
<!-- Package: Microsoft.AspNetCore.JsonPatch-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' ">
|
||||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
<Package Id="Microsoft.AspNetCore.Rewrite" Version="2.1.1" />
|
<Package Id="Microsoft.AspNetCore.Rewrite" Version="2.1.1" />
|
||||||
<Package Id="Microsoft.AspNetCore.Routing.Abstractions" Version="2.1.1" />
|
<Package Id="Microsoft.AspNetCore.Routing.Abstractions" Version="2.1.1" />
|
||||||
<Package Id="Microsoft.AspNetCore.Routing" Version="2.1.1" />
|
<Package Id="Microsoft.AspNetCore.Routing" Version="2.1.1" />
|
||||||
|
<Package Id="Microsoft.AspNetCore.Server.IISIntegration" Version="2.1.2" />
|
||||||
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.1.3" />
|
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.1.3" />
|
||||||
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.1.3" />
|
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.1.3" />
|
||||||
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" Version="2.1.3" />
|
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" Version="2.1.3" />
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Localization" Version="$(MicrosoftExtensionsLocalizationPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Localization" Version="$(MicrosoftExtensionsLocalizationPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||||
|
<LatestPackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion)" />
|
||||||
|
|
@ -48,12 +49,16 @@
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders.Sources" Version="$(MicrosoftExtensionsWebEncodersSourcesPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders.Sources" Version="$(MicrosoftExtensionsWebEncodersSourcesPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
|
||||||
<LatestPackageReference Include="Microsoft.NETCore.Windows.ApiSets" Version="$(MicrosoftNETCoreWindowsApiSetsPackageVersion)" />
|
<LatestPackageReference Include="Microsoft.NETCore.Windows.ApiSets" Version="$(MicrosoftNETCoreWindowsApiSetsPackageVersion)" />
|
||||||
|
<LatestPackageReference Include="System.Buffers" Version="$(SystemBuffersPackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Data.SqlClient" Version="$(SystemDataSqlClientPackageVersion)" />
|
<LatestPackageReference Include="System.Data.SqlClient" Version="$(SystemDataSqlClientPackageVersion)" />
|
||||||
|
<LatestPackageReference Include="System.IO.Pipelines" Version="$(SystemIOPipelinesPackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
|
<LatestPackageReference Include="System.Memory" Version="$(SystemMemoryPackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Net.Http.WinHttpHandler" Version="$(SystemNetHttpWinHttpHandlerPackageVersion)" />
|
|
||||||
<LatestPackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="$(SystemNetWebSocketsWebSocketProtocolPackageVersion)" />
|
<LatestPackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="$(SystemNetWebSocketsWebSocketProtocolPackageVersion)" />
|
||||||
|
<LatestPackageReference Include="System.Net.Http.WinHttpHandler" Version="$(SystemNetHttpWinHttpHandlerPackageVersion)" />
|
||||||
|
<LatestPackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsPackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
|
<LatestPackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemRuntimeCompilerServicesUnsafePackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Security.Cryptography.Cng" Version="$(SystemSecurityCryptographyCngPackageVersion)" />
|
<LatestPackageReference Include="System.Security.Cryptography.Cng" Version="$(SystemSecurityCryptographyCngPackageVersion)" />
|
||||||
|
<LatestPackageReference Include="System.Security.Principal.Windows" Version="$(SystemSecurityPrincipalWindowsPackageVersion)" />
|
||||||
<LatestPackageReference Include="System.Text.Encodings.Web" Version="$(SystemTextEncodingsWebPackageVersion)" />
|
<LatestPackageReference Include="System.Text.Encodings.Web" Version="$(SystemTextEncodingsWebPackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Html.Abstractions" ProjectPath="$(RepositoryRoot)src\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Html.Abstractions" ProjectPath="$(RepositoryRoot)src\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Connections.Abstractions" ProjectPath="$(RepositoryRoot)src\Servers\Connections.Abstractions\src\Microsoft.AspNetCore.Connections.Abstractions.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Connections.Abstractions" ProjectPath="$(RepositoryRoot)src\Servers\Connections.Abstractions\src\Microsoft.AspNetCore.Connections.Abstractions.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.HttpSys" ProjectPath="$(RepositoryRoot)src\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.HttpSys" ProjectPath="$(RepositoryRoot)src\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj" />
|
||||||
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.IISIntegration" ProjectPath="$(RepositoryRoot)src\Servers\IIS\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Core" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Core" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Https" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Https\src\Microsoft.AspNetCore.Server.Kestrel.Https.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Https" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Https\src\Microsoft.AspNetCore.Server.Kestrel.Https.csproj" />
|
||||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel" ProjectPath="$(RepositoryRoot)src\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@
|
||||||
|
|
||||||
<Import Project="$(MicroBuildPluginDirectory)\MicroBuild.Plugins.*\**\build\MicroBuild.Plugins.*.targets" Condition="'$(DisableMicroBuild)' != 'true' AND '$(MicroBuildPluginDirectory)' != ''" />
|
<Import Project="$(MicroBuildPluginDirectory)\MicroBuild.Plugins.*\**\build\MicroBuild.Plugins.*.targets" Condition="'$(DisableMicroBuild)' != 'true' AND '$(MicroBuildPluginDirectory)' != ''" />
|
||||||
|
|
||||||
|
<Target Name="Pack" />
|
||||||
|
<Target Name="Restore" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import
|
|
||||||
Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\AspNetCoreSettings.props"
|
|
||||||
Condition=" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' " />
|
|
||||||
|
|
||||||
<Import Project="version.props" />
|
|
||||||
<Import Project="build\dependencies.props" />
|
|
||||||
<Import Project="build\sources.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<Product>Microsoft ASP.NET Core</Product>
|
|
||||||
<RepositoryUrl>https://github.com/aspnet/AspNetCore</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
|
||||||
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)..\..\eng\AspNetCore.snk</AssemblyOriginatorKeyFile>
|
|
||||||
<SignAssembly>true</SignAssembly>
|
|
||||||
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
|
||||||
<!-- https://github.com/aspnet/IISIntegration/issues/617 -->
|
|
||||||
<EnableApiCheck>false</EnableApiCheck>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
|
||||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
|
||||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,300 +0,0 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 15
|
|
||||||
VisualStudioVersion = 15.0.27130.2036
|
|
||||||
MinimumVisualStudioVersion = 15.0.26730.03
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04B1EDB6-E967-4D25-89B9-E6F8304038CD}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
src\Directory.Build.props = src\Directory.Build.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0EF45656-B25D-40D8-959C-726EAF185E60}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
.editorconfig = .editorconfig
|
|
||||||
Directory.Build.props = Directory.Build.props
|
|
||||||
Directory.Build.targets = Directory.Build.targets
|
|
||||||
NuGet.Config = NuGet.Config
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EF30B533-D715-421A-92B7-92FEF460AC9C}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
test\Directory.Build.props = test\Directory.Build.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C74B8F36-FD2F-45C9-9B8A-00E7CF0126A9}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IISSample", "samples\IISSample\IISSample.csproj", "{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{8B3446E8-E6A8-4591-AA63-A95837C6E97C}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration.Tests", "test\Microsoft.AspNetCore.Server.IISIntegration.Tests\Microsoft.AspNetCore.Server.IISIntegration.Tests.csproj", "{4106DB10-E09F-480E-9CE6-B39235512EE6}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OutOfProcessWebSite", "test\WebSites\OutOfProcessWebSite\OutOfProcessWebSite.csproj", "{F54715C3-88D8-49E3-A291-C13570FE81FC}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {D57EA297-6DC2-4BC0-8C91-334863327863}
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {439824F9-1455-4CC4-BD79-B44FA0A16552}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7E80C58E-9CC8-450C-8A8D-94FC76428150}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
build\applicationhost.config = build\applicationhost.config
|
|
||||||
build\applicationhost.iis.config = build\applicationhost.iis.config
|
|
||||||
build\dependencies.props = build\dependencies.props
|
|
||||||
build\native.targets = build\native.targets
|
|
||||||
build\repo.props = build\repo.props
|
|
||||||
build\testsite.props = build\testsite.props
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IISIntegration.FunctionalTests", "test\IISIntegration.FunctionalTests\IISIntegration.FunctionalTests.csproj", "{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeIISSample", "samples\NativeIISSample\NativeIISSample.csproj", "{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {D57EA297-6DC2-4BC0-8C91-334863327863}
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {439824F9-1455-4CC4-BD79-B44FA0A16552}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "test\WebSites\InProcessWebSite\InProcessWebSite.csproj", "{679FA2A2-898B-4320-884E-C2D294A97CE1}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {D57EA297-6DC2-4BC0-8C91-334863327863}
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {439824F9-1455-4CC4-BD79-B44FA0A16552}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StressTestWebSite", "test\WebSites\StressTestWebSite\StressTestWebSite.csproj", "{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestTasks", "test\TestTasks\TestTasks.csproj", "{064D860B-4D7C-4B1D-918F-E020F1B99E2A}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OverriddenServerWebSite", "test\WebSites\OverriddenServerWebSite\OverriddenServerWebSite.csproj", "{FC2A97F8-A749-4C04-97D1-97500066A820}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {D57EA297-6DC2-4BC0-8C91-334863327863}
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {439824F9-1455-4CC4-BD79-B44FA0A16552}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AspNetCoreModuleV1", "AspNetCoreModuleV1", "{16E521CE-77F1-4B1C-A183-520A41C4F372}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AspNetCoreModuleV2", "AspNetCoreModuleV2", "{06CA2C2B-83B0-4D83-905A-E0C74790009E}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IISLib", "src\AspNetCoreModuleV1\IISLib\IISLib.vcxproj", "{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AspNetCore", "src\AspNetCoreModuleV1\AspNetCore\AspNetCore.vcxproj", "{439824F9-1455-4CC4-BD79-B44FA0A16552}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AspNetCore", "src\AspNetCoreModuleV2\AspNetCore\AspNetCore.vcxproj", "{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "src\AspNetCoreModuleV2\CommonLib\CommonLib.vcxproj", "{55494E58-E061-4C4C-A0A8-837008E72F85}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IISLib", "src\AspNetCoreModuleV2\IISLib\IISLib.vcxproj", "{09D9D1D6-2951-4E14-BC35-76A23CF9391A}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RequestHandler", "src\AspNetCoreModuleV2\RequestHandler\RequestHandler.vcxproj", "{D57EA297-6DC2-4BC0-8C91-334863327863}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Release|x64.Build.0 = Release|x64
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC}.Release|x86.Build.0 = Release|x86
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|x64.Build.0 = Release|x64
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97}.Release|x86.Build.0 = Release|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Release|x64.Build.0 = Release|x64
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1}.Release|x86.Build.0 = Release|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Release|x64.Build.0 = Release|x64
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F}.Release|x86.Build.0 = Release|x86
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Release|x64.Build.0 = Release|x64
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820}.Release|x86.Build.0 = Release|x86
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{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}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|x64.Build.0 = Release|x64
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{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}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x64.Build.0 = Release|x64
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x64.Build.0 = Release|x64
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{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|x86.ActiveCfg = Debug|Win32
|
|
||||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Any CPU.ActiveCfg = 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|x86.ActiveCfg = Release|Win32
|
|
||||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x64.Build.0 = Release|x64
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
|
||||||
{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}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|Any CPU.ActiveCfg = Release|Win32
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.Build.0 = Release|x64
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(NestedProjects) = preSolution
|
|
||||||
{E4E2BDC4-A9C6-4AE9-B429-032EC83EDE64} = {C74B8F36-FD2F-45C9-9B8A-00E7CF0126A9}
|
|
||||||
{8B3446E8-E6A8-4591-AA63-A95837C6E97C} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
|
||||||
{4106DB10-E09F-480E-9CE6-B39235512EE6} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
|
||||||
{F54715C3-88D8-49E3-A291-C13570FE81FC} = {744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}
|
|
||||||
{4E3E1F5C-CD52-4CC0-A35F-D1FA1685D2FA} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
|
||||||
{9BC4AFCB-325D-4C81-8228-8CF301CE2F97} = {C74B8F36-FD2F-45C9-9B8A-00E7CF0126A9}
|
|
||||||
{679FA2A2-898B-4320-884E-C2D294A97CE1} = {744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}
|
|
||||||
{13FD8F12-FFBE-4D01-B4AC-444F2994B04F} = {744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}
|
|
||||||
{064D860B-4D7C-4B1D-918F-E020F1B99E2A} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
|
||||||
{744ACDC6-F6A0-4FF9-9421-F25C5F2DC520} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
|
|
||||||
{FC2A97F8-A749-4C04-97D1-97500066A820} = {744ACDC6-F6A0-4FF9-9421-F25C5F2DC520}
|
|
||||||
{16E521CE-77F1-4B1C-A183-520A41C4F372} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
|
||||||
{06CA2C2B-83B0-4D83-905A-E0C74790009E} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
|
|
||||||
{4787A64F-9A3E-4867-A55A-70CB4B2B2FFE} = {16E521CE-77F1-4B1C-A183-520A41C4F372}
|
|
||||||
{439824F9-1455-4CC4-BD79-B44FA0A16552} = {16E521CE-77F1-4B1C-A183-520A41C4F372}
|
|
||||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
|
||||||
{55494E58-E061-4C4C-A0A8-837008E72F85} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
|
||||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
|
||||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {06CA2C2B-83B0-4D83-905A-E0C74790009E}
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {DB4F868D-E1AE-4FD7-9333-69FA15B268C5}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
This repo hosts the ASP.NET Core middleware for IIS integration and the ASP.NET Core Module.
|
|
||||||
|
|
||||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
@ECHO OFF
|
|
||||||
SET RepoRoot="%~dp0..\.."
|
|
||||||
%RepoRoot%\build.cmd -LockFile %RepoRoot%\korebuild-lock.txt -Path %~dp0 %*
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
repo_root="$DIR/../.."
|
|
||||||
"$repo_root/build.sh" --path "$DIR" --lockfile "$repo_root/korebuild-lock.txt" "$@"
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="12.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildThisFileDirectory)\Build.Settings" />
|
|
||||||
<ItemGroup>
|
|
||||||
<Projects Include="$(SolutionDir)\src\AspNetCoreModuleV1\AspNetCore\AspNetCore.vcxproj" />
|
|
||||||
<Projects Include="$(SolutionDir)\src\AspNetCoreModuleV2\AspNetCore\AspNetCore.vcxproj" />
|
|
||||||
<Projects Include="$(SolutionDir)\src\AspNetCoreModuleV2\RequestHandler\RequestHandler.vcxproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="Build">
|
|
||||||
<MSBuild Targets="$(BuildTargets)"
|
|
||||||
Projects="@(Projects)"
|
|
||||||
Properties="Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset)" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="Clean">
|
|
||||||
<MSBuild Targets="Clean"
|
|
||||||
Projects="@(Projects)" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="Rebuild">
|
|
||||||
<MSBuild Targets="Clean;Build"
|
|
||||||
Projects="$(MSBuildProjectFile)"
|
|
||||||
Properties="BuildTargets=Rebuild;Configuration=$(Configuration);Platform=$(Platform);PlatformToolset=$(PlatformToolset)"/>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="Test" DependsOnTargets="Build">
|
|
||||||
<!-- once we have test project ready, we should add executions to run the test post build-->
|
|
||||||
</Target>
|
|
||||||
<Import Project="Config.Definitions.Props" />
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- These package versions may be overridden or updated by automation. -->
|
|
||||||
<PropertyGroup Label="Package Versions: Auto">
|
|
||||||
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
|
|
||||||
<MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
|
|
||||||
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
|
|
||||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
|
||||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
|
||||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
|
||||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
|
||||||
<SystemBuffersPackageVersion>4.5.0</SystemBuffersPackageVersion>
|
|
||||||
<SystemIOPipelinesPackageVersion>4.5.0</SystemIOPipelinesPackageVersion>
|
|
||||||
<SystemMemoryPackageVersion>4.5.1</SystemMemoryPackageVersion>
|
|
||||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>4.5.1</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
|
||||||
<SystemNumericsVectorsPackageVersion>4.5.0</SystemNumericsVectorsPackageVersion>
|
|
||||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.1</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
|
||||||
<SystemSecurityPrincipalWindowsPackageVersion>4.5.0</SystemSecurityPrincipalWindowsPackageVersion>
|
|
||||||
<Tooling_NewtonsoftJsonPackageVersion>9.0.1</Tooling_NewtonsoftJsonPackageVersion>
|
|
||||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
|
||||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- This may import a generated file which may override the variables above. -->
|
|
||||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
|
||||||
|
|
||||||
<!-- These are package versions that should not be overridden or updated by automation. -->
|
|
||||||
<PropertyGroup Label="Package Versions: Pinned">
|
|
||||||
<MicrosoftAspNetCoreAllPackageVersion>2.1.2</MicrosoftAspNetCoreAllPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.1.1</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.1</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHostingPackageVersion>2.1.1</MicrosoftAspNetCoreHostingPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.1.1</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHttpOverridesPackageVersion>2.1.1</MicrosoftAspNetCoreHttpOverridesPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHttpPackageVersion>2.1.1</MicrosoftAspNetCoreHttpPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreHttpSysSourcesPackageVersion>2.1.1</MicrosoftAspNetCoreHttpSysSourcesPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.1</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.1.1</MicrosoftAspNetCoreTestHostPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0</MicrosoftAspNetCoreTestingPackageVersion>
|
|
||||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.1</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
|
||||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.1.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
|
||||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
|
||||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
|
||||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
|
||||||
<MicrosoftExtensionsLoggingDebugPackageVersion>2.1.1</MicrosoftExtensionsLoggingDebugPackageVersion>
|
|
||||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.1</MicrosoftExtensionsLoggingPackageVersion>
|
|
||||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.1</MicrosoftExtensionsLoggingTestingPackageVersion>
|
|
||||||
<MicrosoftExtensionsOptionsPackageVersion>2.1.1</MicrosoftExtensionsOptionsPackageVersion>
|
|
||||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.1</MicrosoftNetHttpHeadersPackageVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": true,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:5762/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"ANCM IIS Express": {
|
|
||||||
"commandName": "Executable",
|
|
||||||
"executablePath": "$(IISExpressPath)",
|
|
||||||
"commandLineArgs": "$(IISExpressArguments)",
|
|
||||||
"nativeDebugging": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
|
||||||
"ANCM_PATH": "$(TargetDir)$(AncmPath)",
|
|
||||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
|
||||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ANCM IIS": {
|
|
||||||
"commandName": "Executable",
|
|
||||||
"executablePath": "$(IISPath)",
|
|
||||||
"commandLineArgs": "$(IISArguments)",
|
|
||||||
"environmentVariables": {
|
|
||||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
|
||||||
"ANCM_PATH": "$(TargetDir)$(AncmPath)",
|
|
||||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
|
||||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="dependencies.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<AssemblySigningCertName>Microsoft</AssemblySigningCertName>
|
|
||||||
<AncmZipOutputPath>$(BuildDir)AspNetCoreModule.zip</AncmZipOutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\TestSites\*.csproj" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\IISTestSite\*.csproj" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\IISIntegration.FunctionalTests\*.csproj" Condition="'$(OS)' != 'Windows_NT'" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\IISIntegration.IISServerFunctionalTests\*.csproj" Condition="'$(OS)' != 'Windows_NT'" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\AspNetCoreModule.TestSites.Standard\*.csproj" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\WebSocketClientEXE\*.csproj" />
|
|
||||||
<ExcludeFromTest Include="$(RepositoryRoot)test\AspNetCoreModule.Test\*.csproj" Condition="'$(OS)' != 'Windows_NT'" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
|
||||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
|
||||||
<!-- These are for functional test projects that are only runable on windows -->
|
|
||||||
<DotNetCoreRuntime Condition="'$(OS)' == 'Windows_NT'" Include="$(MicrosoftNETCoreApp20PackageVersion)" Arch="x86" />
|
|
||||||
<DotNetCoreRuntime Condition="'$(OS)' == 'Windows_NT'" Include="$(MicrosoftNETCoreApp21PackageVersion)" Arch="x86" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
<Project>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<CompileDependsOn Condition="'$(OS)'=='Windows_NT'">BuildNativeAssets;$(CompileDependsOn)</CompileDependsOn>
|
|
||||||
<PackageDependsOn Condition="'$(OS)'=='Windows_NT'">$(PackageDependsOn);PackageNativeProjects</PackageDependsOn>
|
|
||||||
<NuGetVerifierRuleFile Condition="'$(OS)' != 'Windows_NT'">$(RepositoryRoot)NuGetPackageVerifier.xplat.json</NuGetVerifierRuleFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Target Name="BuildNativeAssets" DependsOnTargets="Prepare;GetToolsets" >
|
|
||||||
<PropertyGroup>
|
|
||||||
<BuildArgs>-p:Configuration=$(Configuration) -v:m -nologo -clp:NoSummary -p:CommitHash=$(CommitHash)</BuildArgs>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Platforms Include="Win32;x64" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Error
|
|
||||||
Text="Could not find an installation of Visual Studio with the C++ development tools."
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' == ''" />
|
|
||||||
|
|
||||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" "$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\AspNetCore.vcxproj" $(BuildArgs) -p:Platform=%(Platforms.Identity) -bl:$(LogOutputDir)native.%(Platforms.Identity).binlog"
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
|
||||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" "$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\AspNetCore.vcxproj" $(BuildArgs) -p:Platform=%(Platforms.Identity) -bl:$(LogOutputDir)native.%(Platforms.Identity).binlog"
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
|
||||||
<Exec Command=""$(VisualStudioMSBuildx86Path)" "$(RepositoryRoot)src\AspNetCoreModuleV2\RequestHandler\RequestHandler.vcxproj" $(BuildArgs) -p:Platform=%(Platforms.Identity) -bl:$(LogOutputDir)native.%(Platforms.Identity).binlog"
|
|
||||||
Condition="'$(VisualStudioMSBuildx86Path)' != ''" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(OS)' == 'Windows_NT' ">
|
|
||||||
<ArtifactInfo Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModule.$(PackageVersion).nupkg">
|
|
||||||
<ArtifactType>NuGetPackage</ArtifactType>
|
|
||||||
<PackageId>Microsoft.AspNetCore.AspNetCoreModule</PackageId>
|
|
||||||
<Version>$(PackageVersion)</Version>
|
|
||||||
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
|
|
||||||
</ArtifactInfo>
|
|
||||||
<FilesToExcludeFromSigning Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModule.$(PackageVersion).nupkg" />
|
|
||||||
|
|
||||||
<ArtifactInfo Include="$(BuildDir)Microsoft.AspNetCore.AspNetCoreModuleV1.$(PackageVersion).nupkg">
|
|
||||||
<ArtifactType>NuGetPackage</ArtifactType>
|
|
||||||
<PackageId>Microsoft.AspNetCore.AspNetCoreModuleV1</PackageId>
|
|
||||||
<Version>$(PackageVersion)</Version>
|
|
||||||
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
|
|
||||||
</ArtifactInfo>
|
|
||||||
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PackageNativeProjects">
|
|
||||||
<PackNuspec NuspecPath="$(MSBuildThisFileDirectory)..\nuget\AspNetCoreV1.nuspec"
|
|
||||||
DestinationFolder="$(BuildDir)"
|
|
||||||
Properties="version=$(PackageVersion);Configuration=$(Configuration)"
|
|
||||||
Overwrite="true"
|
|
||||||
BasePath="$(RepositoryRoot)" />
|
|
||||||
|
|
||||||
<PackNuspec NuspecPath="$(MSBuildThisFileDirectory)..\nuget\AspNetCoreV2.nuspec"
|
|
||||||
DestinationFolder="$(BuildDir)"
|
|
||||||
Properties="version=$(PackageVersion);Configuration=$(Configuration)"
|
|
||||||
Overwrite="true"
|
|
||||||
BasePath="$(RepositoryRoot)" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- x64 -->
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\x64\aspnetcore.dll" Link="AspNetCoreModuleV1\x64\aspnetcore.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\x64\aspnetcore.pdb" Link="AspNetCoreModuleV1\x64\aspnetcore.pdb" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcore.dll" Link="AspNetCoreModuleV2\x64\aspnetcore.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcore.pdb" Link="AspNetCoreModuleV2\x64\aspnetcore.pdb" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\x64\aspnetcorerh.dll" Link="AspNetCoreModuleV2\x64\aspnetcorerh.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\x64\aspnetcorerh.pdb" Link="AspNetCoreModuleV2\x64\aspnetcorerh.pdb" />
|
|
||||||
<!-- x86 -->
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\Win32\aspnetcore.dll" Link="AspNetCoreModuleV1\x86\aspnetcore.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\Win32\aspnetcore.pdb" Link="AspNetCoreModuleV1\x86\aspnetcore.pdb" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\Win32\aspnetcore.dll" Link="AspNetCoreModuleV2\x86\aspnetcore.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\Win32\aspnetcore.pdb" Link="AspNetCoreModuleV2\x86\aspnetcore.pdb" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\Win32\aspnetcorerh.dll" Link="AspNetCoreModuleV2\x86\aspnetcorerh.dll" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\Win32\aspnetcorerh.pdb" Link="AspNetCoreModuleV2\x86\aspnetcorerh.pdb" />
|
|
||||||
<!-- Schema-->
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\x64\aspnetcore_schema.xml" Link="AspNetCoreModuleV1\aspnetcore_schema.xml" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\aspnetcore_schema.xml" Link="AspNetCoreModuleV2\aspnetcore_schema.xml" />
|
|
||||||
<AncmFiles Include="$(RepositoryRoot)src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\x64\ancm.mof" Link="AspNetCoreModuleV2\ancm.mof" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<Project>
|
|
||||||
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
|
|
||||||
|
|
||||||
<PropertyGroup Label="RestoreSources">
|
|
||||||
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
|
|
||||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
|
|
||||||
$(RestoreSources);
|
|
||||||
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
|
|
||||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
|
||||||
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
|
||||||
</RestoreSources>
|
|
||||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
|
|
||||||
$(RestoreSources);
|
|
||||||
https://api.nuget.org/v3/index.json;
|
|
||||||
</RestoreSources>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
<Project>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RuntimeIdentifiers>win7-x64;win7-x86</RuntimeIdentifiers>
|
|
||||||
<Platforms>x64;x86</Platforms>
|
|
||||||
<IISExpressAppHostConfig>$(MSBuildThisFileDirectory)applicationhost.config</IISExpressAppHostConfig>
|
|
||||||
<IISAppHostConfig>$(MSBuildThisFileDirectory)applicationhost.iis.config</IISAppHostConfig>
|
|
||||||
<NativePlatform Condition="'$(Platform)' == 'AnyCPU'">x64</NativePlatform>
|
|
||||||
<NativePlatform Condition="'$(NativePlatform)' == ''">$(Platform)</NativePlatform>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(NativePlatform)' == 'x86'">
|
|
||||||
<IISExpressPath>$(MSBuildProgramFiles32)\IIS Express\iisexpress.exe</IISExpressPath>
|
|
||||||
<IISPath>$(SystemRoot)\SysWOW64\inetsrv\w3wp.exe</IISPath>
|
|
||||||
<NativeFolder>Win32</NativeFolder>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(NativePlatform)' == 'x64'">
|
|
||||||
<IISExpressPath>$(ProgramW6432)\IIS Express\iisexpress.exe</IISExpressPath>
|
|
||||||
<IISPath>$(SystemRoot)\System32\inetsrv\w3wp.exe</IISPath>
|
|
||||||
<NativeFolder>x64</NativeFolder>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<!-- For standalone publish, all dlls are flattened to the same folder.
|
|
||||||
Set the base path to the request handler
|
|
||||||
-->
|
|
||||||
<BasePathForRequestHandler Condition="'$(RuntimeIdentifier)' == ''">$(NativePlatform)\</BasePathForRequestHandler>
|
|
||||||
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND ('$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == '')">
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorerh.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\RequestHandler\bin\$(Configuration)\$(NativeFolder)\aspnetcorerh.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(BasePathForRequestHandler)%(FileName)%(Extension)" />
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcore.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(NativePlatform)\%(FileName)%(Extension)" />
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV2\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcore.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(NativePlatform)\%(FileName)%(Extension)" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND '$(ANCMVersion)' == 'V1'">
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcore.dll" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(NativePlatform)\%(FileName)%(Extension)" />
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)..\src\AspNetCoreModuleV1\AspNetCore\bin\$(Configuration)\$(NativeFolder)\aspnetcore.pdb" CopyToOutputDirectory="PreserveNewest" Visible="true" Link="$(NativePlatform)\%(FileName)%(Extension)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<IISExpressArguments>/config:"$(IISExpressAppHostConfig)"</IISExpressArguments>
|
|
||||||
<IISArguments>-h "$(IISAppHostConfig)"</IISArguments>
|
|
||||||
|
|
||||||
<AncmPath>$(NativePlatform)\aspnetcore.dll</AncmPath>
|
|
||||||
<AncmRHPath>$(NativePlatform)\aspnetcorerh.dll</AncmRHPath>
|
|
||||||
<DotNetPath>$(userprofile)\.dotnet\$(NativePlatform)\dotnet.exe</DotNetPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Target Name="CopyLaunchSettings" AfterTargets="CoreBuild">
|
|
||||||
<!-- This would always override launch settings files in test projects by the default one -->
|
|
||||||
<Copy SourceFiles="$(MSBuildThisFileDirectory)launchSettings.json" DestinationFolder="$(MSBuildProjectDirectory)\Properties" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<!-- Deps file injection-->
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="$(MSBuildThisFileDirectory)..\test\TestTasks\TestTasks.csproj">
|
|
||||||
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<Target Name="PrepareInjectionApp" Condition="'$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == ''">
|
|
||||||
<PropertyGroup>
|
|
||||||
<InjectDepsAssembly>$(MSBuildThisFileDirectory)..\test\TestTasks\bin\$(Configuration)\$(TargetFramework)\TestTasks</InjectDepsAssembly>
|
|
||||||
|
|
||||||
<InjectDepsApp Condition="'$(TargetFramework)' == 'net461'">$(InjectDepsAssembly)</InjectDepsApp>
|
|
||||||
<InjectDepsArguments>"win7-$(NativePlatform)" "$(AncmRHPath)"</InjectDepsArguments>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net461'">
|
|
||||||
<InjectDepsAssembly>$(InjectDepsAssembly).exe</InjectDepsAssembly>
|
|
||||||
<InjectDepsApp>$(InjectDepsAssembly)</InjectDepsApp>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TargetFramework)' != 'net461'">
|
|
||||||
<InjectDepsAssembly>$(InjectDepsAssembly).dll</InjectDepsAssembly>
|
|
||||||
<InjectDepsApp>dotnet</InjectDepsApp>
|
|
||||||
<InjectDepsArguments>$(InjectDepsAssembly) $(InjectDepsArguments)</InjectDepsArguments>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="InjectRequestHandler" AfterTargets="GenerateBuildDependencyFile" DependsOnTargets="PrepareInjectionApp" Condition="'$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == ''">
|
|
||||||
<Exec Command="$(InjectDepsApp) $(InjectDepsArguments) "$(ProjectDepsFilePath)"" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target Name="InjectRequestHandlerOnPublish" AfterTargets="GeneratePublishDependencyFile" DependsOnTargets="PrepareInjectionApp" Condition="'$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == ''">
|
|
||||||
<Exec Command="$(InjectDepsApp) $(InjectDepsArguments) "$(PublishDepsFilePath)"" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json",
|
|
||||||
"channel": "release/2.1",
|
|
||||||
"toolsets": {
|
|
||||||
"visualstudio": {
|
|
||||||
"required": ["Windows"],
|
|
||||||
"includePrerelease": true,
|
|
||||||
"minVersion": "15.0.26730.03",
|
|
||||||
"requiredWorkloads": [
|
|
||||||
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
|
||||||
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win81",
|
|
||||||
"Microsoft.VisualStudio.Component.VC.ATL",
|
|
||||||
"Microsoft.VisualStudio.Component.Windows10SDK.15063.Desktop"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
|
||||||
<metadata>
|
|
||||||
<id>Microsoft.AspNetCore.AspNetCoreModuleV1</id>
|
|
||||||
<title>Microsoft ASP.NET Core Module</title>
|
|
||||||
<version>$VERSION$</version>
|
|
||||||
<authors>Microsoft</authors>
|
|
||||||
<owners>Microsoft</owners>
|
|
||||||
<licenseUrl>https://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
|
||||||
<copyright>© .NET Foundation. All rights reserved.</copyright>
|
|
||||||
<projectUrl>https://www.asp.net/</projectUrl>
|
|
||||||
<iconUrl>https://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
|
|
||||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
|
||||||
<description>ASP.NET Core Module</description>
|
|
||||||
<language>en-US</language>
|
|
||||||
<tags>Microsoft.AspNetCore.AspNetCoreModuleV1</tags>
|
|
||||||
<contentFiles>
|
|
||||||
<files include="any/any/*/*.dll" buildAction="None" copyToOutput="true" flatten="false" />
|
|
||||||
</contentFiles>
|
|
||||||
</metadata>
|
|
||||||
<files>
|
|
||||||
<file src="src\AspNetCoreModuleV1\AspNetCore\bin\$Configuration$\Win32\aspnetcore.dll" target="contentFiles\any\any\x86\aspnetcore.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV1\AspNetCore\bin\$Configuration$\x64\aspnetcore.dll" target="contentFiles\any\any\x64\aspnetcore.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV1\AspNetCore\bin\$Configuration$\x64\*.xml"/>
|
|
||||||
<file src="tools\installancm.ps1"/>
|
|
||||||
<file src="LICENSE.txt"/>
|
|
||||||
<file src="nuget\Microsoft.AspNetCore.AspNetCoreModule.props" target="build\" />
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
|
|
||||||
<metadata>
|
|
||||||
<id>Microsoft.AspNetCore.AspNetCoreModule</id> <!--TODO make this package version V2 when possible -->
|
|
||||||
<title>Microsoft ASP.NET Core Module</title>
|
|
||||||
<version>$VERSION$</version>
|
|
||||||
<authors>Microsoft</authors>
|
|
||||||
<owners>Microsoft</owners>
|
|
||||||
<licenseUrl>https://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
|
||||||
<copyright>© .NET Foundation. All rights reserved.</copyright>
|
|
||||||
<projectUrl>https://www.asp.net/</projectUrl>
|
|
||||||
<iconUrl>https://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
|
|
||||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
|
||||||
<description>ASP.NET Core Module</description>
|
|
||||||
<language>en-US</language>
|
|
||||||
<tags>Microsoft.AspNetCore.AspNetCoreModule</tags>
|
|
||||||
<contentFiles>
|
|
||||||
<files include="any/any/*/*.dll" buildAction="None" copyToOutput="true" flatten="false" />
|
|
||||||
</contentFiles>
|
|
||||||
</metadata>
|
|
||||||
<files>
|
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\Win32\aspnetcore.dll" target="contentFiles\any\any\x86\aspnetcore.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\aspnetcore.dll" target="contentFiles\any\any\x64\aspnetcore.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV2\RequestHandler\bin\$Configuration$\Win32\aspnetcorerh.dll" target="contentFiles\any\any\x86\aspnetcorerh.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV2\RequestHandler\bin\$Configuration$\x64\aspnetcorerh.dll" target="contentFiles\any\any\x64\aspnetcorerh.dll" />
|
|
||||||
<file src="src\AspNetCoreModuleV2\AspNetCore\bin\$Configuration$\x64\*.xml"/>
|
|
||||||
<file src="tools\installancm.ps1"/>
|
|
||||||
<file src="LICENSE.txt"/>
|
|
||||||
<file src="nuget\Microsoft.AspNetCore.AspNetCoreModule.props" target="build\" />
|
|
||||||
</files>
|
|
||||||
</package>
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:25334/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
|
||||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Server.IISIntegration"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IISSample": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "http://localhost:5000",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<Import Project="..\..\build\testsite.props" />
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<AspNetCoreModuleHostingModel>inprocess</AspNetCoreModuleHostingModel>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": true,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:5762/",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"ANCM IIS Express": {
|
|
||||||
"commandName": "Executable",
|
|
||||||
"executablePath": "$(IISExpressPath)",
|
|
||||||
"commandLineArgs": "$(IISExpressArguments)",
|
|
||||||
"nativeDebugging": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
|
||||||
"ANCM_PATH": "$(TargetDir)$(AncmPath)",
|
|
||||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
|
||||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ANCM IIS": {
|
|
||||||
"commandName": "Executable",
|
|
||||||
"executablePath": "$(IISPath)",
|
|
||||||
"commandLineArgs": "$(IISArguments)",
|
|
||||||
"environmentVariables": {
|
|
||||||
"IIS_SITE_PATH": "$(MSBuildThisFileDirectory)",
|
|
||||||
"ANCM_PATH": "$(TargetDir)$(AncmPath)",
|
|
||||||
"LAUNCHER_ARGS": "$(TargetPath)",
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
|
||||||
"LAUNCHER_PATH": "$(DotNetPath)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
|
||||||
using Microsoft.AspNetCore.Server.IISIntegration;
|
|
||||||
|
|
||||||
namespace NativeIISSample
|
|
||||||
{
|
|
||||||
public class Startup
|
|
||||||
{
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAuthenticationSchemeProvider authSchemeProvider)
|
|
||||||
{
|
|
||||||
app.Run(async (context) =>
|
|
||||||
{
|
|
||||||
context.Response.ContentType = "text/plain";
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("Hello World - " + DateTimeOffset.Now + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("Address:" + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("Scheme: " + context.Request.Scheme + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("Host: " + context.Request.Headers["Host"] + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("PathBase: " + context.Request.PathBase.Value + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("Path: " + context.Request.Path.Value + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("Query: " + context.Request.QueryString.Value + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("Connection:" + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("RemoteIp: " + context.Connection.RemoteIpAddress + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("RemotePort: " + context.Connection.RemotePort + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("LocalIp: " + context.Connection.LocalIpAddress + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("LocalPort: " + context.Connection.LocalPort + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync("ClientCert: " + context.Connection.ClientCertificate + Environment.NewLine);
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("User: " + context.User.Identity.Name + Environment.NewLine);
|
|
||||||
var scheme = await authSchemeProvider.GetSchemeAsync(IISDefaults.AuthenticationScheme);
|
|
||||||
await context.Response.WriteAsync("DisplayName: " + scheme?.DisplayName + Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("Headers:" + Environment.NewLine);
|
|
||||||
foreach (var header in context.Request.Headers)
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync(header.Key + ": " + header.Value + Environment.NewLine);
|
|
||||||
}
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("Environment Variables:" + Environment.NewLine);
|
|
||||||
var vars = Environment.GetEnvironmentVariables();
|
|
||||||
foreach (var key in vars.Keys.Cast<string>().OrderBy(key => key, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var value = vars[key];
|
|
||||||
await context.Response.WriteAsync(key + ": " + value + Environment.NewLine);
|
|
||||||
}
|
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
|
||||||
|
|
||||||
// accessing IIS server variables
|
|
||||||
await context.Response.WriteAsync("Server Variables:" + Environment.NewLine);
|
|
||||||
|
|
||||||
if (context.Features.Get<IHttpUpgradeFeature>() != null)
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Websocket feature is enabled.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Websocket feature is disabled.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
var host = new WebHostBuilder()
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseStartup<Startup>()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
host.Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<configuration>
|
|
||||||
<system.webServer>
|
|
||||||
<handlers>
|
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
|
||||||
</handlers>
|
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" stdoutLogEnabled="false" hostingModel="inprocess"/>
|
|
||||||
</system.webServer>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -1,260 +0,0 @@
|
||||||
<?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="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>AspNetCoreModule</RootNamespace>
|
|
||||||
<ProjectName>AspNetCore</ProjectName>
|
|
||||||
<TargetName>aspnetcore</TargetName>
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
|
||||||
</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)'=='Debug|x64'" 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)'=='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="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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
|
||||||
<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 Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<ResourceCompile>
|
|
||||||
<AdditionalIncludeDirectories>..\Commonlib</AdditionalIncludeDirectories>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<ResourceCompile>
|
|
||||||
<AdditionalIncludeDirectories>..\Commonlib</AdditionalIncludeDirectories>
|
|
||||||
</ResourceCompile>
|
|
||||||
</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;ASPNETCOREMODULE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<ResourceCompile>
|
|
||||||
<AdditionalIncludeDirectories>..\Commonlib</AdditionalIncludeDirectories>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level4</WarningLevel>
|
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ASPNETCOREMODULE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<ResourceCompile>
|
|
||||||
<AdditionalIncludeDirectories>..\Commonlib</AdditionalIncludeDirectories>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="Inc\applicationinfo.h" />
|
|
||||||
<ClInclude Include="Inc\appoffline.h" />
|
|
||||||
<ClInclude Include="inc\globalmodule.h" />
|
|
||||||
<ClInclude Include="Inc\applicationmanager.h" />
|
|
||||||
<ClInclude Include="Inc\filewatcher.h" />
|
|
||||||
<ClInclude Include="Inc\proxymodule.h" />
|
|
||||||
<ClInclude Include="Src\precomp.hxx" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="Src\applicationinfo.cpp" />
|
|
||||||
<ClCompile Include="Src\applicationmanager.cxx" />
|
|
||||||
<ClCompile Include="Src\dllmain.cpp" />
|
|
||||||
<ClCompile Include="Src\filewatcher.cxx" />
|
|
||||||
<ClCompile Include="src\globalmodule.cpp" />
|
|
||||||
<ClCompile Include="Src\proxymodule.cxx" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\CommonLib\CommonLib.vcxproj">
|
|
||||||
<Project>{55494e58-e061-4c4c-a0a8-837008e72f85}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\IISLib\IISLib.vcxproj">
|
|
||||||
<Project>{09d9d1d6-2951-4e14-bc35-76a23cf9391a}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="ancm.mof" />
|
|
||||||
<None Include="Source.def" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="aspnetcoremodule.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="aspnetcore_schema.xml">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="ancm.mof">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Xml Include="aspnetcore_schema.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="..\..\..\build\native.targets" />
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,251 +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
|
|
||||||
#define API_BUFFER_TOO_SMALL 0x80008098
|
|
||||||
|
|
||||||
extern BOOL g_fRecycleProcessCalled;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// ExtractApplication will increase the reference counter of the application
|
|
||||||
// Caller is responsible for dereference the application.
|
|
||||||
// Otherwise memory leak
|
|
||||||
//
|
|
||||||
VOID
|
|
||||||
ExtractApplication(APPLICATION** ppApplication)
|
|
||||||
{
|
|
||||||
AcquireSRWLockShared(&m_srwLock);
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
m_pApplication->ReferenceApplication();
|
|
||||||
}
|
|
||||||
*ppApplication = m_pApplication;
|
|
||||||
ReleaseSRWLockShared(&m_srwLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
RecycleApplication();
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ShutDownApplication();
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
EnsureApplicationCreated();
|
|
||||||
|
|
||||||
PFN_ASPNETCORE_CREATE_REQUEST_HANDLER
|
|
||||||
QueryCreateRequestHandler()
|
|
||||||
{
|
|
||||||
return m_pfnAspNetCoreCreateRequestHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
HRESULT FindRequestHandlerAssembly();
|
|
||||||
HRESULT FindNativeAssemblyFromGlobalLocation(STRU* struFilename);
|
|
||||||
HRESULT FindNativeAssemblyFromHostfxr(STRU* struFilename);
|
|
||||||
|
|
||||||
static VOID DoRecycleApplication(LPVOID lpParam);
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
ReferenceCopyToTable(
|
|
||||||
APPLICATION_INFO * pEntry,
|
|
||||||
PVOID pvData
|
|
||||||
)
|
|
||||||
{
|
|
||||||
APPLICATION_INFO_HASH *pHash = static_cast<APPLICATION_INFO_HASH *>(pvData);
|
|
||||||
DBG_ASSERT(pHash);
|
|
||||||
pHash->InsertRecord(pEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
APPLICATION_INFO_HASH(const APPLICATION_INFO_HASH &);
|
|
||||||
void operator=(const APPLICATION_INFO_HASH &);
|
|
||||||
};
|
|
||||||
|
|
@ -1,154 +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
|
|
||||||
|
|
||||||
#define DEFAULT_HASH_BUCKETS 17
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
//
|
|
||||||
|
|
||||||
struct CONFIG_CHANGE_CONTEXT
|
|
||||||
{
|
|
||||||
PCWSTR pstrPath;
|
|
||||||
MULTISZ MultiSz;
|
|
||||||
};
|
|
||||||
|
|
||||||
class APPLICATION_MANAGER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
APPLICATION_MANAGER*
|
|
||||||
GetInstance(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ( sm_pApplicationManager == NULL )
|
|
||||||
{
|
|
||||||
sm_pApplicationManager = new APPLICATION_MANAGER();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sm_pApplicationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
Cleanup(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if(sm_pApplicationManager != NULL)
|
|
||||||
{
|
|
||||||
delete sm_pApplicationManager;
|
|
||||||
sm_pApplicationManager = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
FindConfigChangedApplication(
|
|
||||||
_In_ APPLICATION_INFO * pEntry,
|
|
||||||
_In_ PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
ShutdownApplication(
|
|
||||||
_In_ APPLICATION_INFO * pEntry,
|
|
||||||
_In_ PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetOrCreateApplicationInfo(
|
|
||||||
_In_ IHttpServer* pServer,
|
|
||||||
_In_ ASPNETCORE_CONFIG* pConfig,
|
|
||||||
_Out_ APPLICATION_INFO ** ppApplicationInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
RecycleApplicationFromManager(
|
|
||||||
_In_ LPCWSTR pszApplicationId
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ShutDown();
|
|
||||||
|
|
||||||
~APPLICATION_MANAGER()
|
|
||||||
{
|
|
||||||
if (m_pFileWatcher != NULL)
|
|
||||||
{
|
|
||||||
delete m_pFileWatcher;
|
|
||||||
m_pFileWatcher = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pApplicationInfoHash != NULL)
|
|
||||||
{
|
|
||||||
m_pApplicationInfoHash->Clear();
|
|
||||||
delete m_pApplicationInfoHash;
|
|
||||||
m_pApplicationInfoHash = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE_WATCHER*
|
|
||||||
GetFileWatcher()
|
|
||||||
{
|
|
||||||
return m_pFileWatcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT Initialize()
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if(m_pApplicationInfoHash == NULL)
|
|
||||||
{
|
|
||||||
m_pApplicationInfoHash = new APPLICATION_INFO_HASH();
|
|
||||||
if(m_pApplicationInfoHash == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = m_pApplicationInfoHash->Initialize(DEFAULT_HASH_BUCKETS);
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_pFileWatcher == NULL )
|
|
||||||
{
|
|
||||||
m_pFileWatcher = new FILE_WATCHER;
|
|
||||||
if(m_pFileWatcher == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pFileWatcher->Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//
|
|
||||||
// we currently limit the size of m_pstrErrorInfo to 5000, be careful if you want to change its payload
|
|
||||||
//
|
|
||||||
APPLICATION_MANAGER() : m_pApplicationInfoHash(NULL),
|
|
||||||
m_pFileWatcher(NULL),
|
|
||||||
m_hostingModel(HOSTING_UNKNOWN)
|
|
||||||
{
|
|
||||||
InitializeSRWLock(&m_srwLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE_WATCHER *m_pFileWatcher;
|
|
||||||
APPLICATION_INFO_HASH *m_pApplicationInfoHash;
|
|
||||||
static APPLICATION_MANAGER *sm_pApplicationManager;
|
|
||||||
SRWLOCK m_srwLock;
|
|
||||||
APP_HOSTING_MODEL m_hostingModel;
|
|
||||||
};
|
|
||||||
|
|
@ -1,101 +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 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 (HRESULT_FROM_WIN32(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;
|
|
||||||
};
|
|
||||||
|
|
@ -1,127 +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
|
|
||||||
|
|
||||||
#define FILE_WATCHER_SHUTDOWN_KEY (ULONG_PTR)(-1)
|
|
||||||
#define FILE_WATCHER_ENTRY_BUFFER_SIZE 4096
|
|
||||||
#ifndef CONTAINING_RECORD
|
|
||||||
//
|
|
||||||
// Calculate the address of the base of the structure given its type, and an
|
|
||||||
// address of a field within the structure.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define CONTAINING_RECORD(address, type, field) \
|
|
||||||
((type *)((PCHAR)(address)-(ULONG_PTR)(&((type *)0)->field)))
|
|
||||||
|
|
||||||
#endif // !CONTAINING_RECORD
|
|
||||||
#define FILE_NOTIFY_VALID_MASK 0x00000fff
|
|
||||||
#define FILE_WATCHER_ENTRY_SIGNATURE ((DWORD) 'FWES')
|
|
||||||
#define FILE_WATCHER_ENTRY_SIGNATURE_FREE ((DWORD) 'sewf')
|
|
||||||
|
|
||||||
class APPLICATION_INFO;
|
|
||||||
|
|
||||||
class FILE_WATCHER{
|
|
||||||
public:
|
|
||||||
|
|
||||||
FILE_WATCHER();
|
|
||||||
|
|
||||||
~FILE_WATCHER();
|
|
||||||
|
|
||||||
HRESULT Create();
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
QueryCompletionPort(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return m_hCompletionPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
DWORD
|
|
||||||
WINAPI ChangeNotificationThread(LPVOID);
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
WINAPI FileWatcherCompletionRoutine
|
|
||||||
(
|
|
||||||
DWORD dwCompletionStatus,
|
|
||||||
DWORD cbCompletion,
|
|
||||||
OVERLAPPED * pOverlapped
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HANDLE m_hCompletionPort;
|
|
||||||
HANDLE m_hChangeNotificationThread;
|
|
||||||
volatile BOOL m_fThreadExit;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FILE_WATCHER_ENTRY
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor);
|
|
||||||
|
|
||||||
OVERLAPPED _overlapped;
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
Create(
|
|
||||||
_In_ PCWSTR pszDirectoryToMonitor,
|
|
||||||
_In_ PCWSTR pszFileNameToMonitor,
|
|
||||||
_In_ APPLICATION_INFO* pApplicationInfo,
|
|
||||||
_In_ HANDLE hImpersonationToken
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ReferenceFileWatcherEntry() const
|
|
||||||
{
|
|
||||||
InterlockedIncrement(&_cRefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DereferenceFileWatcherEntry() const
|
|
||||||
{
|
|
||||||
if (InterlockedDecrement(&_cRefs) == 0)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryIsValid() const
|
|
||||||
{
|
|
||||||
return _fIsValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MarkEntryInValid()
|
|
||||||
{
|
|
||||||
_fIsValid = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT Monitor();
|
|
||||||
|
|
||||||
VOID StopMonitor();
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
HandleChangeCompletion(
|
|
||||||
_In_ DWORD dwCompletionStatus,
|
|
||||||
_In_ DWORD cbCompletion
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~FILE_WATCHER_ENTRY();
|
|
||||||
|
|
||||||
DWORD _dwSignature;
|
|
||||||
BUFFER _buffDirectoryChanges;
|
|
||||||
HANDLE _hImpersonationToken;
|
|
||||||
HANDLE _hDirectory;
|
|
||||||
FILE_WATCHER* _pFileMonitor;
|
|
||||||
APPLICATION_INFO* _pApplicationInfo;
|
|
||||||
STRU _strFileName;
|
|
||||||
STRU _strDirectoryName;
|
|
||||||
LONG _lStopMonitorCalled;
|
|
||||||
mutable LONG _cRefs;
|
|
||||||
BOOL _fIsValid;
|
|
||||||
SRWLOCK _srwLock;
|
|
||||||
};
|
|
||||||
|
|
@ -1,49 +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.
|
|
||||||
|
|
||||||
#ifndef __FX_VER_H__
|
|
||||||
#define __FX_VER_H__
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// Note: This is not SemVer (esp., in comparing pre-release part, fx_ver_t does not
|
|
||||||
// compare multiple dot separated identifiers individually.) ex: 1.0.0-beta.2 vs. 1.0.0-beta.11
|
|
||||||
struct fx_ver_t
|
|
||||||
{
|
|
||||||
fx_ver_t(int major, int minor, int patch);
|
|
||||||
fx_ver_t(int major, int minor, int patch, const std::wstring& pre);
|
|
||||||
fx_ver_t(int major, int minor, int patch, const std::wstring& pre, const std::wstring& build);
|
|
||||||
|
|
||||||
int get_major() const { return m_major; }
|
|
||||||
int get_minor() const { return m_minor; }
|
|
||||||
int get_patch() const { return m_patch; }
|
|
||||||
|
|
||||||
void set_major(int m) { m_major = m; }
|
|
||||||
void set_minor(int m) { m_minor = m; }
|
|
||||||
void set_patch(int p) { m_patch = p; }
|
|
||||||
|
|
||||||
bool is_prerelease() const { return !m_pre.empty(); }
|
|
||||||
|
|
||||||
std::wstring as_str() const;
|
|
||||||
std::wstring prerelease_glob() const;
|
|
||||||
std::wstring patch_glob() const;
|
|
||||||
|
|
||||||
bool operator ==(const fx_ver_t& b) const;
|
|
||||||
bool operator !=(const fx_ver_t& b) const;
|
|
||||||
bool operator <(const fx_ver_t& b) const;
|
|
||||||
bool operator >(const fx_ver_t& b) const;
|
|
||||||
bool operator <=(const fx_ver_t& b) const;
|
|
||||||
bool operator >=(const fx_ver_t& b) const;
|
|
||||||
|
|
||||||
static bool parse(const std::wstring& ver, fx_ver_t* fx_ver, bool parse_only_production = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_major;
|
|
||||||
int m_minor;
|
|
||||||
int m_patch;
|
|
||||||
std::wstring m_pre;
|
|
||||||
std::wstring m_build;
|
|
||||||
|
|
||||||
static int compare(const fx_ver_t&a, const fx_ver_t& b);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __FX_VER_H__
|
|
||||||
|
|
@ -1,37 +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 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,64 +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
|
|
||||||
|
|
||||||
extern HTTP_MODULE_ID g_pModuleId;
|
|
||||||
extern IHttpServer *g_pHttpServer;
|
|
||||||
extern HMODULE g_hAspnetCoreRH;
|
|
||||||
|
|
||||||
class ASPNET_CORE_PROXY_MODULE : public CHttpModule
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
ASPNET_CORE_PROXY_MODULE();
|
|
||||||
|
|
||||||
~ASPNET_CORE_PROXY_MODULE();
|
|
||||||
|
|
||||||
void * operator new(size_t size, IModuleAllocator * pPlacement)
|
|
||||||
{
|
|
||||||
return pPlacement->AllocateMemory(static_cast<DWORD>(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
operator delete(
|
|
||||||
void *
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
__override
|
|
||||||
REQUEST_NOTIFICATION_STATUS
|
|
||||||
OnExecuteRequestHandler(
|
|
||||||
IHttpContext * pHttpContext,
|
|
||||||
IHttpEventProvider * pProvider
|
|
||||||
);
|
|
||||||
|
|
||||||
__override
|
|
||||||
REQUEST_NOTIFICATION_STATUS
|
|
||||||
OnAsyncCompletion(
|
|
||||||
IHttpContext * pHttpContext,
|
|
||||||
DWORD dwNotification,
|
|
||||||
BOOL fPostNotification,
|
|
||||||
IHttpEventProvider * pProvider,
|
|
||||||
IHttpCompletionInfo * pCompletionInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
APPLICATION_INFO *m_pApplicationInfo;
|
|
||||||
APPLICATION *m_pApplication;
|
|
||||||
REQUEST_HANDLER *m_pHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ASPNET_CORE_PROXY_MODULE_FACTORY : public IHttpModuleFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HRESULT
|
|
||||||
GetHttpModule(
|
|
||||||
CHttpModule ** ppModule,
|
|
||||||
IModuleAllocator * pAllocator
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
Terminate();
|
|
||||||
};
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
LIBRARY aspnetcore
|
|
||||||
|
|
||||||
EXPORTS
|
|
||||||
RegisterModule
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
||||||
#pragma classflags("forceupdate")
|
|
||||||
#pragma namespace ("\\\\.\\Root\\WMI")
|
|
||||||
#pragma autorecover
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AspNetCore module trace events layout
|
|
||||||
* Uncomment the following class to run mof2trace to generate header file
|
|
||||||
* comment it back before checking it in */
|
|
||||||
[Dynamic,
|
|
||||||
Description("IIS: WWW Server"),
|
|
||||||
Guid("{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}"),
|
|
||||||
locale("MS\\0x409")]
|
|
||||||
class IIS_Trace:EventTrace
|
|
||||||
{
|
|
||||||
[Description ("Enable Flags") : amended,
|
|
||||||
ValueDescriptions{
|
|
||||||
"AspNetCore module events" } : amended,
|
|
||||||
DefineValues{
|
|
||||||
"ETW_IIS_ANCM" },
|
|
||||||
Values{
|
|
||||||
"ANCM" },
|
|
||||||
ValueMap{
|
|
||||||
"0x10000" }
|
|
||||||
]
|
|
||||||
uint32 Flags;
|
|
||||||
|
|
||||||
[Description ("Levels") : amended,
|
|
||||||
ValueDescriptions{
|
|
||||||
"Abnormal exit or termination",
|
|
||||||
"Severe errors",
|
|
||||||
"Warnings",
|
|
||||||
"Information",
|
|
||||||
"Detailed information" } : amended,
|
|
||||||
DefineValues{
|
|
||||||
"TRACE_LEVEL_FATAL",
|
|
||||||
"TRACE_LEVEL_ERROR",
|
|
||||||
"TRACE_LEVEL_WARNING",
|
|
||||||
"TRACE_LEVEL_INFORMATION",
|
|
||||||
"TRACE_LEVEL_VERBOSE" },
|
|
||||||
Values{
|
|
||||||
"Fatal",
|
|
||||||
"Error",
|
|
||||||
"Warning",
|
|
||||||
"Information",
|
|
||||||
"Verbose" },
|
|
||||||
ValueMap{
|
|
||||||
"0x1",
|
|
||||||
"0x2",
|
|
||||||
"0x3",
|
|
||||||
"0x4",
|
|
||||||
"0x5" },
|
|
||||||
ValueType("index")
|
|
||||||
]
|
|
||||||
uint32 Level;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("ANCM runtime events") : amended,
|
|
||||||
Guid("{82ADEAD7-12B2-4781-BDCA-5A4B6C757191}"),
|
|
||||||
EventVersion(1),
|
|
||||||
DisplayName("ANCM"),
|
|
||||||
EventANCMRuntime,
|
|
||||||
locale("MS\\0x409")
|
|
||||||
]
|
|
||||||
class ANCM_Events:IIS_Trace
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Start application success") : amended,
|
|
||||||
EventType(1),
|
|
||||||
EventLevel(4),
|
|
||||||
EventTypeName("ANCM_START_APPLICATION_SUCCESS") : amended
|
|
||||||
]
|
|
||||||
class ANCMAppStart:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
[WmiDataId(2),
|
|
||||||
Description("Application Description") : amended,
|
|
||||||
StringTermination("NullTerminated"),
|
|
||||||
format("w"),
|
|
||||||
read]
|
|
||||||
string AppDescription;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Start application failed") : amended,
|
|
||||||
EventType(2),
|
|
||||||
EventLevel(2),
|
|
||||||
EventTypeName("ANCM_START_APPLICATION_FAIL") : amended
|
|
||||||
]
|
|
||||||
class ANCMAppStartFail:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
[WmiDataId(2),
|
|
||||||
Description("Application Start Failure Description") : amended,
|
|
||||||
StringTermination("NullTerminated"),
|
|
||||||
format("w"),
|
|
||||||
read]
|
|
||||||
string FailureDescription;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Start forwarding request") : amended,
|
|
||||||
EventType(3),
|
|
||||||
EventLevel(4),
|
|
||||||
EventTypeName("ANCM_REQUEST_FORWARD_START") : amended
|
|
||||||
]
|
|
||||||
class ANCMForwardStart:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Finish forwarding request") : amended,
|
|
||||||
EventType(4),
|
|
||||||
EventLevel(4),
|
|
||||||
EventTypeName("ANCM_REQUEST_FORWARD_END") : amended
|
|
||||||
]
|
|
||||||
class ANCMForwardEnd:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Forwarding request failure") : amended,
|
|
||||||
EventType(5),
|
|
||||||
EventLevel(2),
|
|
||||||
EventTypeName("ANCM_REQUEST_FORWARD_FAIL") : amended
|
|
||||||
]
|
|
||||||
class ANCMForwardFail:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
[WmiDataId(2),
|
|
||||||
Description("Error code") : amended,
|
|
||||||
format("x"),
|
|
||||||
read]
|
|
||||||
uint32 ErrorCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Receiving callback from WinHttp") : amended,
|
|
||||||
EventType(6),
|
|
||||||
EventLevel(4),
|
|
||||||
EventTypeName("ANCM_WINHTTP_CALLBACK") : amended
|
|
||||||
]
|
|
||||||
class ANCMWinHttpCallBack:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
[WmiDataId(2),
|
|
||||||
Description("InternetStatus") : amended,
|
|
||||||
format("x"),
|
|
||||||
read]
|
|
||||||
uint32 InternetStatus;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Dynamic,
|
|
||||||
Description("Inprocess executing request failure") : amended,
|
|
||||||
EventType(7),
|
|
||||||
EventLevel(2),
|
|
||||||
EventTypeName("ANCM_EXECUTE_REQUEST_FAIL") : amended
|
|
||||||
]
|
|
||||||
class ANCMExecuteFailed:ANCM_Events
|
|
||||||
{
|
|
||||||
[WmiDataId(1),
|
|
||||||
Description("Context ID") : amended,
|
|
||||||
extension("Guid"),
|
|
||||||
ActivityID,
|
|
||||||
read]
|
|
||||||
object ContextId;
|
|
||||||
[WmiDataId(2),
|
|
||||||
Description("InternetStatus") : amended,
|
|
||||||
format("x"),
|
|
||||||
read]
|
|
||||||
uint32 ErrorCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<!--
|
|
||||||
|
|
||||||
IIS Asp.Net Core Extension Schema
|
|
||||||
|
|
||||||
** Please DO NOT edit this file yourself. **
|
|
||||||
|
|
||||||
If you want to add configuration sections to the schema, you may place
|
|
||||||
them in .xml files similar to this one, in this directory. They will be
|
|
||||||
picked up automatically on startup.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<configSchema>
|
|
||||||
<sectionSchema name="system.webServer/aspNetCore">
|
|
||||||
<attribute name="processPath" type="string" expanded="true"/>
|
|
||||||
<attribute name="arguments" type="string" expanded="true" defaultValue=""/>
|
|
||||||
<attribute name="startupTimeLimit" type="uint" defaultValue="120" validationType="integerRange" validationParameter="0,3600"/>
|
|
||||||
<!-- in seconds -->
|
|
||||||
<attribute name="shutdownTimeLimit" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,600"/>
|
|
||||||
<!-- in seconds -->
|
|
||||||
<attribute name="rapidFailsPerMinute" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,100"/>
|
|
||||||
<attribute name="requestTimeout" type="timeSpan" defaultValue="00:02:00" validationType="timeSpanRange" validationParameter="0,1296000,1"/>
|
|
||||||
<attribute name="stdoutLogEnabled" type="bool" defaultValue="false" />
|
|
||||||
<attribute name="stdoutLogFile" type="string" defaultValue=".\aspnetcore-stdout" expanded="true"/>
|
|
||||||
<attribute name="processesPerApplication" type="uint" defaultValue="1" validationType="integerRange" validationParameter="1,100"/>
|
|
||||||
<attribute name="forwardWindowsAuthToken" type="bool" defaultValue="true" />
|
|
||||||
<attribute name="disableStartUpErrorPage" type="bool" defaultValue="false" />
|
|
||||||
<attribute name="hostingModel" type="string" />
|
|
||||||
<element name="recycleOnFileChange">
|
|
||||||
<collection addElement="file" clearElement="clear">
|
|
||||||
<attribute name="path" type="string" required="true" validationType="nonEmptyString" expanded="true"/>
|
|
||||||
</collection>
|
|
||||||
</element>
|
|
||||||
<element name="environmentVariables">
|
|
||||||
<collection addElement="environmentVariable" clearElement="clear" >
|
|
||||||
<attribute name="name" type="string" required="true" validationType="nonEmptyString"/>
|
|
||||||
<attribute name="value" type="string" required="true"/>
|
|
||||||
</collection>
|
|
||||||
</element>
|
|
||||||
<element name="handlerSettings">
|
|
||||||
<collection addElement="handlerSetting" clearElement="clear" >
|
|
||||||
<attribute name="name" type="string" required="true" validationType="nonEmptyString"/>
|
|
||||||
<attribute name="value" type="string" required="true"/>
|
|
||||||
</collection>
|
|
||||||
</element>
|
|
||||||
</sectionSchema>
|
|
||||||
</configSchema>
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#include <windows.h>
|
|
||||||
#include "version.h"
|
|
||||||
#include "..\CommonLib\Aspnetcore_msg.rc"
|
|
||||||
#include "..\CommonLib\resources.h"
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// English (United States) resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|
||||||
|
|
||||||
#define FileDescription "IIS AspNetCore Module. Commit: " CommitHash
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// 11
|
|
||||||
//
|
|
||||||
|
|
||||||
//1 11
|
|
||||||
//BEGIN
|
|
||||||
// 0x0001, 0x0000, 0x03e8, 0x0000, 0x03ed, 0x0000, 0x0010, 0x0000, 0x0010,
|
|
||||||
// 0x0001, 0x0025, 0x0031, 0x000d, 0x000a, 0x0000, 0x0000, 0x0010, 0x0001,
|
|
||||||
// 0x0025, 0x0031, 0x000d, 0x000a, 0x0000, 0x0000, 0x0010, 0x0001, 0x0025,
|
|
||||||
// 0x0031, 0x000d, 0x000a, 0x0000, 0x0000, 0x0010, 0x0001, 0x0025, 0x0031,
|
|
||||||
// 0x000d, 0x000a, 0x0000, 0x0000, 0x0010, 0x0001, 0x0025, 0x0031, 0x000d,
|
|
||||||
// 0x000a, 0x0000, 0x0000, 0x0010, 0x0001, 0x0025, 0x0031, 0x000d, 0x000a,
|
|
||||||
// 0x0000, 0x0000
|
|
||||||
//END
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// TEXTINCLUDE
|
|
||||||
//
|
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"..\CommonLib\resources.h\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
|
||||||
BEGIN
|
|
||||||
"\r\n"
|
|
||||||
"\0"
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Version
|
|
||||||
//
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION FileVersion
|
|
||||||
PRODUCTVERSION ProductVersion
|
|
||||||
FILEFLAGSMASK 0x3fL
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 0x1L
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
|
||||||
FILEOS 0x40004L
|
|
||||||
FILETYPE 0x2L
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "CompanyName", "Microsoft Corporation"
|
|
||||||
VALUE "FileDescription", FileDescription
|
|
||||||
VALUE "FileVersion", FileVersionStr
|
|
||||||
VALUE "InternalName", "aspnetcore"
|
|
||||||
VALUE "LegalCopyright", "Copyright (C) Microsoft Corporation"
|
|
||||||
VALUE "OriginalFilename", "aspnetcore.dll"
|
|
||||||
VALUE "ProductName", "ASP.NET Core Module"
|
|
||||||
VALUE "ProductVersion", ProductVersionStr
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// String Table
|
|
||||||
//
|
|
||||||
|
|
||||||
STRINGTABLE
|
|
||||||
BEGIN
|
|
||||||
IDS_INVALID_PROPERTY "Property name '%s' in system.webServer/aspNetCore section has invalid value '%s' which does not conform to the prescribed format"
|
|
||||||
IDS_SERVER_ERROR "There was a connection error while trying to route the request."
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // English (United States) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
@ -1,650 +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_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->DereferenceFileWatcherEntry();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Called by the file watcher when the app_offline.htm's file status has been changed.
|
|
||||||
// If it finds it, we will call recycle on the application.
|
|
||||||
//
|
|
||||||
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;
|
|
||||||
|
|
||||||
ReferenceApplicationInfo();
|
|
||||||
|
|
||||||
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFilePath.QueryStr()) &&
|
|
||||||
GetLastError() == ERROR_FILE_NOT_FOUND)
|
|
||||||
{
|
|
||||||
// Check if app offline was originally present.
|
|
||||||
// if it was, log that app_offline has been dropped.
|
|
||||||
if (m_fAppOfflineFound)
|
|
||||||
{
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED_MSG)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_INFORMATION_TYPE,
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fAppOfflineFound = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fAppOfflineFound = TRUE;
|
|
||||||
|
|
||||||
// recycle the application
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_MSG,
|
|
||||||
m_pApplication->QueryConfig()->QueryApplicationPath()->QueryStr())))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_INFORMATION_TYPE,
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_APPOFFLINE,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
|
|
||||||
RecycleApplication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DereferenceApplicationInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
APPLICATION_INFO::EnsureApplicationCreated()
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
BOOL fLocked = FALSE;
|
|
||||||
APPLICATION* pApplication = NULL;
|
|
||||||
STACK_STRU(struFileName, 300); // >MAX_PATH
|
|
||||||
STRU struHostFxrDllLocation;
|
|
||||||
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pApplication == NULL)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
fLocked = TRUE;
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// in case of app offline, we don't want to create a new application now
|
|
||||||
//
|
|
||||||
if (!m_fAppOfflineFound)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Move the request handler check inside of the lock
|
|
||||||
// such that only one request finds and loads it.
|
|
||||||
// FindRequestHandlerAssembly obtains a global lock, but after releasing the lock,
|
|
||||||
// there is a period where we could call
|
|
||||||
|
|
||||||
hr = FindRequestHandlerAssembly();
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pConfiguration->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
|
||||||
{
|
|
||||||
if (FAILED(hr = FindNativeAssemblyFromHostfxr(&struFileName)))
|
|
||||||
{
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_INPROCESS_RH_MISSING_MSG)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_INFORMATION_TYPE,
|
|
||||||
ASPNETCORE_EVENT_INPROCESS_RH_MISSING,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FAILED(hr = FindNativeAssemblyFromGlobalLocation(&struFileName)))
|
|
||||||
{
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_INFORMATION_TYPE,
|
|
||||||
ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
if (FAILED(hr = struFilename->Resize(dwSize + 20)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!fDone)
|
|
||||||
{
|
|
||||||
DWORD dwReturnedSize = GetModuleFileNameW(g_hModule, 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
|
|
||||||
if (FAILED(hr = struFilename->Resize(dwSize + 20))) // + 20 for aspnetcorerh.dll
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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(L"\\")) ||
|
|
||||||
FAILED(hr = struFilename->Append(g_pwzAspnetcoreRequestHandlerName)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tries to find aspnetcorerh.dll from the application
|
|
||||||
// Calls into hostfxr.dll to find it.
|
|
||||||
// Will leave hostfxr.dll loaded as it will be used again to call hostfxr_main.
|
|
||||||
//
|
|
||||||
HRESULT
|
|
||||||
APPLICATION_INFO::FindNativeAssemblyFromHostfxr(
|
|
||||||
STRU* struFilename
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU struApplicationFullPath;
|
|
||||||
STRU struNativeSearchPaths;
|
|
||||||
STRU struNativeDllLocation;
|
|
||||||
HMODULE hmHostFxrDll = NULL;
|
|
||||||
INT intHostFxrExitCode = 0;
|
|
||||||
INT intIndex = -1;
|
|
||||||
INT intPrevIndex = 0;
|
|
||||||
BOOL fFound = FALSE;
|
|
||||||
DWORD dwBufferSize = 1024 * 10;
|
|
||||||
DWORD dwRequiredBufferSize = 0;
|
|
||||||
|
|
||||||
DBG_ASSERT(struFileName != NULL);
|
|
||||||
|
|
||||||
hmHostFxrDll = LoadLibraryW(m_pConfiguration->QueryHostFxrFullPath());
|
|
||||||
|
|
||||||
if (hmHostFxrDll == NULL)
|
|
||||||
{
|
|
||||||
// Could not load hostfxr
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hostfxr_get_native_search_directories_fn pFnHostFxrSearchDirectories = (hostfxr_get_native_search_directories_fn)
|
|
||||||
GetProcAddress(hmHostFxrDll, "hostfxr_get_native_search_directories");
|
|
||||||
|
|
||||||
if (pFnHostFxrSearchDirectories == NULL)
|
|
||||||
{
|
|
||||||
// Host fxr version is incorrect (need a higher version).
|
|
||||||
// TODO log error
|
|
||||||
hr = E_FAIL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struNativeSearchPaths.Resize(dwBufferSize)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
intHostFxrExitCode = pFnHostFxrSearchDirectories(
|
|
||||||
m_pConfiguration->QueryHostFxrArgCount(),
|
|
||||||
m_pConfiguration->QueryHostFxrArguments(),
|
|
||||||
struNativeSearchPaths.QueryStr(),
|
|
||||||
dwBufferSize,
|
|
||||||
&dwRequiredBufferSize
|
|
||||||
);
|
|
||||||
|
|
||||||
if (intHostFxrExitCode == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (dwRequiredBufferSize > dwBufferSize)
|
|
||||||
{
|
|
||||||
dwBufferSize = dwRequiredBufferSize + 1; // for null terminator
|
|
||||||
|
|
||||||
if (FAILED(hr = struNativeSearchPaths.Resize(dwBufferSize)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = E_FAIL;
|
|
||||||
// Log "Error finding native search directories from aspnetcore application.
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struNativeSearchPaths.SyncWithBuffer()))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
fFound = FALSE;
|
|
||||||
|
|
||||||
// The native search directories are semicolon delimited.
|
|
||||||
// Split on semicolons, append aspnetcorerh.dll, and check if the file exists.
|
|
||||||
while ((intIndex = struNativeSearchPaths.IndexOf(L";", intPrevIndex)) != -1)
|
|
||||||
{
|
|
||||||
if (FAILED(hr = struNativeDllLocation.Copy(&struNativeSearchPaths.QueryStr()[intPrevIndex], intIndex - intPrevIndex)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!struNativeDllLocation.EndsWith(L"\\"))
|
|
||||||
{
|
|
||||||
if (FAILED(hr = struNativeDllLocation.Append(L"\\")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struNativeDllLocation.Append(g_pwzAspnetcoreRequestHandlerName)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UTILITY::CheckIfFileExists(struNativeDllLocation.QueryStr()))
|
|
||||||
{
|
|
||||||
if (FAILED(hr = struFilename->Copy(struNativeDllLocation)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
fFound = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
intPrevIndex = intIndex + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFound)
|
|
||||||
{
|
|
||||||
hr = E_FAIL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
if (FAILED(hr) && hmHostFxrDll != NULL)
|
|
||||||
{
|
|
||||||
FreeLibrary(hmHostFxrDll);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
APPLICATION_INFO::RecycleApplication()
|
|
||||||
{
|
|
||||||
APPLICATION* pApplication = NULL;
|
|
||||||
HANDLE hThread = INVALID_HANDLE_VALUE;
|
|
||||||
BOOL fLockAcquired = FALSE;
|
|
||||||
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
fLockAcquired = TRUE;
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
pApplication = m_pApplication;
|
|
||||||
if (pApplication->QueryConfig()->QueryHostingModel() == HOSTING_OUT_PROCESS)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// For inprocess, need to set m_pApplication to NULL first to
|
|
||||||
// avoid mapping new request to the recycled application.
|
|
||||||
// Outofprocess application instance will be created for new request
|
|
||||||
// For inprocess, as recycle will lead to shutdown later, leave m_pApplication
|
|
||||||
// to not block incoming requests till worker process shutdown
|
|
||||||
//
|
|
||||||
m_pApplication = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// For inprocess, need hold the application till shutdown is called
|
|
||||||
// Bump the reference counter as DoRecycleApplication will do dereference
|
|
||||||
//
|
|
||||||
pApplication->ReferenceApplication();
|
|
||||||
}
|
|
||||||
|
|
||||||
hThread = CreateThread(
|
|
||||||
NULL, // default security attributes
|
|
||||||
0, // default stack size
|
|
||||||
(LPTHREAD_START_ROUTINE)DoRecycleApplication,
|
|
||||||
pApplication, // thread function arguments
|
|
||||||
0, // default creation flags
|
|
||||||
NULL); // receive thread identifier
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hThread == NULL)
|
|
||||||
{
|
|
||||||
if (!g_fRecycleProcessCalled)
|
|
||||||
{
|
|
||||||
g_fRecycleProcessCalled = TRUE;
|
|
||||||
g_pHttpServer->RecycleProcess(L"On Demand by AspNetCore Module for recycle application failure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Closing a thread handle does not terminate the associated thread or remove the thread object.
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLockAcquired)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
APPLICATION_INFO::DoRecycleApplication(
|
|
||||||
LPVOID lpParam)
|
|
||||||
{
|
|
||||||
APPLICATION* pApplication = static_cast<APPLICATION*>(lpParam);
|
|
||||||
|
|
||||||
// No lock required
|
|
||||||
|
|
||||||
if (pApplication != NULL)
|
|
||||||
{
|
|
||||||
// Recycle will call shutdown for out of process
|
|
||||||
pApplication->Recycle();
|
|
||||||
|
|
||||||
// Decrement the ref count as we reference it in RecycleApplication.
|
|
||||||
pApplication->DereferenceApplication();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
APPLICATION_INFO::ShutDownApplication()
|
|
||||||
{
|
|
||||||
APPLICATION* pApplication = NULL;
|
|
||||||
BOOL fLockAcquired = FALSE;
|
|
||||||
|
|
||||||
// pApplication can be NULL due to app_offline
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
fLockAcquired = TRUE;
|
|
||||||
if (m_pApplication != NULL)
|
|
||||||
{
|
|
||||||
pApplication = m_pApplication;
|
|
||||||
|
|
||||||
// Set m_pApplication to NULL first to prevent anyone from using it
|
|
||||||
m_pApplication = NULL;
|
|
||||||
pApplication->ShutDown();
|
|
||||||
pApplication->DereferenceApplication();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fLockAcquired)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,458 +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"
|
|
||||||
|
|
||||||
// The application manager is a singleton across ANCM.
|
|
||||||
APPLICATION_MANAGER* APPLICATION_MANAGER::sm_pApplicationManager = NULL;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Retrieves the application info from the application manager
|
|
||||||
// Will create the application info if it isn't initalized
|
|
||||||
//
|
|
||||||
HRESULT
|
|
||||||
APPLICATION_MANAGER::GetOrCreateApplicationInfo(
|
|
||||||
_In_ IHttpServer* pServer,
|
|
||||||
_In_ ASPNETCORE_CONFIG* pConfig,
|
|
||||||
_Out_ APPLICATION_INFO ** ppApplicationInfo
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
APPLICATION_INFO *pApplicationInfo = NULL;
|
|
||||||
APPLICATION_INFO_KEY key;
|
|
||||||
BOOL fExclusiveLock = FALSE;
|
|
||||||
BOOL fMixedHostingModelError = FALSE;
|
|
||||||
BOOL fDuplicatedInProcessApp = FALSE;
|
|
||||||
PCWSTR pszApplicationId = NULL;
|
|
||||||
STACK_STRU ( strEventMsg, 256 );
|
|
||||||
|
|
||||||
DBG_ASSERT(pServer);
|
|
||||||
DBG_ASSERT(pConfig);
|
|
||||||
DBG_ASSERT(ppApplicationInfo);
|
|
||||||
|
|
||||||
*ppApplicationInfo = NULL;
|
|
||||||
|
|
||||||
// The configuration path is unique for each application and is used for the
|
|
||||||
// key in the applicationInfoHash.
|
|
||||||
pszApplicationId = pConfig->QueryConfigPath()->QueryStr();
|
|
||||||
hr = key.Initialize(pszApplicationId);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When accessing the m_pApplicationInfoHash, we need to acquire the application manager
|
|
||||||
// lock to avoid races on setting state.
|
|
||||||
AcquireSRWLockShared(&m_srwLock);
|
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockShared(&m_srwLock);
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
m_pApplicationInfoHash->FindKey(&key, ppApplicationInfo);
|
|
||||||
ReleaseSRWLockShared(&m_srwLock);
|
|
||||||
|
|
||||||
if (*ppApplicationInfo == NULL)
|
|
||||||
{
|
|
||||||
// Check which hosting model we want to support
|
|
||||||
switch (pConfig->QueryHostingModel())
|
|
||||||
{
|
|
||||||
case HOSTING_IN_PROCESS:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HOSTING_OUT_PROCESS:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
pApplicationInfo = new APPLICATION_INFO(pServer);
|
|
||||||
if (pApplicationInfo == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
fExclusiveLock = TRUE;
|
|
||||||
if (g_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 (*ppApplicationInfo != NULL)
|
|
||||||
{
|
|
||||||
// someone else created the application
|
|
||||||
delete pApplicationInfo;
|
|
||||||
pApplicationInfo = NULL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hosting model check. We do not allow mixed scenario for now
|
|
||||||
// could be changed in the future
|
|
||||||
if (m_hostingModel != HOSTING_UNKNOWN)
|
|
||||||
{
|
|
||||||
if (m_hostingModel != pConfig->QueryHostingModel())
|
|
||||||
{
|
|
||||||
// hosting model does not match, error out
|
|
||||||
fMixedHostingModelError = TRUE;
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_APP_INIT_FAILURE);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pApplicationInfo->Initialize(pConfig, m_pFileWatcher);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = m_pApplicationInfoHash->InsertRecord( pApplicationInfo );
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// first application will decide which hosting model allowed by this process
|
|
||||||
//
|
|
||||||
if (m_hostingModel == HOSTING_UNKNOWN)
|
|
||||||
{
|
|
||||||
m_hostingModel = pConfig->QueryHostingModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppApplicationInfo = pApplicationInfo;
|
|
||||||
pApplicationInfo->StartMonitoringAppOffline();
|
|
||||||
|
|
||||||
// Release the locko after starting to monitor for app offline to avoid races with it being dropped.
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
|
|
||||||
fExclusiveLock = FALSE;
|
|
||||||
pApplicationInfo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (fExclusiveLock)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pApplicationInfo != NULL)
|
|
||||||
{
|
|
||||||
pApplicationInfo->DereferenceApplicationInfo();
|
|
||||||
pApplicationInfo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
if (fDuplicatedInProcessApp)
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG,
|
|
||||||
pszApplicationId)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fMixedHostingModelError)
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG,
|
|
||||||
pszApplicationId,
|
|
||||||
pConfig->QueryHostingModel())))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG,
|
|
||||||
pszApplicationId,
|
|
||||||
hr)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_ADD_APPLICATION_ERROR,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the application's configuration was changed,
|
|
||||||
// append the configuration path to the config change context.
|
|
||||||
//
|
|
||||||
BOOL
|
|
||||||
APPLICATION_MANAGER::FindConfigChangedApplication(
|
|
||||||
_In_ APPLICATION_INFO * pEntry,
|
|
||||||
_In_ PVOID pvContext)
|
|
||||||
{
|
|
||||||
DBG_ASSERT(pEntry);
|
|
||||||
DBG_ASSERT(pvContext);
|
|
||||||
|
|
||||||
// Config Change context contains the original config path that changed
|
|
||||||
// and a multiStr containing
|
|
||||||
CONFIG_CHANGE_CONTEXT* pContext = static_cast<CONFIG_CHANGE_CONTEXT*>(pvContext);
|
|
||||||
STRU* pstruConfigPath = pEntry->QueryConfig()->QueryConfigPath();
|
|
||||||
|
|
||||||
// check if the application path contains our app/subapp by seeing if the config path
|
|
||||||
// starts with the notification path.
|
|
||||||
BOOL fChanged = pstruConfigPath->StartsWith(pContext->pstrPath, true);
|
|
||||||
if (fChanged)
|
|
||||||
{
|
|
||||||
DWORD dwLen = (DWORD)wcslen(pContext->pstrPath);
|
|
||||||
WCHAR wChar = pstruConfigPath->QueryStr()[dwLen];
|
|
||||||
|
|
||||||
// We need to check that the last character of the config path
|
|
||||||
// is either a null terminator or a slash.
|
|
||||||
// This checks the case where the config path was
|
|
||||||
// MACHINE/WEBROOT/site and your site path is MACHINE/WEBROOT/siteTest
|
|
||||||
if (wChar != L'\0' && wChar != L'/')
|
|
||||||
{
|
|
||||||
// not current app or sub app
|
|
||||||
fChanged = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pContext->MultiSz.Append(*pstruConfigPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Finds any applications affected by a configuration change and calls Recycle on them
|
|
||||||
// InProcess: Triggers g_httpServer->RecycleProcess() and keep the application inside of the manager.
|
|
||||||
// This will cause a shutdown event to occur through the global stop listening event.
|
|
||||||
// OutOfProcess: Removes all applications in the application manager and calls Recycle, which will call Shutdown,
|
|
||||||
// on each application.
|
|
||||||
//
|
|
||||||
HRESULT
|
|
||||||
APPLICATION_MANAGER::RecycleApplicationFromManager(
|
|
||||||
_In_ LPCWSTR pszApplicationId
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
APPLICATION_INFO_KEY key;
|
|
||||||
DWORD dwPreviousCounter = 0;
|
|
||||||
APPLICATION_INFO_HASH* table = NULL;
|
|
||||||
CONFIG_CHANGE_CONTEXT context;
|
|
||||||
BOOL fKeepTable = FALSE;
|
|
||||||
|
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
|
||||||
// We are already shutting down, ignore this event as a global configuration change event
|
|
||||||
// can occur after global stop listening for some reason.
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = key.Initialize(pszApplicationId);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
// Make a shallow copy of existing hashtable as we may need to remove nodes
|
|
||||||
// This will be used for finding differences in which applications are affected by a config change.
|
|
||||||
table = new APPLICATION_INFO_HASH();
|
|
||||||
|
|
||||||
if (table == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// few application expected, small bucket size for hash table
|
|
||||||
if (FAILED(hr = table->Initialize(17 /*prime*/)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.pstrPath = pszApplicationId;
|
|
||||||
|
|
||||||
// Keep track of the preview count of applications to know whether there are applications to delete
|
|
||||||
dwPreviousCounter = m_pApplicationInfoHash->Count();
|
|
||||||
|
|
||||||
// We don't want to hold the application manager lock for long time as it will block all incoming requests
|
|
||||||
// Don't call application shutdown inside the lock
|
|
||||||
m_pApplicationInfoHash->Apply(APPLICATION_INFO_HASH::ReferenceCopyToTable, static_cast<PVOID>(table));
|
|
||||||
DBG_ASSERT(dwPreviousCounter == table->Count());
|
|
||||||
|
|
||||||
// Removed the applications which are impacted by the configurtion change
|
|
||||||
m_pApplicationInfoHash->DeleteIf(FindConfigChangedApplication, (PVOID)&context);
|
|
||||||
|
|
||||||
if (dwPreviousCounter != m_pApplicationInfoHash->Count())
|
|
||||||
{
|
|
||||||
if (m_hostingModel == HOSTING_IN_PROCESS)
|
|
||||||
{
|
|
||||||
// When we are inprocess, we need to keep the application the
|
|
||||||
// application manager that is being deleted. This is because we will always need to recycle the worker
|
|
||||||
// process and any requests that hit this worker process must be rejected (while out of process can
|
|
||||||
// start a new dotnet process). We will immediately call Recycle after this call.
|
|
||||||
DBG_ASSERT(m_pApplicationInfoHash->Count() == 0);
|
|
||||||
delete m_pApplicationInfoHash;
|
|
||||||
|
|
||||||
// We don't want to delete the table as m_pApplicationInfoHash = table
|
|
||||||
fKeepTable = TRUE;
|
|
||||||
m_pApplicationInfoHash = table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pApplicationInfoHash->Count() == 0)
|
|
||||||
{
|
|
||||||
m_hostingModel = HOSTING_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
|
|
||||||
// If we receive a request at this point.
|
|
||||||
// OutOfProcess: we will create a new application with new configuration
|
|
||||||
// InProcess: the request would have to be rejected, as we are about to call g_HttpServer->RecycleProcess
|
|
||||||
// on the worker proocess
|
|
||||||
if (!context.MultiSz.IsEmpty())
|
|
||||||
{
|
|
||||||
PCWSTR path = context.MultiSz.First();
|
|
||||||
// Iterate through each of the paths that were shut down,
|
|
||||||
// calling RecycleApplication on each of them.
|
|
||||||
while (path != NULL)
|
|
||||||
{
|
|
||||||
APPLICATION_INFO* pRecord;
|
|
||||||
|
|
||||||
// Application got recycled. Log an event
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_CONFIGURATION_MSG,
|
|
||||||
path)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_INFORMATION_TYPE,
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_CONFIGURATION,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = key.Initialize(path);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
table->FindKey(&key, &pRecord);
|
|
||||||
DBG_ASSERT(pRecord != NULL);
|
|
||||||
|
|
||||||
// RecycleApplication is called on a separate thread.
|
|
||||||
pRecord->RecycleApplication();
|
|
||||||
pRecord->DereferenceApplicationInfo();
|
|
||||||
path = context.MultiSz.Next(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
if (table != NULL && !fKeepTable)
|
|
||||||
{
|
|
||||||
table->Clear();
|
|
||||||
delete table;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
// Failed to recycle an application. Log an event
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG,
|
|
||||||
pszApplicationId)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_RECYCLE_APP_FAILURE,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
// Need to recycle the process as we cannot recycle the application
|
|
||||||
if (!g_fRecycleProcessCalled)
|
|
||||||
{
|
|
||||||
g_fRecycleProcessCalled = TRUE;
|
|
||||||
g_pHttpServer->RecycleProcess(L"AspNetCore Recycle Process on Demand Due Application Recycle Error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Shutsdown all applications in the application hashtable
|
|
||||||
// Only called by OnGlobalStopListening.
|
|
||||||
//
|
|
||||||
VOID
|
|
||||||
APPLICATION_MANAGER::ShutDown()
|
|
||||||
{
|
|
||||||
// We are guaranteed to only have one outstanding OnGlobalStopListening event at a time
|
|
||||||
// However, it is possible to receive multiple OnGlobalStopListening events
|
|
||||||
// Protect against this by checking if we already shut down.
|
|
||||||
g_fInShutdown = TRUE;
|
|
||||||
if (m_pApplicationInfoHash != NULL)
|
|
||||||
{
|
|
||||||
if (m_pFileWatcher != NULL)
|
|
||||||
{
|
|
||||||
delete m_pFileWatcher;
|
|
||||||
m_pFileWatcher = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_ASSERT(m_pApplicationInfoHash);
|
|
||||||
// During shutdown we lock until we delete the application
|
|
||||||
AcquireSRWLockExclusive(&m_srwLock);
|
|
||||||
|
|
||||||
// Call shutdown on each application in the application manager
|
|
||||||
m_pApplicationInfoHash->Apply(ShutdownApplication, NULL);
|
|
||||||
m_pApplicationInfoHash->Clear();
|
|
||||||
delete m_pApplicationInfoHash;
|
|
||||||
m_pApplicationInfoHash = NULL;
|
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&m_srwLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calls shutdown on each application. ApplicationManager's lock is held for duration of
|
|
||||||
// each shutdown call, guaranteeing another application cannot be created.
|
|
||||||
//
|
|
||||||
// static
|
|
||||||
VOID
|
|
||||||
APPLICATION_MANAGER::ShutdownApplication(
|
|
||||||
_In_ APPLICATION_INFO * pEntry,
|
|
||||||
_In_ PVOID pvContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(pvContext);
|
|
||||||
DBG_ASSERT(pEntry != NULL);
|
|
||||||
|
|
||||||
pEntry->ShutDownApplication();
|
|
||||||
}
|
|
||||||
|
|
@ -1,254 +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"
|
|
||||||
#include <IPHlpApi.h>
|
|
||||||
|
|
||||||
HTTP_MODULE_ID g_pModuleId = NULL;
|
|
||||||
IHttpServer * g_pHttpServer = NULL;
|
|
||||||
HANDLE g_hEventLog = NULL;
|
|
||||||
BOOL g_fRecycleProcessCalled = FALSE;
|
|
||||||
PCWSTR g_pszModuleName = NULL;
|
|
||||||
HINSTANCE g_hModule;
|
|
||||||
HMODULE g_hAspnetCoreRH = NULL;
|
|
||||||
BOOL g_fAspnetcoreRHAssemblyLoaded = FALSE;
|
|
||||||
BOOL g_fAspnetcoreRHLoadedError = FALSE;
|
|
||||||
BOOL g_fInShutdown = FALSE;
|
|
||||||
DWORD g_dwAspNetCoreDebugFlags = 0;
|
|
||||||
DWORD g_dwActiveServerProcesses = 0;
|
|
||||||
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();
|
|
||||||
if (g_hEventLog != NULL)
|
|
||||||
{
|
|
||||||
DeregisterEventSource(g_hEventLog);
|
|
||||||
g_hEventLog = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
// IIS can cause dll detach to occur before we receive global notifications
|
|
||||||
// For example, when we switch the bitness of the worker process,
|
|
||||||
// this is a bug in IIS. To try to avoid AVs, we will set a global flag
|
|
||||||
g_fInShutdown = TRUE;
|
|
||||||
StaticCleanup();
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
__stdcall
|
|
||||||
RegisterModule(
|
|
||||||
DWORD dwServerVersion,
|
|
||||||
IHttpModuleRegistrationInfo * pModuleInfo,
|
|
||||||
IHttpServer * pHttpServer
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine description:
|
|
||||||
|
|
||||||
Function called by IIS immediately after loading the module, used to let
|
|
||||||
IIS know what notifications the module is interested in
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
dwServerVersion - IIS version the module is being loaded on
|
|
||||||
pModuleInfo - info regarding this module
|
|
||||||
pHttpServer - callback functions which can be used by the module at
|
|
||||||
any point
|
|
||||||
|
|
||||||
Return value:
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
g_dwDebugFlags = DEBUG_FLAGS_ANY;
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
CREATE_DEBUG_PRINT_OBJECT;
|
|
||||||
|
|
||||||
//LoadGlobalConfiguration();
|
|
||||||
|
|
||||||
InitializeSRWLock(&g_srwLock);
|
|
||||||
|
|
||||||
g_pModuleId = pModuleInfo->GetId();
|
|
||||||
g_pszModuleName = pModuleInfo->GetName();
|
|
||||||
g_pHttpServer = pHttpServer;
|
|
||||||
|
|
||||||
if (g_pHttpServer->IsCommandLineLaunch())
|
|
||||||
{
|
|
||||||
g_hEventLog = RegisterEventSource(NULL, ASPNETCORE_IISEXPRESS_EVENT_PROVIDER);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_hEventLog = RegisterEventSource(NULL, ASPNETCORE_EVENT_PROVIDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
cbData = sizeof(dwData);
|
|
||||||
if ((RegQueryValueEx(hKey,
|
|
||||||
L"DebugFlags",
|
|
||||||
NULL,
|
|
||||||
&dwType,
|
|
||||||
(LPBYTE)&dwData,
|
|
||||||
&cbData) == NO_ERROR) &&
|
|
||||||
(dwType == REG_DWORD))
|
|
||||||
{
|
|
||||||
g_dwAspNetCoreDebugFlags = dwData;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fDisableANCM)
|
|
||||||
{
|
|
||||||
// Logging
|
|
||||||
STACK_STRU(strEventMsg, 256);
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeSnwprintf(
|
|
||||||
ASPNETCORE_EVENT_MODULE_DISABLED_MSG)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(g_hEventLog,
|
|
||||||
EVENTLOG_WARNING_TYPE,
|
|
||||||
ASPNETCORE_EVENT_MODULE_DISABLED,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
// this will return 500 error to client
|
|
||||||
// as we did not register the module
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create the factory before any static initialization.
|
|
||||||
// The ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate method will clean any
|
|
||||||
// static object initialized.
|
|
||||||
//
|
|
||||||
pFactory = new ASPNET_CORE_PROXY_MODULE_FACTORY;
|
|
||||||
|
|
||||||
if (pFactory == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pModuleInfo->SetRequestNotifications(
|
|
||||||
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;
|
|
||||||
|
|
||||||
pGlobalModule = new ASPNET_CORE_GLOBAL_MODULE(pApplicationManager);
|
|
||||||
if (pGlobalModule == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pModuleInfo->SetGlobalNotifications(
|
|
||||||
pGlobalModule,
|
|
||||||
GL_CONFIGURATION_CHANGE | // Configuration change trigers IIS application stop
|
|
||||||
GL_STOP_LISTENING); // worker process stop or recycle
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
pGlobalModule = NULL;
|
|
||||||
|
|
||||||
hr = ALLOC_CACHE_HANDLER::StaticInitialize();
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
if (pGlobalModule != NULL)
|
|
||||||
{
|
|
||||||
delete pGlobalModule;
|
|
||||||
pGlobalModule = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFactory != NULL)
|
|
||||||
{
|
|
||||||
pFactory->Terminate();
|
|
||||||
pFactory = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,497 +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"
|
|
||||||
|
|
||||||
FILE_WATCHER::FILE_WATCHER() :
|
|
||||||
m_hCompletionPort(NULL),
|
|
||||||
m_hChangeNotificationThread(NULL),
|
|
||||||
m_fThreadExit(FALSE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE_WATCHER::~FILE_WATCHER()
|
|
||||||
{
|
|
||||||
if (m_hChangeNotificationThread != NULL)
|
|
||||||
{
|
|
||||||
DWORD dwRetryCounter = 20; // totally wait for 1s
|
|
||||||
DWORD dwExitCode = STILL_ACTIVE;
|
|
||||||
|
|
||||||
// signal the file watch thread to exit
|
|
||||||
PostQueuedCompletionStatus(m_hCompletionPort, 0, FILE_WATCHER_SHUTDOWN_KEY, NULL);
|
|
||||||
while (!m_fThreadExit && dwRetryCounter > 0)
|
|
||||||
{
|
|
||||||
if (GetExitCodeThread(m_hChangeNotificationThread, &dwExitCode))
|
|
||||||
{
|
|
||||||
if (dwExitCode == STILL_ACTIVE)
|
|
||||||
{
|
|
||||||
// the file watcher thread will set m_fThreadExit before exit
|
|
||||||
WaitForSingleObject(m_hChangeNotificationThread, 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// fail to get thread status
|
|
||||||
// call terminitethread
|
|
||||||
TerminateThread(m_hChangeNotificationThread, 1);
|
|
||||||
m_fThreadExit = TRUE;
|
|
||||||
}
|
|
||||||
dwRetryCounter--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_fThreadExit)
|
|
||||||
{
|
|
||||||
TerminateThread(m_hChangeNotificationThread, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(m_hChangeNotificationThread);
|
|
||||||
m_hChangeNotificationThread = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != m_hCompletionPort)
|
|
||||||
{
|
|
||||||
CloseHandle(m_hCompletionPort);
|
|
||||||
m_hCompletionPort = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FILE_WATCHER::Create(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (m_hCompletionPort == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hChangeNotificationThread = CreateThread(NULL,
|
|
||||||
0,
|
|
||||||
ChangeNotificationThread,
|
|
||||||
this,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (m_hChangeNotificationThread == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
|
|
||||||
CloseHandle(m_hCompletionPort);
|
|
||||||
m_hCompletionPort = NULL;
|
|
||||||
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
WINAPI
|
|
||||||
FILE_WATCHER::ChangeNotificationThread(
|
|
||||||
LPVOID pvArg
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
IO completion thread
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
None
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
Win32 error
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
FILE_WATCHER * pFileMonitor;
|
|
||||||
BOOL fSuccess = FALSE;
|
|
||||||
DWORD cbCompletion = 0;
|
|
||||||
OVERLAPPED * pOverlapped = NULL;
|
|
||||||
DWORD dwErrorStatus;
|
|
||||||
ULONG_PTR completionKey;
|
|
||||||
|
|
||||||
pFileMonitor = (FILE_WATCHER*)pvArg;
|
|
||||||
DBG_ASSERT(pFileMonitor != NULL);
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
fSuccess = GetQueuedCompletionStatus(
|
|
||||||
pFileMonitor->m_hCompletionPort,
|
|
||||||
&cbCompletion,
|
|
||||||
&completionKey,
|
|
||||||
&pOverlapped,
|
|
||||||
INFINITE);
|
|
||||||
|
|
||||||
DBG_ASSERT(fSuccess);
|
|
||||||
dwErrorStatus = fSuccess ? ERROR_SUCCESS : GetLastError();
|
|
||||||
|
|
||||||
if (completionKey == FILE_WATCHER_SHUTDOWN_KEY)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_ASSERT(pOverlapped != NULL);
|
|
||||||
if (pOverlapped != NULL)
|
|
||||||
{
|
|
||||||
FileWatcherCompletionRoutine(
|
|
||||||
dwErrorStatus,
|
|
||||||
cbCompletion,
|
|
||||||
pOverlapped);
|
|
||||||
}
|
|
||||||
pOverlapped = NULL;
|
|
||||||
cbCompletion = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pFileMonitor->m_fThreadExit = TRUE;
|
|
||||||
ExitThread(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
WINAPI
|
|
||||||
FILE_WATCHER::FileWatcherCompletionRoutine(
|
|
||||||
DWORD dwCompletionStatus,
|
|
||||||
DWORD cbCompletion,
|
|
||||||
OVERLAPPED * pOverlapped
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Called when ReadDirectoryChangesW() completes
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
dwCompletionStatus - Error of completion
|
|
||||||
cbCompletion - Bytes of completion
|
|
||||||
pOverlapped - State of completion
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
None
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
FILE_WATCHER_ENTRY * pMonitorEntry;
|
|
||||||
pMonitorEntry = CONTAINING_RECORD(pOverlapped, FILE_WATCHER_ENTRY, _overlapped);
|
|
||||||
|
|
||||||
DBG_ASSERT(pMonitorEntry != NULL);
|
|
||||||
|
|
||||||
pMonitorEntry->HandleChangeCompletion(dwCompletionStatus, cbCompletion);
|
|
||||||
|
|
||||||
if (pMonitorEntry->QueryIsValid())
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Continue monitoring
|
|
||||||
//
|
|
||||||
pMonitorEntry->Monitor();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Deference the counter not matter whether the monitor is valid
|
|
||||||
// Valid: Monitor increases the counter, need to reduce one
|
|
||||||
// InValid: Reduce the counter to free the entry
|
|
||||||
//
|
|
||||||
pMonitorEntry->DereferenceFileWatcherEntry();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FILE_WATCHER_ENTRY::FILE_WATCHER_ENTRY(FILE_WATCHER * pFileMonitor) :
|
|
||||||
_pFileMonitor(pFileMonitor),
|
|
||||||
_hDirectory(INVALID_HANDLE_VALUE),
|
|
||||||
_hImpersonationToken(NULL),
|
|
||||||
_pApplicationInfo(NULL),
|
|
||||||
_lStopMonitorCalled(0),
|
|
||||||
_cRefs(1),
|
|
||||||
_fIsValid(TRUE)
|
|
||||||
{
|
|
||||||
_dwSignature = FILE_WATCHER_ENTRY_SIGNATURE;
|
|
||||||
InitializeSRWLock(&_srwLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE_WATCHER_ENTRY::~FILE_WATCHER_ENTRY()
|
|
||||||
{
|
|
||||||
_dwSignature = FILE_WATCHER_ENTRY_SIGNATURE_FREE;
|
|
||||||
|
|
||||||
if (_hDirectory != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(_hDirectory);
|
|
||||||
_hDirectory = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_hImpersonationToken != NULL)
|
|
||||||
{
|
|
||||||
CloseHandle(_hImpersonationToken);
|
|
||||||
_hImpersonationToken = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(disable:4100)
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FILE_WATCHER_ENTRY::HandleChangeCompletion(
|
|
||||||
_In_ DWORD dwCompletionStatus,
|
|
||||||
_In_ DWORD cbCompletion
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Handle change notification (see if any of associated config files
|
|
||||||
need to be flushed)
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
dwCompletionStatus - Completion status
|
|
||||||
cbCompletion - Bytes of completion
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
FILE_NOTIFY_INFORMATION * pNotificationInfo;
|
|
||||||
BOOL fFileChanged = FALSE;
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&_srwLock);
|
|
||||||
if (!_fIsValid)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When directory handle is closed then HandleChangeCompletion
|
|
||||||
// happens with cbCompletion = 0 and dwCompletionStatus = 0
|
|
||||||
// From documentation it is not clear if that combination
|
|
||||||
// of return values is specific to closing handles or whether
|
|
||||||
// it could also mean an error condition. Hence we will maintain
|
|
||||||
// explicit flag that will help us determine if entry
|
|
||||||
// is being shutdown (StopMonitor() called)
|
|
||||||
//
|
|
||||||
if (_lStopMonitorCalled)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// There could be a FCN overflow
|
|
||||||
// Let assume the file got changed instead of checking files
|
|
||||||
// Othersie we have to cache the file info
|
|
||||||
//
|
|
||||||
if (cbCompletion == 0)
|
|
||||||
{
|
|
||||||
fFileChanged = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pNotificationInfo = (FILE_NOTIFY_INFORMATION*)_buffDirectoryChanges.QueryPtr();
|
|
||||||
DBG_ASSERT(pNotificationInfo != NULL);
|
|
||||||
|
|
||||||
while (pNotificationInfo != NULL)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// check whether the monitored file got changed
|
|
||||||
//
|
|
||||||
if (_wcsnicmp(pNotificationInfo->FileName,
|
|
||||||
_strFileName.QueryStr(),
|
|
||||||
pNotificationInfo->FileNameLength / sizeof(WCHAR)) == 0)
|
|
||||||
{
|
|
||||||
fFileChanged = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Advance to next notification
|
|
||||||
//
|
|
||||||
if (pNotificationInfo->NextEntryOffset == 0)
|
|
||||||
{
|
|
||||||
pNotificationInfo = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pNotificationInfo = (FILE_NOTIFY_INFORMATION*)
|
|
||||||
((PBYTE)pNotificationInfo +
|
|
||||||
pNotificationInfo->NextEntryOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fFileChanged)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// so far we only monitoring app_offline
|
|
||||||
//
|
|
||||||
_pApplicationInfo->UpdateAppOfflineFileHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
ReleaseSRWLockExclusive(&_srwLock);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning( error : 4100 )
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FILE_WATCHER_ENTRY::Monitor(VOID)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
DWORD cbRead;
|
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&_srwLock);
|
|
||||||
ReferenceFileWatcherEntry();
|
|
||||||
ZeroMemory(&_overlapped, sizeof(_overlapped));
|
|
||||||
|
|
||||||
if (!ReadDirectoryChangesW(_hDirectory,
|
|
||||||
_buffDirectoryChanges.QueryPtr(),
|
|
||||||
_buffDirectoryChanges.QuerySize(),
|
|
||||||
FALSE, // Watching sub dirs. Set to False now as only monitoring app_offline
|
|
||||||
FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS,
|
|
||||||
&cbRead,
|
|
||||||
&_overlapped,
|
|
||||||
NULL))
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
DereferenceFileWatcherEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&_srwLock);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FILE_WATCHER_ENTRY::StopMonitor(VOID)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Flag that monitoring is being stopped so that
|
|
||||||
// we know that HandleChangeCompletion() call
|
|
||||||
// can be ignored
|
|
||||||
//
|
|
||||||
InterlockedExchange(&_lStopMonitorCalled, 1);
|
|
||||||
|
|
||||||
if (_hDirectory != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(&_srwLock);
|
|
||||||
if (_hDirectory != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(_hDirectory);
|
|
||||||
_hDirectory = INVALID_HANDLE_VALUE;
|
|
||||||
DereferenceFileWatcherEntry();
|
|
||||||
}
|
|
||||||
ReleaseSRWLockExclusive(&_srwLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FILE_WATCHER_ENTRY::Create(
|
|
||||||
_In_ PCWSTR pszDirectoryToMonitor,
|
|
||||||
_In_ PCWSTR pszFileNameToMonitor,
|
|
||||||
_In_ APPLICATION_INFO* pApplicationInfo,
|
|
||||||
_In_ HANDLE hImpersonationToken
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
BOOL fRet = FALSE;
|
|
||||||
|
|
||||||
if (pszDirectoryToMonitor == NULL ||
|
|
||||||
pszFileNameToMonitor == NULL ||
|
|
||||||
pApplicationInfo == NULL)
|
|
||||||
{
|
|
||||||
DBG_ASSERT(FALSE);
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//remember the application
|
|
||||||
//
|
|
||||||
_pApplicationInfo = pApplicationInfo;
|
|
||||||
|
|
||||||
if (FAILED(hr = _strFileName.Copy(pszFileNameToMonitor)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = _strDirectoryName.Copy(pszDirectoryToMonitor)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Resize change buffer to something "reasonable"
|
|
||||||
//
|
|
||||||
if (!_buffDirectoryChanges.Resize(FILE_WATCHER_ENTRY_BUFFER_SIZE))
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hImpersonationToken != NULL)
|
|
||||||
{
|
|
||||||
fRet = DuplicateHandle(GetCurrentProcess(),
|
|
||||||
hImpersonationToken,
|
|
||||||
GetCurrentProcess(),
|
|
||||||
&_hImpersonationToken,
|
|
||||||
0,
|
|
||||||
FALSE,
|
|
||||||
DUPLICATE_SAME_ACCESS);
|
|
||||||
|
|
||||||
if (!fRet)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_hImpersonationToken != NULL)
|
|
||||||
{
|
|
||||||
CloseHandle(_hImpersonationToken);
|
|
||||||
_hImpersonationToken = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_hDirectory = CreateFileW(
|
|
||||||
_strDirectoryName.QueryStr(),
|
|
||||||
FILE_LIST_DIRECTORY,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
NULL,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (_hDirectory == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CreateIoCompletionPort(
|
|
||||||
_hDirectory,
|
|
||||||
_pFileMonitor->QueryCompletionPort(),
|
|
||||||
NULL,
|
|
||||||
0) == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start monitoring
|
|
||||||
//
|
|
||||||
hr = Monitor();
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
#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 (g_fInShutdown)
|
|
||||||
{
|
|
||||||
// Avoid receiving two shutudown notifications.
|
|
||||||
return GL_NOTIFICATION_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_ASSERT(m_pApplicationManager);
|
|
||||||
// we should let application manager to shutdown 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
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
|
||||||
return GL_NOTIFICATION_CONTINUE;
|
|
||||||
}
|
|
||||||
// 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->RecycleApplicationFromManager(pwszChangePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return processing to the pipeline.
|
|
||||||
return GL_NOTIFICATION_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
@ -1,159 +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
|
|
||||||
#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 <ntassert.h>
|
|
||||||
#include <Shlobj.h>
|
|
||||||
#include <httpserv.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 <httptrace.h>
|
|
||||||
#include <winhttp.h>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <vector>
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// Option available starting Windows 8.
|
|
||||||
// 111 is the value in SDK on May 15, 2012.
|
|
||||||
//
|
|
||||||
#ifndef WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS
|
|
||||||
#define WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS 111
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <hashfn.h>
|
|
||||||
#include <hashtable.h>
|
|
||||||
#include "stringa.h"
|
|
||||||
#include "stringu.h"
|
|
||||||
#include "dbgutil.h"
|
|
||||||
#include "ahutil.h"
|
|
||||||
#include "multisz.h"
|
|
||||||
#include "multisza.h"
|
|
||||||
#include "base64.h"
|
|
||||||
#include <listentry.h>
|
|
||||||
#include <datetime.h>
|
|
||||||
#include <reftrace.h>
|
|
||||||
#include <acache.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "..\..\CommonLib\environmentvariablehash.h"
|
|
||||||
#include "..\..\CommonLib\aspnetcoreconfig.h"
|
|
||||||
#include "..\..\CommonLib\hostfxr_utility.h"
|
|
||||||
#include "..\..\CommonLib\application.h"
|
|
||||||
#include "..\..\CommonLib\utility.h"
|
|
||||||
#include "..\..\CommonLib\debugutil.h"
|
|
||||||
#include "..\..\CommonLib\requesthandler.h"
|
|
||||||
#include "..\..\CommonLib\resources.h"
|
|
||||||
#include "..\..\CommonLib\aspnetcore_msg.h"
|
|
||||||
//#include "aspnetcore_event.h"
|
|
||||||
#include "appoffline.h"
|
|
||||||
#include "filewatcher.h"
|
|
||||||
#include "applicationinfo.h"
|
|
||||||
#include "applicationmanager.h"
|
|
||||||
#include "globalmodule.h"
|
|
||||||
#include "proxymodule.h"
|
|
||||||
#include "applicationinfo.h"
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
DWORD
|
|
||||||
WIN32_FROM_HRESULT(
|
|
||||||
HRESULT hr
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ((FAILED(hr)) &&
|
|
||||||
(HRESULT_FACILITY(hr) == FACILITY_WIN32))
|
|
||||||
{
|
|
||||||
return HRESULT_CODE(hr);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
HRESULT
|
|
||||||
HRESULT_FROM_GETLASTERROR()
|
|
||||||
{
|
|
||||||
return ( GetLastError() != NO_ERROR )
|
|
||||||
? HRESULT_FROM_WIN32( GetLastError() )
|
|
||||||
: E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern PVOID g_pModuleId;
|
|
||||||
extern BOOL g_fAspnetcoreRHAssemblyLoaded;
|
|
||||||
extern BOOL g_fAspnetcoreRHLoadedError;
|
|
||||||
extern BOOL g_fInShutdown;
|
|
||||||
extern BOOL g_fEnableReferenceCountTracing;
|
|
||||||
extern DWORD g_dwActiveServerProcesses;
|
|
||||||
extern HINSTANCE g_hModule;
|
|
||||||
extern HMODULE g_hAspnetCoreRH;
|
|
||||||
extern SRWLOCK g_srwLock;
|
|
||||||
extern PCWSTR g_pwzAspnetcoreRequestHandlerName;
|
|
||||||
extern HANDLE g_hEventLog;
|
|
||||||
extern PFN_ASPNETCORE_CREATE_APPLICATION g_pfnAspNetCoreCreateApplication;
|
|
||||||
extern PFN_ASPNETCORE_CREATE_REQUEST_HANDLER g_pfnAspNetCoreCreateRequestHandler;
|
|
||||||
#pragma warning( error : 4091)
|
|
||||||
|
|
@ -1,211 +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"
|
|
||||||
|
|
||||||
__override
|
|
||||||
HRESULT
|
|
||||||
ASPNET_CORE_PROXY_MODULE_FACTORY::GetHttpModule(
|
|
||||||
CHttpModule ** ppModule,
|
|
||||||
IModuleAllocator * pAllocator
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ASPNET_CORE_PROXY_MODULE *pModule = new (pAllocator) ASPNET_CORE_PROXY_MODULE();
|
|
||||||
if (pModule == NULL)
|
|
||||||
{
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppModule = pModule;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
__override
|
|
||||||
VOID
|
|
||||||
ASPNET_CORE_PROXY_MODULE_FACTORY::Terminate(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine description:
|
|
||||||
|
|
||||||
Function called by IIS for global (non-request-specific) notifications
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
Return value:
|
|
||||||
|
|
||||||
None
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
/* FORWARDING_HANDLER::StaticTerminate();
|
|
||||||
|
|
||||||
WEBSOCKET_HANDLER::StaticTerminate();*/
|
|
||||||
|
|
||||||
ALLOC_CACHE_HANDLER::StaticTerminate();
|
|
||||||
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASPNET_CORE_PROXY_MODULE::ASPNET_CORE_PROXY_MODULE(
|
|
||||||
) : m_pApplicationInfo(NULL), m_pHandler(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ASPNET_CORE_PROXY_MODULE::~ASPNET_CORE_PROXY_MODULE()
|
|
||||||
{
|
|
||||||
if (m_pApplicationInfo != NULL)
|
|
||||||
{
|
|
||||||
m_pApplicationInfo->DereferenceApplicationInfo();
|
|
||||||
m_pApplicationInfo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pHandler != NULL)
|
|
||||||
{
|
|
||||||
m_pHandler->DereferenceRequestHandler();
|
|
||||||
m_pHandler = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__override
|
|
||||||
REQUEST_NOTIFICATION_STATUS
|
|
||||||
ASPNET_CORE_PROXY_MODULE::OnExecuteRequestHandler(
|
|
||||||
IHttpContext * pHttpContext,
|
|
||||||
IHttpEventProvider *
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
ASPNETCORE_CONFIG *pConfig = NULL;
|
|
||||||
APPLICATION_MANAGER *pApplicationManager = NULL;
|
|
||||||
REQUEST_NOTIFICATION_STATUS retVal = RQ_NOTIFICATION_CONTINUE;
|
|
||||||
APPLICATION* pApplication = NULL;
|
|
||||||
STACK_STRU(struFileName, 256);
|
|
||||||
if (g_fInShutdown)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = ASPNETCORE_CONFIG::GetConfig(g_pHttpServer, g_pModuleId, pHttpContext, g_hEventLog, &pConfig);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pApplicationManager = APPLICATION_MANAGER::GetInstance();
|
|
||||||
if (pApplicationManager == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pApplicationManager->GetOrCreateApplicationInfo(
|
|
||||||
g_pHttpServer,
|
|
||||||
pConfig,
|
|
||||||
&m_pApplicationInfo);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// app_offline check to avoid loading aspnetcorerh.dll unnecessarily
|
|
||||||
if (m_pApplicationInfo->AppOfflineFound())
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure assmebly is loaded and application is created
|
|
||||||
hr = m_pApplicationInfo->EnsureApplicationCreated();
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pApplicationInfo->ExtractApplication(&pApplication);
|
|
||||||
|
|
||||||
// make sure application is in running state
|
|
||||||
// cannot recreate the application as we cannot reload clr for inprocess
|
|
||||||
if (pApplication != NULL &&
|
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::RUNNING &&
|
|
||||||
pApplication->QueryStatus() != APPLICATION_STATUS::STARTING)
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
retVal = RQ_NOTIFICATION_FINISH_REQUEST;
|
|
||||||
if (hr == HRESULT_FROM_WIN32(ERROR_SERVER_SHUTDOWN_IN_PROGRESS))
|
|
||||||
{
|
|
||||||
pHttpContext->GetResponse()->SetStatus(503, "Service Unavailable", 0, hr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pHttpContext->GetResponse()->SetStatus(500, "Internal Server Error", 0, hr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pApplication != NULL)
|
|
||||||
{
|
|
||||||
pApplication->DereferenceApplication();
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
__override
|
|
||||||
REQUEST_NOTIFICATION_STATUS
|
|
||||||
ASPNET_CORE_PROXY_MODULE::OnAsyncCompletion(
|
|
||||||
IHttpContext *,
|
|
||||||
DWORD,
|
|
||||||
BOOL,
|
|
||||||
IHttpEventProvider *,
|
|
||||||
IHttpCompletionInfo * pCompletionInfo
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_pHandler->OnAsyncCompletion(
|
|
||||||
pCompletionInfo->GetCompletionBytes(),
|
|
||||||
pCompletionInfo->GetCompletionStatus());
|
|
||||||
}
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
||||||
<?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>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
</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="disconnectcontext.h" />
|
|
||||||
<ClInclude Include="environmentvariablehash.h" />
|
|
||||||
<ClInclude Include="fx_ver.h" />
|
|
||||||
<ClInclude Include="hostfxr_utility.h" />
|
|
||||||
<ClInclude Include="requesthandler.h" />
|
|
||||||
<ClInclude Include="resources.h" />
|
|
||||||
<ClInclude Include="SRWLockWrapper.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="SRWLockWrapper.cpp" />
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#include "stdafx.h"
|
|
||||||
#include "SRWLockWrapper.h"
|
|
||||||
|
|
||||||
SRWLockWrapper::SRWLockWrapper(const SRWLOCK& lock)
|
|
||||||
: m_lock(lock)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(const_cast<SRWLOCK*>(&m_lock));
|
|
||||||
}
|
|
||||||
|
|
||||||
SRWLockWrapper::~SRWLockWrapper()
|
|
||||||
{
|
|
||||||
ReleaseSRWLockExclusive(const_cast<SRWLOCK*>(&m_lock));
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#pragma once
|
|
||||||
class SRWLockWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SRWLockWrapper(const SRWLOCK& lock);
|
|
||||||
~SRWLockWrapper();
|
|
||||||
private:
|
|
||||||
const SRWLOCK& m_lock;
|
|
||||||
};
|
|
||||||
|
|
@ -1,50 +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 "stdafx.h"
|
|
||||||
|
|
||||||
APPLICATION::APPLICATION(
|
|
||||||
_In_ IHttpServer* pHttpServer,
|
|
||||||
_In_ ASPNETCORE_CONFIG* pConfig) :
|
|
||||||
m_cRefs(1),
|
|
||||||
m_pConfig(pConfig),
|
|
||||||
m_status(APPLICATION_STATUS::UNKNOWN)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER(pHttpServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +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
|
|
||||||
|
|
||||||
enum APPLICATION_STATUS
|
|
||||||
{
|
|
||||||
UNKNOWN = 0,
|
|
||||||
STARTING,
|
|
||||||
RUNNING,
|
|
||||||
SHUTDOWN,
|
|
||||||
FAIL
|
|
||||||
};
|
|
||||||
|
|
||||||
class ASPNETCORE_CONFIG;
|
|
||||||
|
|
||||||
class APPLICATION
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
APPLICATION(
|
|
||||||
_In_ IHttpServer* pHttpServer,
|
|
||||||
_In_ ASPNETCORE_CONFIG* pConfig);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
ShutDown() = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
Recycle() = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
~APPLICATION();
|
|
||||||
|
|
||||||
APPLICATION_STATUS
|
|
||||||
QueryStatus();
|
|
||||||
|
|
||||||
ASPNETCORE_CONFIG*
|
|
||||||
QueryConfig();
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ReferenceApplication()
|
|
||||||
const;
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DereferenceApplication()
|
|
||||||
const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
mutable LONG m_cRefs;
|
|
||||||
volatile APPLICATION_STATUS m_status;
|
|
||||||
ASPNETCORE_CONFIG* m_pConfig;
|
|
||||||
};
|
|
||||||
|
|
@ -1,217 +0,0 @@
|
||||||
;/*++
|
|
||||||
;
|
|
||||||
; 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_
|
|
||||||
;
|
|
||||||
|
|
||||||
SeverityNames=(Success=0x0
|
|
||||||
Informational=0x1
|
|
||||||
Warning=0x2
|
|
||||||
Error=0x3
|
|
||||||
)
|
|
||||||
|
|
||||||
MessageIdTypedef=DWORD
|
|
||||||
|
|
||||||
Messageid=1000
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PROCESS_START_ERROR
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1001
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PROCESS_START_SUCCESS
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1002
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PROCESS_CRASH
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1003
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_RAPID_FAIL_COUNT_EXCEEDED
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1004
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_CONFIG_ERROR
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1005
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_GRACEFUL_SHUTDOWN_FAILURE
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1006
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1007
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_LOAD_CLR_FALIURE
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1008
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1009
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1010
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_ADD_APPLICATION_ERROR
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1011
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1012
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_RECYCLE_APPOFFLINE
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1013
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_MODULE_DISABLED
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1014
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1015
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1016
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1017
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1018
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1019
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1020
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PROCESS_START_FAILURE
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1021
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_RECYCLE_CONFIGURATION
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1022
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_RECYCLE_APP_FAILURE
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1023
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_APP_IN_SHUTDOWN
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1024
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1025
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_GENERAL_INFO_MSG
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1026
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_GENERAL_WARNING_MSG
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1027
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_GENERAL_ERROR_MSG
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1028
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_INPROCESS_RH_MISSING
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1029
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
Messageid=1030
|
|
||||||
SymbolicName=ASPNETCORE_EVENT_PROCESS_SHUTDOWN
|
|
||||||
Language=English
|
|
||||||
%1
|
|
||||||
.
|
|
||||||
|
|
||||||
;
|
|
||||||
;#endif // _ASPNETCORE_MODULE_MSG_H_
|
|
||||||
;
|
|
||||||
|
|
@ -1,609 +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 "stdafx.h"
|
|
||||||
#include "aspnetcoreconfig.h"
|
|
||||||
#include "debugutil.h"
|
|
||||||
|
|
||||||
ASPNETCORE_CONFIG::~ASPNETCORE_CONFIG()
|
|
||||||
{
|
|
||||||
if (m_ppStrArguments != NULL)
|
|
||||||
{
|
|
||||||
delete[] m_ppStrArguments;
|
|
||||||
m_ppStrArguments = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pEnvironmentVariables != NULL)
|
|
||||||
{
|
|
||||||
m_pEnvironmentVariables->Clear();
|
|
||||||
delete m_pEnvironmentVariables;
|
|
||||||
m_pEnvironmentVariables = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ASPNETCORE_CONFIG::ReferenceConfiguration(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
InterlockedIncrement(&m_cRefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ASPNETCORE_CONFIG::DereferenceConfiguration(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
DBG_ASSERT(m_cRefs != 0);
|
|
||||||
LONG cRefs = 0;
|
|
||||||
if ((cRefs = InterlockedDecrement(&m_cRefs)) == 0)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ASPNETCORE_CONFIG::GetConfig(
|
|
||||||
_In_ IHttpServer *pHttpServer,
|
|
||||||
_In_ HTTP_MODULE_ID pModuleId,
|
|
||||||
_In_ IHttpContext *pHttpContext,
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
IHttpApplication *pHttpApplication = pHttpContext->GetApplication();
|
|
||||||
ASPNETCORE_CONFIG *pAspNetCoreConfig = NULL;
|
|
||||||
STRU struHostFxrDllLocation;
|
|
||||||
PWSTR* pwzArgv;
|
|
||||||
DWORD dwArgCount;
|
|
||||||
|
|
||||||
if (ppAspNetCoreConfig == NULL)
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppAspNetCoreConfig = NULL;
|
|
||||||
|
|
||||||
// potential bug if user sepcific config at virtual dir level
|
|
||||||
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)
|
|
||||||
pHttpApplication->GetModuleContextContainer()->GetModuleContext(pModuleId);
|
|
||||||
|
|
||||||
if (pAspNetCoreConfig != NULL)
|
|
||||||
{
|
|
||||||
*ppAspNetCoreConfig = pAspNetCoreConfig;
|
|
||||||
pAspNetCoreConfig = NULL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pAspNetCoreConfig = new ASPNETCORE_CONFIG;
|
|
||||||
if (pAspNetCoreConfig == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pAspNetCoreConfig->Populate(pHttpServer, pHttpContext);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify config for inprocess.
|
|
||||||
if (pAspNetCoreConfig->QueryHostingModel() == APP_HOSTING_MODEL::HOSTING_IN_PROCESS)
|
|
||||||
{
|
|
||||||
if (FAILED(hr = HOSTFXR_UTILITY::GetHostFxrParameters(
|
|
||||||
hEventLog,
|
|
||||||
pAspNetCoreConfig->QueryProcessPath()->QueryStr(),
|
|
||||||
pAspNetCoreConfig->QueryApplicationPhysicalPath()->QueryStr(),
|
|
||||||
pAspNetCoreConfig->QueryArguments()->QueryStr(),
|
|
||||||
&struHostFxrDllLocation,
|
|
||||||
&dwArgCount,
|
|
||||||
&pwzArgv)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = pAspNetCoreConfig->SetHostFxrFullPath(struHostFxrDllLocation.QueryStr())))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pAspNetCoreConfig->SetHostFxrArguments(dwArgCount, pwzArgv);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pHttpApplication->GetModuleContextContainer()->
|
|
||||||
SetModuleContext(pAspNetCoreConfig, pModuleId);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_ASSIGNED))
|
|
||||||
{
|
|
||||||
delete pAspNetCoreConfig;
|
|
||||||
|
|
||||||
pAspNetCoreConfig = (ASPNETCORE_CONFIG*)pHttpApplication->
|
|
||||||
GetModuleContextContainer()->
|
|
||||||
GetModuleContext(pModuleId);
|
|
||||||
|
|
||||||
_ASSERT(pAspNetCoreConfig != NULL);
|
|
||||||
|
|
||||||
hr = S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
|
|
||||||
"ASPNETCORE_CONFIG::GetConfig, set config to ModuleContext");
|
|
||||||
// set appliction info here instead of inside Populate()
|
|
||||||
// as the destructor will delete the backend process
|
|
||||||
hr = pAspNetCoreConfig->QueryApplicationPath()->Copy(pHttpApplication->GetApplicationId());
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppAspNetCoreConfig = pAspNetCoreConfig;
|
|
||||||
pAspNetCoreConfig = NULL;
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (pAspNetCoreConfig != NULL)
|
|
||||||
{
|
|
||||||
delete pAspNetCoreConfig;
|
|
||||||
pAspNetCoreConfig = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ASPNETCORE_CONFIG::Populate(
|
|
||||||
IHttpServer *pHttpServer,
|
|
||||||
IHttpContext *pHttpContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
STACK_STRU(strHostingModel, 300);
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU strEnvName;
|
|
||||||
STRU strEnvValue;
|
|
||||||
STRU strExpandedEnvValue;
|
|
||||||
STRU strApplicationFullPath;
|
|
||||||
IAppHostAdminManager *pAdminManager = NULL;
|
|
||||||
IAppHostElement *pAspNetCoreElement = NULL;
|
|
||||||
IAppHostElement *pWindowsAuthenticationElement = NULL;
|
|
||||||
IAppHostElement *pBasicAuthenticationElement = NULL;
|
|
||||||
IAppHostElement *pAnonymousAuthenticationElement = NULL;
|
|
||||||
IAppHostElement *pWebSocketElement = NULL;
|
|
||||||
IAppHostElement *pEnvVarList = NULL;
|
|
||||||
IAppHostElement *pEnvVar = NULL;
|
|
||||||
IAppHostElementCollection *pEnvVarCollection = NULL;
|
|
||||||
ULONGLONG ullRawTimeSpan = 0;
|
|
||||||
ENUM_INDEX index;
|
|
||||||
ENVIRONMENT_VAR_ENTRY* pEntry = NULL;
|
|
||||||
DWORD dwCounter = 0;
|
|
||||||
DWORD dwPosition = 0;
|
|
||||||
WCHAR* pszPath = NULL;
|
|
||||||
BSTR bstrWindowAuthSection = NULL;
|
|
||||||
BSTR bstrBasicAuthSection = NULL;
|
|
||||||
BSTR bstrAnonymousAuthSection = NULL;
|
|
||||||
BSTR bstrAspNetCoreSection = NULL;
|
|
||||||
BSTR bstrWebsocketSection = NULL;
|
|
||||||
|
|
||||||
m_pEnvironmentVariables = new ENVIRONMENT_VAR_HASH();
|
|
||||||
if (m_pEnvironmentVariables == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (FAILED(hr = m_pEnvironmentVariables->Initialize(37 /*prime*/)))
|
|
||||||
{
|
|
||||||
delete m_pEnvironmentVariables;
|
|
||||||
m_pEnvironmentVariables = NULL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pAdminManager = pHttpServer->GetAdminManager();
|
|
||||||
hr = m_struConfigPath.Copy(pHttpContext->GetApplication()->GetAppConfigPath());
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = m_struApplicationPhysicalPath.Copy(pHttpContext->GetApplication()->GetApplicationPhysicalPath());
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszPath = m_struConfigPath.QueryStr();
|
|
||||||
while (pszPath[dwPosition] != NULL)
|
|
||||||
{
|
|
||||||
if (pszPath[dwPosition] == '/')
|
|
||||||
{
|
|
||||||
dwCounter++;
|
|
||||||
if (dwCounter == 4)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dwPosition++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dwCounter == 4)
|
|
||||||
{
|
|
||||||
hr = m_struApplicationVirtualPath.Copy(pszPath + dwPosition);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = m_struApplicationVirtualPath.Copy(L"/");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Will setup the application virtual path.
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
// assume the corresponding authen was not enabled
|
|
||||||
// as the section may get deleted by user in some HWC case
|
|
||||||
// ToDo: log a warning to event log
|
|
||||||
m_fWindowsAuthEnabled = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = GetElementBoolProperty(pWindowsAuthenticationElement,
|
|
||||||
CS_ENABLED,
|
|
||||||
&m_fWindowsAuthEnabled);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
m_fBasicAuthEnabled = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = GetElementBoolProperty(pBasicAuthenticationElement,
|
|
||||||
CS_ENABLED,
|
|
||||||
&m_fBasicAuthEnabled);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
m_fAnonymousAuthEnabled = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = GetElementBoolProperty(pAnonymousAuthenticationElement,
|
|
||||||
CS_ENABLED,
|
|
||||||
&m_fAnonymousAuthEnabled);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bstrWebsocketSection = SysAllocString(CS_WEBSOCKET_SECTION);
|
|
||||||
if (bstrWebsocketSection == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pAdminManager->GetAdminSection(bstrWebsocketSection,
|
|
||||||
m_struConfigPath.QueryStr(),
|
|
||||||
&pWebSocketElement);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
m_fWebSocketEnabled = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = GetElementBoolProperty(pWebSocketElement,
|
|
||||||
CS_ENABLED,
|
|
||||||
&m_fWebSocketEnabled);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bstrAspNetCoreSection = SysAllocString(CS_ASPNETCORE_SECTION);
|
|
||||||
if (bstrAspNetCoreSection == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
hr = pAdminManager->GetAdminSection(bstrAspNetCoreSection,
|
|
||||||
m_struConfigPath.QueryStr(),
|
|
||||||
&pAspNetCoreElement);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_PROCESS_EXE_PATH,
|
|
||||||
&m_struProcessPath);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_HOSTING_MODEL,
|
|
||||||
&strHostingModel);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
// Swallow this error for backward compatability
|
|
||||||
// Use default behavior for empty string
|
|
||||||
hr = S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strHostingModel.IsEmpty() || strHostingModel.Equals(L"outofprocess", TRUE))
|
|
||||||
{
|
|
||||||
m_hostingModel = HOSTING_OUT_PROCESS;
|
|
||||||
}
|
|
||||||
else if (strHostingModel.Equals(L"inprocess", TRUE))
|
|
||||||
{
|
|
||||||
m_hostingModel = HOSTING_IN_PROCESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// block unknown hosting value
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementStringProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_PROCESS_ARGUMENTS,
|
|
||||||
&m_struArguments);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementDWORDProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_RAPID_FAILS_PER_MINUTE,
|
|
||||||
&m_dwRapidFailsPerMinute);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// rapidFailsPerMinute cannot be greater than 100.
|
|
||||||
//
|
|
||||||
if (m_dwRapidFailsPerMinute > MAX_RAPID_FAILS_PER_MINUTE)
|
|
||||||
{
|
|
||||||
m_dwRapidFailsPerMinute = MAX_RAPID_FAILS_PER_MINUTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementDWORDProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_PROCESSES_PER_APPLICATION,
|
|
||||||
&m_dwProcessesPerApplication);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementDWORDProperty(
|
|
||||||
pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT,
|
|
||||||
&m_dwStartupTimeLimitInMS
|
|
||||||
);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dwStartupTimeLimitInMS *= MILLISECONDS_IN_ONE_SECOND;
|
|
||||||
|
|
||||||
hr = GetElementDWORDProperty(
|
|
||||||
pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT,
|
|
||||||
&m_dwShutdownTimeLimitInMS
|
|
||||||
);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
m_dwShutdownTimeLimitInMS *= MILLISECONDS_IN_ONE_SECOND;
|
|
||||||
|
|
||||||
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_FORWARD_WINDOWS_AUTH_TOKEN,
|
|
||||||
&m_fForwardWindowsAuthToken);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE,
|
|
||||||
&m_fDisableStartUpErrorPage);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = GetElementRawTimeSpanProperty(
|
|
||||||
pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_WINHTTP_REQUEST_TIMEOUT,
|
|
||||||
&ullRawTimeSpan
|
|
||||||
);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dwRequestTimeoutInMS = (DWORD)TIMESPAN_IN_MILLISECONDS(ullRawTimeSpan);
|
|
||||||
|
|
||||||
hr = GetElementBoolProperty(pAspNetCoreElement,
|
|
||||||
CS_ASPNETCORE_STDOUT_LOG_ENABLED,
|
|
||||||
&m_fStdoutLogEnabled);
|
|
||||||
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,
|
|
||||||
&pEnvVarList);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = pEnvVarList->get_Collection(&pEnvVarCollection);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (hr = FindFirstElement(pEnvVarCollection, &index, &pEnvVar);
|
|
||||||
SUCCEEDED(hr);
|
|
||||||
hr = FindNextElement(pEnvVarCollection, &index, &pEnvVar))
|
|
||||||
{
|
|
||||||
if (hr == S_FALSE)
|
|
||||||
{
|
|
||||||
hr = S_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = GetElementStringProperty(pEnvVar,
|
|
||||||
CS_ASPNETCORE_ENVIRONMENT_VARIABLE_NAME,
|
|
||||||
&strEnvName)) ||
|
|
||||||
FAILED(hr = GetElementStringProperty(pEnvVar,
|
|
||||||
CS_ASPNETCORE_ENVIRONMENT_VARIABLE_VALUE,
|
|
||||||
&strEnvValue)) ||
|
|
||||||
FAILED(hr = strEnvName.Append(L"=")) ||
|
|
||||||
FAILED(hr = STRU::ExpandEnvironmentVariables(strEnvValue.QueryStr(), &strExpandedEnvValue)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEntry = new ENVIRONMENT_VAR_ENTRY();
|
|
||||||
if (pEntry == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = pEntry->Initialize(strEnvName.QueryStr(), strExpandedEnvValue.QueryStr())) ||
|
|
||||||
FAILED(hr = m_pEnvironmentVariables->InsertRecord(pEntry)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
strEnvName.Reset();
|
|
||||||
strEnvValue.Reset();
|
|
||||||
strExpandedEnvValue.Reset();
|
|
||||||
pEnvVar->Release();
|
|
||||||
pEnvVar = NULL;
|
|
||||||
pEntry->Dereference();
|
|
||||||
pEntry = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (pAspNetCoreElement != NULL)
|
|
||||||
{
|
|
||||||
pAspNetCoreElement->Release();
|
|
||||||
pAspNetCoreElement = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pWebSocketElement != NULL)
|
|
||||||
{
|
|
||||||
pWebSocketElement->Release();
|
|
||||||
pWebSocketElement = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pWindowsAuthenticationElement != NULL)
|
|
||||||
{
|
|
||||||
pWindowsAuthenticationElement->Release();
|
|
||||||
pWindowsAuthenticationElement = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pAnonymousAuthenticationElement != NULL)
|
|
||||||
{
|
|
||||||
pAnonymousAuthenticationElement->Release();
|
|
||||||
pAnonymousAuthenticationElement = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pBasicAuthenticationElement != NULL)
|
|
||||||
{
|
|
||||||
pBasicAuthenticationElement->Release();
|
|
||||||
pBasicAuthenticationElement = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEnvVarList != NULL)
|
|
||||||
{
|
|
||||||
pEnvVarList->Release();
|
|
||||||
pEnvVarList = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEnvVar != NULL)
|
|
||||||
{
|
|
||||||
pEnvVar->Release();
|
|
||||||
pEnvVar = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEnvVarCollection != NULL)
|
|
||||||
{
|
|
||||||
pEnvVarCollection->Release();
|
|
||||||
pEnvVarCollection = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pEntry != NULL)
|
|
||||||
{
|
|
||||||
pEntry->Dereference();
|
|
||||||
pEntry = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
@ -1,332 +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
|
|
||||||
#define CS_ROOTWEB_CONFIG L"MACHINE/WEBROOT/APPHOST/"
|
|
||||||
#define CS_ROOTWEB_CONFIG_LEN _countof(CS_ROOTWEB_CONFIG)-1
|
|
||||||
#define CS_ASPNETCORE_SECTION L"system.webServer/aspNetCore"
|
|
||||||
#define CS_WINDOWS_AUTHENTICATION_SECTION L"system.webServer/security/authentication/windowsAuthentication"
|
|
||||||
#define CS_BASIC_AUTHENTICATION_SECTION L"system.webServer/security/authentication/basicAuthentication"
|
|
||||||
#define CS_ANONYMOUS_AUTHENTICATION_SECTION L"system.webServer/security/authentication/anonymousAuthentication"
|
|
||||||
#define CS_WEBSOCKET_SECTION L"system.webServer/webSocket"
|
|
||||||
#define CS_ENABLED L"enabled"
|
|
||||||
#define CS_ASPNETCORE_PROCESS_EXE_PATH L"processPath"
|
|
||||||
#define CS_ASPNETCORE_PROCESS_ARGUMENTS L"arguments"
|
|
||||||
#define CS_ASPNETCORE_PROCESS_STARTUP_TIME_LIMIT L"startupTimeLimit"
|
|
||||||
#define CS_ASPNETCORE_PROCESS_SHUTDOWN_TIME_LIMIT L"shutdownTimeLimit"
|
|
||||||
#define CS_ASPNETCORE_WINHTTP_REQUEST_TIMEOUT L"requestTimeout"
|
|
||||||
#define CS_ASPNETCORE_RAPID_FAILS_PER_MINUTE L"rapidFailsPerMinute"
|
|
||||||
#define CS_ASPNETCORE_STDOUT_LOG_ENABLED L"stdoutLogEnabled"
|
|
||||||
#define CS_ASPNETCORE_STDOUT_LOG_FILE L"stdoutLogFile"
|
|
||||||
#define CS_ASPNETCORE_ENVIRONMENT_VARIABLES L"environmentVariables"
|
|
||||||
#define CS_ASPNETCORE_ENVIRONMENT_VARIABLE L"environmentVariable"
|
|
||||||
#define CS_ASPNETCORE_ENVIRONMENT_VARIABLE_NAME L"name"
|
|
||||||
#define CS_ASPNETCORE_ENVIRONMENT_VARIABLE_VALUE L"value"
|
|
||||||
#define CS_ASPNETCORE_PROCESSES_PER_APPLICATION L"processesPerApplication"
|
|
||||||
#define CS_ASPNETCORE_FORWARD_WINDOWS_AUTH_TOKEN L"forwardWindowsAuthToken"
|
|
||||||
#define CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE L"disableStartUpErrorPage"
|
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE L"recycleOnFileChange"
|
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE L"file"
|
|
||||||
#define CS_ASPNETCORE_RECYCLE_ON_FILE_CHANGE_FILE_PATH L"path"
|
|
||||||
#define CS_ASPNETCORE_HOSTING_MODEL L"hostingModel"
|
|
||||||
|
|
||||||
#define MAX_RAPID_FAILS_PER_MINUTE 100
|
|
||||||
#define MILLISECONDS_IN_ONE_SECOND 1000
|
|
||||||
#define MIN_PORT 1025
|
|
||||||
#define MAX_PORT 48000
|
|
||||||
|
|
||||||
#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)))
|
|
||||||
|
|
||||||
//#define HEX_TO_ASCII(c) ((CHAR)(((c) < 10) ? ((c) + '0') : ((c) + 'a' - 10)))
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
|
|
||||||
enum APP_HOSTING_MODEL
|
|
||||||
{
|
|
||||||
HOSTING_UNKNOWN = 0,
|
|
||||||
HOSTING_IN_PROCESS,
|
|
||||||
HOSTING_OUT_PROCESS
|
|
||||||
};
|
|
||||||
|
|
||||||
class ASPNETCORE_CONFIG : IHttpStoredContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual
|
|
||||||
~ASPNETCORE_CONFIG();
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CleanupStoredContext()
|
|
||||||
{
|
|
||||||
DereferenceConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetConfig(
|
|
||||||
_In_ IHttpServer *pHttpServer,
|
|
||||||
_In_ HTTP_MODULE_ID pModuleId,
|
|
||||||
_In_ IHttpContext *pHttpContext,
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_Out_ ASPNETCORE_CONFIG **ppAspNetCoreConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
ENVIRONMENT_VAR_HASH*
|
|
||||||
QueryEnvironmentVariables(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_pEnvironmentVariables;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryRapidFailsPerMinute(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwRapidFailsPerMinute;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryStartupTimeLimitInMS(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwStartupTimeLimitInMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryShutdownTimeLimitInMS(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwShutdownTimeLimitInMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryProcessesPerApplication(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwProcessesPerApplication;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryRequestTimeoutInMS(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwRequestTimeoutInMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryArguments(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return &m_struArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryApplicationPath(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return &m_struApplication;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryApplicationPhysicalPath(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return &m_struApplicationPhysicalPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryApplicationVirtualPath(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return &m_struApplicationVirtualPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryProcessPath(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return &m_struProcessPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
APP_HOSTING_MODEL
|
|
||||||
QueryHostingModel(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_hostingModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryStdoutLogEnabled()
|
|
||||||
{
|
|
||||||
return m_fStdoutLogEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryWebSocketEnabled()
|
|
||||||
{
|
|
||||||
return m_fWebSocketEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryForwardWindowsAuthToken()
|
|
||||||
{
|
|
||||||
return m_fForwardWindowsAuthToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryWindowsAuthEnabled()
|
|
||||||
{
|
|
||||||
return m_fWindowsAuthEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryBasicAuthEnabled()
|
|
||||||
{
|
|
||||||
return m_fBasicAuthEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryAnonymousAuthEnabled()
|
|
||||||
{
|
|
||||||
return m_fAnonymousAuthEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
QueryDisableStartUpErrorPage()
|
|
||||||
{
|
|
||||||
return m_fDisableStartUpErrorPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryStdoutLogFile()
|
|
||||||
{
|
|
||||||
return &m_struStdoutLogFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU*
|
|
||||||
QueryConfigPath()
|
|
||||||
{
|
|
||||||
return &m_struConfigPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
CONST
|
|
||||||
PCWSTR*
|
|
||||||
QueryHostFxrArguments(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_ppStrArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
CONST
|
|
||||||
DWORD
|
|
||||||
QueryHostFxrArgCount(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_dwArgc;
|
|
||||||
}
|
|
||||||
|
|
||||||
CONST
|
|
||||||
PCWSTR
|
|
||||||
QueryHostFxrFullPath(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_struHostFxrLocation.QueryStr();
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SetHostFxrFullPath(
|
|
||||||
PCWSTR pStrHostFxrFullPath
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return m_struHostFxrLocation.Copy(pStrHostFxrFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
SetHostFxrArguments(
|
|
||||||
DWORD dwArgc,
|
|
||||||
PWSTR* ppStrArguments
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (m_ppStrArguments != NULL)
|
|
||||||
{
|
|
||||||
delete[] m_ppStrArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dwArgc = dwArgc;
|
|
||||||
m_ppStrArguments = ppStrArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ReferenceConfiguration(
|
|
||||||
VOID
|
|
||||||
) const;
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DereferenceConfiguration(
|
|
||||||
VOID
|
|
||||||
) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//
|
|
||||||
// private constructor
|
|
||||||
//
|
|
||||||
ASPNETCORE_CONFIG():
|
|
||||||
m_fStdoutLogEnabled( FALSE ),
|
|
||||||
m_pEnvironmentVariables( NULL ),
|
|
||||||
m_cRefs( 1 ),
|
|
||||||
m_hostingModel( HOSTING_UNKNOWN ),
|
|
||||||
m_ppStrArguments(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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_struArguments;
|
|
||||||
STRU m_struProcessPath;
|
|
||||||
STRU m_struStdoutLogFile;
|
|
||||||
STRU m_struApplication;
|
|
||||||
STRU m_struApplicationPhysicalPath;
|
|
||||||
STRU m_struApplicationVirtualPath;
|
|
||||||
STRU m_struConfigPath;
|
|
||||||
BOOL m_fStdoutLogEnabled;
|
|
||||||
BOOL m_fForwardWindowsAuthToken;
|
|
||||||
BOOL m_fDisableStartUpErrorPage;
|
|
||||||
BOOL m_fWindowsAuthEnabled;
|
|
||||||
BOOL m_fBasicAuthEnabled;
|
|
||||||
BOOL m_fAnonymousAuthEnabled;
|
|
||||||
BOOL m_fWebSocketEnabled;
|
|
||||||
APP_HOSTING_MODEL m_hostingModel;
|
|
||||||
ENVIRONMENT_VAR_HASH* m_pEnvironmentVariables;
|
|
||||||
STRU m_struHostFxrLocation;
|
|
||||||
PWSTR* m_ppStrArguments;
|
|
||||||
DWORD m_dwArgc;
|
|
||||||
};
|
|
||||||
|
|
@ -1,81 +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
|
|
||||||
#define ASPNETCORE_DEBUG_FLAG_INFO 0x00000001
|
|
||||||
#define ASPNETCORE_DEBUG_FLAG_WARNING 0x00000002
|
|
||||||
#define ASPNETCORE_DEBUG_FLAG_ERROR 0x00000004
|
|
||||||
|
|
||||||
extern DWORD g_dwAspNetCoreDebugFlags;
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
IfDebug(
|
|
||||||
DWORD dwFlag
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return ( dwFlag & g_dwAspNetCoreDebugFlags );
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
DebugPrint(
|
|
||||||
DWORD dwFlag,
|
|
||||||
LPCSTR szString
|
|
||||||
)
|
|
||||||
{
|
|
||||||
STACK_STRA (strOutput, 256);
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if ( IfDebug( dwFlag ) )
|
|
||||||
{
|
|
||||||
hr = strOutput.SafeSnprintf(
|
|
||||||
"[aspnetcore.dll] %s\r\n",
|
|
||||||
szString );
|
|
||||||
|
|
||||||
if (FAILED (hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputDebugStringA( strOutput.QueryStr() );
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
DebugPrintf(
|
|
||||||
DWORD dwFlag,
|
|
||||||
LPCSTR szFormat,
|
|
||||||
...
|
|
||||||
)
|
|
||||||
{
|
|
||||||
STACK_STRA (strCooked,256);
|
|
||||||
|
|
||||||
va_list args;
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if ( IfDebug( dwFlag ) )
|
|
||||||
{
|
|
||||||
va_start( args, szFormat );
|
|
||||||
|
|
||||||
hr = strCooked.SafeVsnprintf(szFormat, args );
|
|
||||||
|
|
||||||
va_end( args );
|
|
||||||
|
|
||||||
if (FAILED (hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugPrint( dwFlag, strCooked.QueryStr() );
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,131 +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
|
|
||||||
|
|
||||||
#define HOSTING_STARTUP_ASSEMBLIES_ENV_STR L"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES"
|
|
||||||
#define HOSTING_STARTUP_ASSEMBLIES_NAME L"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="
|
|
||||||
#define HOSTING_STARTUP_ASSEMBLIES_VALUE L"Microsoft.AspNetCore.Server.IISIntegration"
|
|
||||||
#define ASPNETCORE_IIS_AUTH_ENV_STR L"ASPNETCORE_IIS_HTTPAUTH="
|
|
||||||
#define ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED_ENV_STR L"ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED="
|
|
||||||
#define ASPNETCORE_IIS_AUTH_WINDOWS L"windows;"
|
|
||||||
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
|
|
||||||
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"
|
|
||||||
#define ASPNETCORE_IIS_AUTH_NONE L"none"
|
|
||||||
|
|
||||||
//
|
|
||||||
// The key used for hash-table lookups, consists of the port on which the http process is created.
|
|
||||||
//
|
|
||||||
|
|
||||||
class ENVIRONMENT_VAR_ENTRY
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ENVIRONMENT_VAR_ENTRY():
|
|
||||||
_cRefs(1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
Initialize(
|
|
||||||
PCWSTR pszName,
|
|
||||||
PCWSTR pszValue
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (FAILED(hr = _strName.Copy(pszName)) ||
|
|
||||||
FAILED(hr = _strValue.Copy(pszValue)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
Reference() const
|
|
||||||
{
|
|
||||||
InterlockedIncrement(&_cRefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
Dereference() const
|
|
||||||
{
|
|
||||||
if (InterlockedDecrement(&_cRefs) == 0)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PWSTR const
|
|
||||||
QueryName()
|
|
||||||
{
|
|
||||||
return _strName.QueryStr();
|
|
||||||
}
|
|
||||||
|
|
||||||
PWSTR const
|
|
||||||
QueryValue()
|
|
||||||
{
|
|
||||||
return _strValue.QueryStr();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
~ENVIRONMENT_VAR_ENTRY()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
STRU _strName;
|
|
||||||
STRU _strValue;
|
|
||||||
mutable LONG _cRefs;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ENVIRONMENT_VAR_HASH : public HASH_TABLE<ENVIRONMENT_VAR_ENTRY, PWSTR>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ENVIRONMENT_VAR_HASH()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PWSTR
|
|
||||||
ExtractKey(
|
|
||||||
ENVIRONMENT_VAR_ENTRY * pEntry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return pEntry->QueryName();
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
CalcKeyHash(
|
|
||||||
PWSTR pszName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return HashStringNoCase(pszName);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
EqualKeys(
|
|
||||||
PWSTR pszName1,
|
|
||||||
PWSTR pszName2
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return (_wcsicmp(pszName1, pszName2) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ReferenceRecord(
|
|
||||||
ENVIRONMENT_VAR_ENTRY * pEntry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pEntry->Reference();
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DereferenceRecord(
|
|
||||||
ENVIRONMENT_VAR_ENTRY * pEntry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pEntry->Dereference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
ENVIRONMENT_VAR_HASH(const ENVIRONMENT_VAR_HASH &);
|
|
||||||
void operator=(const ENVIRONMENT_VAR_HASH &);
|
|
||||||
};
|
|
||||||
|
|
@ -1,192 +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 "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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +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.
|
|
||||||
|
|
||||||
#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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,807 +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 "stdafx.h"
|
|
||||||
|
|
||||||
HOSTFXR_UTILITY::HOSTFXR_UTILITY()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HOSTFXR_UTILITY::~HOSTFXR_UTILITY()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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::GetStandaloneHostfxrParameters(
|
|
||||||
PCWSTR pwzExeAbsolutePath, // includes .exe file extension.
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
PCWSTR pcwzArguments,
|
|
||||||
HANDLE hEventLog,
|
|
||||||
_Inout_ STRU* struHostFxrDllLocation,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ PWSTR** ppwzArgv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU struDllPath;
|
|
||||||
STRU struArguments;
|
|
||||||
STRU struHostFxrPath;
|
|
||||||
STRU struRuntimeConfigLocation;
|
|
||||||
DWORD dwPosition;
|
|
||||||
|
|
||||||
// Obtain the app name from the processPath section.
|
|
||||||
if ( FAILED( hr = struDllPath.Copy( pwzExeAbsolutePath ) ) )
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwPosition = struDllPath.LastIndexOf( L'.', 0 );
|
|
||||||
if ( dwPosition == -1 )
|
|
||||||
{
|
|
||||||
hr = E_FAIL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = UTILITY::ConvertPathToFullPath( L".\\hostfxr.dll", pcwzApplicationPhysicalPath, &struHostFxrPath );
|
|
||||||
if ( FAILED( hr ) )
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
struDllPath.QueryStr()[dwPosition] = L'\0';
|
|
||||||
if (FAILED(hr = struDllPath.SyncWithBuffer()))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !UTILITY::CheckIfFileExists( struHostFxrPath.QueryStr() ) )
|
|
||||||
{
|
|
||||||
// Most likely a full framework app.
|
|
||||||
// Check that the runtime config file doesn't exist in the folder as another heuristic.
|
|
||||||
if (FAILED(hr = struRuntimeConfigLocation.Copy(struDllPath)) ||
|
|
||||||
FAILED(hr = struRuntimeConfigLocation.Append( L".runtimeconfig.json" )))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (!UTILITY::CheckIfFileExists(struRuntimeConfigLocation.QueryStr()))
|
|
||||||
{
|
|
||||||
|
|
||||||
hr = E_APPLICATION_ACTIVATION_EXEC_FAILURE;
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP,
|
|
||||||
ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP_MSG,
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
hr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If a runtime config file does exist, report a file not found on the app.exe
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND,
|
|
||||||
ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_MSG,
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struHostFxrDllLocation->Copy(struHostFxrPath)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (FAILED(hr = struDllPath.Append(L".dll")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UTILITY::CheckIfFileExists(struDllPath.QueryStr()))
|
|
||||||
{
|
|
||||||
// Treat access issue as File not found
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struArguments.Copy(struDllPath)) ||
|
|
||||||
FAILED(hr = struArguments.Append(L" ")) ||
|
|
||||||
FAILED(hr = struArguments.Append(pcwzArguments)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = ParseHostfxrArguments(
|
|
||||||
struArguments.QueryStr(),
|
|
||||||
pwzExeAbsolutePath,
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
hEventLog,
|
|
||||||
pdwArgCount,
|
|
||||||
ppwzArgv)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
HOSTFXR_UTILITY::GetHostFxrParameters(
|
|
||||||
HANDLE hEventLog,
|
|
||||||
PCWSTR pcwzProcessPath,
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
PCWSTR pcwzArguments,
|
|
||||||
_Inout_ STRU* struHostFxrDllLocation,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ BSTR** pbstrArgv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU struSystemPathVariable;
|
|
||||||
STRU struAbsolutePathToHostFxr;
|
|
||||||
STRU struAbsolutePathToDotnet;
|
|
||||||
STRU struEventMsg;
|
|
||||||
STACK_STRU(struExpandedProcessPath, MAX_PATH);
|
|
||||||
STACK_STRU(struExpandedArguments, MAX_PATH);
|
|
||||||
|
|
||||||
// Copy and Expand the processPath and Arguments.
|
|
||||||
if (FAILED(hr = struExpandedProcessPath.CopyAndExpandEnvironmentStrings(pcwzProcessPath))
|
|
||||||
|| FAILED(hr = struExpandedArguments.CopyAndExpandEnvironmentStrings(pcwzArguments)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the process path an absolute path to our current application directory.
|
|
||||||
// If the path is already an absolute path, it will be unchanged.
|
|
||||||
hr = UTILITY::ConvertPathToFullPath(
|
|
||||||
struExpandedProcessPath.QueryStr(),
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
&struAbsolutePathToDotnet
|
|
||||||
);
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the absolute path is to dotnet or not.
|
|
||||||
if (struAbsolutePathToDotnet.EndsWith(L"dotnet.exe") || struAbsolutePathToDotnet.EndsWith(L"dotnet"))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// The processPath ends with dotnet.exe or dotnet
|
|
||||||
// like: C:\Program Files\dotnet\dotnet.exe, C:\Program Files\dotnet\dotnet, dotnet.exe, or dotnet.
|
|
||||||
// Get the absolute path to dotnet. If the path is already an absolute path, it will return that path
|
|
||||||
//
|
|
||||||
if (FAILED(hr = HOSTFXR_UTILITY::GetAbsolutePathToDotnet(&struAbsolutePathToDotnet))) // Make sure to append the dotnet.exe path correctly here (pass in regular path)?
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = GetAbsolutePathToHostFxr(&struAbsolutePathToDotnet, hEventLog, &struAbsolutePathToHostFxr)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = ParseHostfxrArguments(
|
|
||||||
struExpandedArguments.QueryStr(),
|
|
||||||
struAbsolutePathToDotnet.QueryStr(),
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
hEventLog,
|
|
||||||
pdwArgCount,
|
|
||||||
pbstrArgv)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struHostFxrDllLocation->Copy(struAbsolutePathToHostFxr)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// The processPath is a path to the application executable
|
|
||||||
// like: C:\test\MyApp.Exe or MyApp.Exe
|
|
||||||
// Check if the file exists, and if it does, get the parameters for a standalone application
|
|
||||||
//
|
|
||||||
if (UTILITY::CheckIfFileExists(struAbsolutePathToDotnet.QueryStr()))
|
|
||||||
{
|
|
||||||
hr = GetStandaloneHostfxrParameters(
|
|
||||||
struAbsolutePathToDotnet.QueryStr(),
|
|
||||||
pcwzApplicationPhysicalPath,
|
|
||||||
struExpandedArguments.QueryStr(),
|
|
||||||
hEventLog,
|
|
||||||
struHostFxrDllLocation,
|
|
||||||
pdwArgCount,
|
|
||||||
pbstrArgv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// If the processPath file does not exist and it doesn't include dotnet.exe or dotnet
|
|
||||||
// then it is an invalid argument.
|
|
||||||
//
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);;
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_GENERAL_ERROR_MSG,
|
|
||||||
ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG,
|
|
||||||
struExpandedProcessPath.QueryStr(),
|
|
||||||
hr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Forms the argument list in HOSTFXR_PARAMETERS.
|
|
||||||
// Sets the ArgCount and Arguments.
|
|
||||||
// Arg structure:
|
|
||||||
// argv[0] = Path to exe activating hostfxr.
|
|
||||||
// argv[1] = L"exec"
|
|
||||||
// argv[2] = absolute path to dll.
|
|
||||||
//
|
|
||||||
HRESULT
|
|
||||||
HOSTFXR_UTILITY::ParseHostfxrArguments(
|
|
||||||
PCWSTR pwzArgumentsFromConfig,
|
|
||||||
PCWSTR pwzExePath,
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
HANDLE hEventLog,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ BSTR** pbstrArgv
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNREFERENCED_PARAMETER( hEventLog ); // TODO use event log to set errors.
|
|
||||||
|
|
||||||
DBG_ASSERT(dwArgCount != NULL);
|
|
||||||
DBG_ASSERT(pwzArgv != NULL);
|
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
INT argc = 0;
|
|
||||||
BSTR* argv = NULL;
|
|
||||||
LPWSTR* pwzArgs = NULL;
|
|
||||||
STRU struTempPath;
|
|
||||||
INT intArgsProcessed = 0;
|
|
||||||
|
|
||||||
// If we call CommandLineToArgvW with an empty string, argc is 5 for some interesting reason.
|
|
||||||
// Protectively guard against this by check if the string is null or empty.
|
|
||||||
if (pwzArgumentsFromConfig == NULL || wcscmp(pwzArgumentsFromConfig, L"") == 0)
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pwzArgs = CommandLineToArgvW(pwzArgumentsFromConfig, &argc);
|
|
||||||
|
|
||||||
if (pwzArgs == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv = new BSTR[argc + 1];
|
|
||||||
if (argv == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[0] = SysAllocString(pwzExePath);
|
|
||||||
|
|
||||||
if (argv[0] == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to convert the application dll from a relative to an absolute path
|
|
||||||
// Don't record this failure as pwzArgs[0] may already be an absolute path to the dll.
|
|
||||||
for (intArgsProcessed = 0; intArgsProcessed < argc; intArgsProcessed++)
|
|
||||||
{
|
|
||||||
struTempPath.Copy(pwzArgs[intArgsProcessed]);
|
|
||||||
if (struTempPath.EndsWith(L".dll"))
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(UTILITY::ConvertPathToFullPath(pwzArgs[intArgsProcessed], pcwzApplicationPhysicalPath, &struTempPath)))
|
|
||||||
{
|
|
||||||
argv[intArgsProcessed + 1] = SysAllocString(struTempPath.QueryStr());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
argv[intArgsProcessed + 1] = SysAllocString(pwzArgs[intArgsProcessed]);
|
|
||||||
}
|
|
||||||
if (argv[intArgsProcessed + 1] == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
argv[intArgsProcessed + 1] = SysAllocString(pwzArgs[intArgsProcessed]);
|
|
||||||
if (argv[intArgsProcessed + 1] == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*pbstrArgv = argv;
|
|
||||||
*pdwArgCount = argc + 1;
|
|
||||||
|
|
||||||
goto Finished;
|
|
||||||
|
|
||||||
Failure:
|
|
||||||
if (argv != NULL)
|
|
||||||
{
|
|
||||||
// intArgsProcess - 1 here as if we fail to allocated the ith string
|
|
||||||
// we don't want to free it.
|
|
||||||
for (INT i = 0; i < intArgsProcessed - 1; i++)
|
|
||||||
{
|
|
||||||
SysFreeString(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] argv;
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
if (pwzArgs != NULL)
|
|
||||||
{
|
|
||||||
LocalFree(pwzArgs);
|
|
||||||
DBG_ASSERT(pwzArgs == NULL);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
HOSTFXR_UTILITY::GetAbsolutePathToDotnet(
|
|
||||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If we are given an absolute path to dotnet.exe, we are done
|
|
||||||
//
|
|
||||||
if (UTILITY::CheckIfFileExists(pStruAbsolutePathToDotnet->QueryStr()))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If the path was C:\Program Files\dotnet\dotnet
|
|
||||||
// We need to try appending .exe and check if the file exists too.
|
|
||||||
//
|
|
||||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Append(L".exe")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UTILITY::CheckIfFileExists(pStruAbsolutePathToDotnet->QueryStr()))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, we are calling where.exe to find dotnet.
|
|
||||||
// If we encounter any failures, try getting dotnet.exe from the
|
|
||||||
// backup location.
|
|
||||||
if (!InvokeWhereToFindDotnet(pStruAbsolutePathToDotnet))
|
|
||||||
{
|
|
||||||
hr = GetAbsolutePathToDotnetFromProgramFiles(pStruAbsolutePathToDotnet);
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
HOSTFXR_UTILITY::GetAbsolutePathToHostFxr(
|
|
||||||
STRU* pStruAbsolutePathToDotnet,
|
|
||||||
HANDLE hEventLog,
|
|
||||||
STRU* pStruAbsolutePathToHostfxr
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU struHostFxrPath;
|
|
||||||
STRU struHostFxrSearchExpression;
|
|
||||||
STRU struHighestDotnetVersion;
|
|
||||||
STRU struEventMsg;
|
|
||||||
std::vector<std::wstring> vVersionFolders;
|
|
||||||
DWORD dwPosition = 0;
|
|
||||||
|
|
||||||
if (FAILED(hr = struHostFxrPath.Copy(pStruAbsolutePathToDotnet)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwPosition = struHostFxrPath.LastIndexOf(L'\\', 0);
|
|
||||||
if (dwPosition == -1)
|
|
||||||
{
|
|
||||||
hr = E_FAIL;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
struHostFxrPath.QueryStr()[dwPosition] = L'\0';
|
|
||||||
|
|
||||||
if (FAILED(hr = struHostFxrPath.SyncWithBuffer()) ||
|
|
||||||
FAILED(hr = struHostFxrPath.Append(L"\\")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = struHostFxrPath.Append(L"host\\fxr");
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UTILITY::DirectoryExists(&struHostFxrPath))
|
|
||||||
{
|
|
||||||
hr = ERROR_BAD_ENVIRONMENT;
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND,
|
|
||||||
struEventMsg.QueryStr(),
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG,
|
|
||||||
struHostFxrPath.QueryStr(),
|
|
||||||
hr);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all folders under host\\fxr\\ for version numbers.
|
|
||||||
hr = struHostFxrSearchExpression.Copy(struHostFxrPath);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = struHostFxrSearchExpression.Append(L"\\*");
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As we use the logic from core-setup, we are opting to use std here.
|
|
||||||
UTILITY::FindDotNetFolders(struHostFxrSearchExpression.QueryStr(), &vVersionFolders);
|
|
||||||
|
|
||||||
if (vVersionFolders.size() == 0)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_BAD_ENVIRONMENT);
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND,
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG,
|
|
||||||
struHostFxrPath.QueryStr(),
|
|
||||||
hr);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = UTILITY::FindHighestDotNetVersion(vVersionFolders, &struHighestDotnetVersion);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = struHostFxrPath.Append(L"\\"))
|
|
||||||
|| FAILED(hr = struHostFxrPath.Append(struHighestDotnetVersion.QueryStr()))
|
|
||||||
|| FAILED(hr = struHostFxrPath.Append(L"\\hostfxr.dll")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UTILITY::CheckIfFileExists(struHostFxrPath.QueryStr()))
|
|
||||||
{
|
|
||||||
// ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID);
|
|
||||||
UTILITY::LogEventF(hEventLog,
|
|
||||||
EVENTLOG_ERROR_TYPE,
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND,
|
|
||||||
ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG,
|
|
||||||
struHostFxrPath.QueryStr(),
|
|
||||||
hr);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = pStruAbsolutePathToHostfxr->Copy(struHostFxrPath)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tries to call where.exe to find the location of dotnet.exe.
|
|
||||||
// Will check that the bitness of dotnet matches the current
|
|
||||||
// worker process bitness.
|
|
||||||
// Returns true if a valid dotnet was found, else false.
|
|
||||||
//
|
|
||||||
BOOL
|
|
||||||
HOSTFXR_UTILITY::InvokeWhereToFindDotnet(
|
|
||||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
// Arguments to call where.exe
|
|
||||||
STARTUPINFOW startupInfo = { 0 };
|
|
||||||
PROCESS_INFORMATION processInformation = { 0 };
|
|
||||||
SECURITY_ATTRIBUTES securityAttributes;
|
|
||||||
|
|
||||||
CHAR pzFileContents[READ_BUFFER_SIZE];
|
|
||||||
HANDLE hStdOutReadPipe = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE hStdOutWritePipe = INVALID_HANDLE_VALUE;
|
|
||||||
LPWSTR pwzDotnetName = NULL;
|
|
||||||
DWORD dwFilePointer;
|
|
||||||
BOOL fIsWow64Process;
|
|
||||||
BOOL fIsCurrentProcess64Bit;
|
|
||||||
DWORD dwExitCode;
|
|
||||||
STRU struDotnetSubstring;
|
|
||||||
STRU struDotnetLocationsString;
|
|
||||||
DWORD dwNumBytesRead;
|
|
||||||
DWORD dwBinaryType;
|
|
||||||
INT index = 0;
|
|
||||||
INT prevIndex = 0;
|
|
||||||
BOOL fProcessCreationResult = FALSE;
|
|
||||||
BOOL fResult = FALSE;
|
|
||||||
|
|
||||||
// Set the security attributes for the read/write pipe
|
|
||||||
securityAttributes.nLength = sizeof(securityAttributes);
|
|
||||||
securityAttributes.lpSecurityDescriptor = NULL;
|
|
||||||
securityAttributes.bInheritHandle = TRUE;
|
|
||||||
|
|
||||||
// Reset the path to dotnet as we will be using whether the string is
|
|
||||||
// empty or not as state
|
|
||||||
pStruAbsolutePathToDotnet->Reset();
|
|
||||||
|
|
||||||
// Create a read/write pipe that will be used for reading the result of where.exe
|
|
||||||
if (!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0))
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (!SetHandleInformation(hStdOutReadPipe, HANDLE_FLAG_INHERIT, 0))
|
|
||||||
{
|
|
||||||
hr = ERROR_FILE_INVALID;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the stdout and err pipe to the write pipes.
|
|
||||||
startupInfo.cb = sizeof(startupInfo);
|
|
||||||
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
|
||||||
startupInfo.hStdOutput = hStdOutWritePipe;
|
|
||||||
startupInfo.hStdError = hStdOutWritePipe;
|
|
||||||
|
|
||||||
// CreateProcess requires a mutable string to be passed to commandline
|
|
||||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083/
|
|
||||||
pwzDotnetName = SysAllocString(L"\"where.exe\" dotnet.exe");
|
|
||||||
if (pwzDotnetName == NULL)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a process to invoke where.exe
|
|
||||||
fProcessCreationResult = CreateProcessW(NULL,
|
|
||||||
pwzDotnetName,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
TRUE,
|
|
||||||
CREATE_NO_WINDOW,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&startupInfo,
|
|
||||||
&processInformation
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!fProcessCreationResult)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for where.exe to return, waiting 2 seconds.
|
|
||||||
if (WaitForSingleObject(processInformation.hProcess, 2000) != WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
// Timeout occured, terminate the where.exe process and return.
|
|
||||||
TerminateProcess(processInformation.hProcess, 2);
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// where.exe will return 0 on success, 1 if the file is not found
|
|
||||||
// and 2 if there was an error. Check if the exit code is 1 and set
|
|
||||||
// a new hr result saying it couldn't find dotnet.exe
|
|
||||||
//
|
|
||||||
if (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// In this block, if anything fails, we will goto our fallback of
|
|
||||||
// looking in C:/Program Files/
|
|
||||||
//
|
|
||||||
if (dwExitCode != 0)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Where succeeded.
|
|
||||||
// Reset file pointer to the beginning of the file.
|
|
||||||
dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN);
|
|
||||||
if (dwFilePointer == INVALID_SET_FILE_POINTER)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang.
|
|
||||||
// TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block.
|
|
||||||
//
|
|
||||||
if (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dwNumBytesRead >= READ_BUFFER_SIZE)
|
|
||||||
{
|
|
||||||
// This shouldn't ever be this large. We could continue to call ReadFile in a loop,
|
|
||||||
// however if someone had this many dotnet.exes on their machine.
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
if (FAILED(hr = struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the bitness of the currently running process
|
|
||||||
// matches the dotnet.exe found.
|
|
||||||
if (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process))
|
|
||||||
{
|
|
||||||
// Calling IsWow64Process failed
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (fIsWow64Process)
|
|
||||||
{
|
|
||||||
// 32 bit mode
|
|
||||||
fIsCurrentProcess64Bit = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check the SystemInfo to see if we are currently 32 or 64 bit.
|
|
||||||
SYSTEM_INFO systemInfo;
|
|
||||||
GetNativeSystemInfo(&systemInfo);
|
|
||||||
fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex);
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (FAILED(hr = struDotnetSubstring.Copy(&struDotnetLocationsString.QueryStr()[prevIndex], index - prevIndex)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
// \r\n is two wchars, so add 2 here.
|
|
||||||
prevIndex = index + 2;
|
|
||||||
|
|
||||||
if (GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType) &&
|
|
||||||
fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
|
|
||||||
{
|
|
||||||
// The bitness of dotnet matched with the current worker process bitness.
|
|
||||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Copy(struDotnetSubstring)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
fResult = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (hStdOutReadPipe != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(hStdOutReadPipe);
|
|
||||||
}
|
|
||||||
if (hStdOutWritePipe != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(hStdOutWritePipe);
|
|
||||||
}
|
|
||||||
if (processInformation.hProcess != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(processInformation.hProcess);
|
|
||||||
}
|
|
||||||
if (processInformation.hThread != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
CloseHandle(processInformation.hThread);
|
|
||||||
}
|
|
||||||
if (pwzDotnetName != NULL)
|
|
||||||
{
|
|
||||||
SysFreeString(pwzDotnetName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
HOSTFXR_UTILITY::GetAbsolutePathToDotnetFromProgramFiles(
|
|
||||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
BOOL fFound = FALSE;
|
|
||||||
DWORD dwNumBytesRead = 0;
|
|
||||||
DWORD dwPathSize = MAX_PATH;
|
|
||||||
STRU struDotnetSubstring;
|
|
||||||
|
|
||||||
while (!fFound)
|
|
||||||
{
|
|
||||||
if (FAILED(hr = struDotnetSubstring.Resize(dwPathSize)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwNumBytesRead = GetEnvironmentVariable(L"ProgramFiles", struDotnetSubstring.QueryStr(), dwPathSize);
|
|
||||||
if (dwNumBytesRead == 0)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
else if (dwNumBytesRead >= dwPathSize)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// The path to ProgramFiles should never be this long, but resize and try again.
|
|
||||||
dwPathSize *= 2 + 30; // for dotnet substring
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FAILED(hr = struDotnetSubstring.SyncWithBuffer()) ||
|
|
||||||
FAILED(hr = struDotnetSubstring.Append(L"\\dotnet\\dotnet.exe")))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (!UTILITY::CheckIfFileExists(struDotnetSubstring.QueryStr()))
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
if (FAILED(hr = pStruAbsolutePathToDotnet->Copy(struDotnetSubstring)))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
fFound = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
typedef INT(*hostfxr_get_native_search_directories_fn) (CONST INT argc, CONST PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size);
|
|
||||||
typedef INT(*hostfxr_main_fn) (CONST DWORD argc, CONST PCWSTR argv[]);
|
|
||||||
|
|
||||||
#define READ_BUFFER_SIZE 4096
|
|
||||||
|
|
||||||
class HOSTFXR_UTILITY
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HOSTFXR_UTILITY();
|
|
||||||
~HOSTFXR_UTILITY();
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetHostFxrParameters(
|
|
||||||
HANDLE hEventLog,
|
|
||||||
PCWSTR pcwzProcessPath,
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
PCWSTR pcwzArguments,
|
|
||||||
_Inout_ STRU* pStruHostFxrDllLocation,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ BSTR** ppwzArgv
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetStandaloneHostfxrParameters(
|
|
||||||
PCWSTR pwzExeAbsolutePath, // includes .exe file extension.
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
PCWSTR pcwzArguments,
|
|
||||||
HANDLE hEventLog,
|
|
||||||
_Inout_ STRU* pStruHostFxrDllLocation,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ BSTR** ppwzArgv
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
ParseHostfxrArguments(
|
|
||||||
PCWSTR pwzArgumentsFromConfig,
|
|
||||||
PCWSTR pwzExePath,
|
|
||||||
PCWSTR pcwzApplicationPhysicalPath,
|
|
||||||
HANDLE hEventLog,
|
|
||||||
_Out_ DWORD* pdwArgCount,
|
|
||||||
_Out_ BSTR** ppwzArgv
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetAbsolutePathToDotnet(
|
|
||||||
STRU* pStruAbsolutePathToDotnet
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetAbsolutePathToHostFxr(
|
|
||||||
_In_ STRU* pStruAbsolutePathToDotnet,
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_Out_ STRU* pStruAbsolutePathToHostfxr
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
InvokeWhereToFindDotnet(
|
|
||||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetAbsolutePathToDotnetFromProgramFiles(
|
|
||||||
_Inout_ STRU* pStruAbsolutePathToDotnet
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,44 +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 "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +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 "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,47 +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
|
|
||||||
|
|
||||||
#define IDS_INVALID_PROPERTY 1000
|
|
||||||
#define IDS_SERVER_ERROR 1001
|
|
||||||
|
|
||||||
#define ASPNETCORE_EVENT_PROVIDER L"IIS AspNetCore Module"
|
|
||||||
#define ASPNETCORE_IISEXPRESS_EVENT_PROVIDER L"IIS Express AspNetCore Module"
|
|
||||||
|
|
||||||
#define ASPNETCORE_EVENT_MSG_BUFFER_SIZE 256
|
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_SUCCESS_MSG L"Application '%s' started process '%d' successfully and process '%d' 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_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' at stage '%s', ErrorCode = '0x%x', assigned port %d, retryCounter '%d'."
|
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_FAILURE_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' with multiple retries. The last try of listening port is '%d'. See pervious warnings for details."
|
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_STATUS_ERROR_MSG L"Application '%s' with physical root '%s' failed to start process with commandline '%s' , ErrorCode = '0x%x', processId '%d', processStatus '%d'."
|
|
||||||
#define ASPNETCORE_EVENT_PROCESS_START_PORTSETUP_ERROR_MSG L"Application '%s' with physical root '%s' failed to choose listen port '%d' given port rang '%d - %d', EorrorCode = '0x%x'. If environment variable 'ASPNETCORE_PORT' was set, try removing it such that a random port is selected instead."
|
|
||||||
#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 respond or did not listen on the given port '%d', ErrorCode = '0x%x'"
|
|
||||||
#define ASPNETCORE_EVENT_PROCESS_SHUTDOWN_MSG L"Application '%s' with physical root '%s' shut down process with Id '%d' listening on port '%d'"
|
|
||||||
#define ASPNETCORE_EVENT_INVALID_STDOUT_LOG_FILE_MSG L"Warning: Could not create stdoutLogFile %s, ErrorCode = '0x%x'."
|
|
||||||
#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_APP_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown application '%s'."
|
|
||||||
#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 '%d' 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_STDERR_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x. First 4KB characters of captured stderr logs on startup:\r\n%s"
|
|
||||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x. Last 4KB characters of captured stdout and stderr logs:\r\n%s"
|
|
||||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXIT_MSG L"Application '%s' with physical root '%s' hit unexpected managed background thread exit, ErrorCode = '0x%x. Please check the stderr logs for more information."
|
|
||||||
#define ASPNETCORE_EVENT_APP_IN_SHUTDOWN_MSG L"Application shutting down."
|
|
||||||
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_MSG L"Application '%s' was recycled after detecting the app_offline file."
|
|
||||||
#define ASPNETCORE_EVENT_RECYCLE_APPOFFLINE_REMOVED_MSG L"App_offline.htm has been removed from the application. Application will be recycled."
|
|
||||||
#define ASPNETCORE_EVENT_RECYCLE_CONFIGURATION_MSG L"Application '%s' was recycled due to configuration change"
|
|
||||||
#define ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG L"Failed to recycle application due to a configuration change at '%s'. Recycling worker process."
|
|
||||||
#define ASPNETCORE_EVENT_MODULE_DISABLED_MSG L"AspNetCore Module is disabled"
|
|
||||||
#define ASPNETCORE_EVENT_INPROCESS_FULL_FRAMEWORK_APP_MSG L"Application '%s' was compiled for .NET Framework. Please compile for .NET core to run the inprocess application or change the process mode to out of process. ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_PORTABLE_APP_DOTNET_MISSING_MSG L"Could not find dotnet.exe on the system PATH environment variable for portable application '%s'. Check that a valid path to dotnet is on the PATH and the bitness of dotnet matches the bitness of the IIS worker process. ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_HOSTFXR_DIRECTORY_NOT_FOUND_MSG L"Could not find the hostfxr directory '%s' in the dotnet directory. ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_HOSTFXR_DLL_NOT_FOUND_MSG L"Could not find hostfxr.dll in '%s'. ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_APPLICATION_EXE_NOT_FOUND_MSG L"Could not find application executable in '%s'. ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, ErrorCode = '0x%x. Please check the stderr logs for more information."
|
|
||||||
#define ASPNETCORE_EVENT_INVALID_PROCESS_PATH_MSG L"Invalid or unknown processPath provided in web.config: processPath = %s, ErrorCode = '0x%x'."
|
|
||||||
#define ASPNETCORE_EVENT_INPROCESS_RH_MISSING_MSG L"Could not find the aspnetcorerh.dll for in-process application. Please confirm the Microsoft.AspNetCore.Server.IIS package is referenced in your application."
|
|
||||||
#define ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG L"Could not find the aspnetcorerh.dll for out-of-process application. Please confirm the aspnetcorerh.dll is installed in installed globally for IIS or IISExpress."
|
|
||||||
|
|
@ -1,4 +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 "stdafx.h"
|
|
||||||
|
|
@ -1,34 +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 "targetver.h"
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <httpserv.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <shellapi.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include "Shlwapi.h"
|
|
||||||
#include "..\IISLib\hashtable.h"
|
|
||||||
#include "..\IISLib\stringu.h"
|
|
||||||
#include "..\IISLib\stringa.h"
|
|
||||||
#include "..\IISLib\multisz.h"
|
|
||||||
#include "..\IISLib\dbgutil.h"
|
|
||||||
#include "..\IISLib\ahutil.h"
|
|
||||||
#include "..\IISLib\hashfn.h"
|
|
||||||
#include "SRWLockWrapper.h"
|
|
||||||
#include "environmentvariablehash.h"
|
|
||||||
#include "utility.h"
|
|
||||||
#include "aspnetcoreconfig.h"
|
|
||||||
#include "application.h"
|
|
||||||
#include "requesthandler.h"
|
|
||||||
#include "fx_ver.h"
|
|
||||||
#include "hostfxr_utility.h"
|
|
||||||
#include "resources.h"
|
|
||||||
#include "aspnetcore_msg.h"
|
|
||||||
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
|
||||||
|
|
||||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
|
||||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
|
||||||
|
|
||||||
#include <SDKDDKVer.h>
|
|
||||||
|
|
@ -1,656 +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"stdafx.h"
|
|
||||||
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
UTILITY::SplitUrl(
|
|
||||||
PCWSTR pszDestinationUrl,
|
|
||||||
BOOL *pfSecure,
|
|
||||||
STRU *pstrDestination,
|
|
||||||
STRU *pstrUrl
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Split the URL specified for forwarding into its specific components
|
|
||||||
The format of the URL looks like
|
|
||||||
http[s]://destination[:port]/path
|
|
||||||
when port is omitted, the default port for that specific protocol is used
|
|
||||||
when host is omitted, it gets the same value as the destination
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pszDestinationUrl - the url to be split up
|
|
||||||
pfSecure - SSL to be used in forwarding?
|
|
||||||
pstrDestination - destination
|
|
||||||
pDestinationPort - port
|
|
||||||
pstrUrl - URL
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
//
|
|
||||||
// First determine if the target is secure
|
|
||||||
//
|
|
||||||
if (_wcsnicmp(pszDestinationUrl, L"http://", 7) == 0)
|
|
||||||
{
|
|
||||||
*pfSecure = FALSE;
|
|
||||||
pszDestinationUrl += 7;
|
|
||||||
}
|
|
||||||
else if (_wcsnicmp(pszDestinationUrl, L"https://", 8) == 0)
|
|
||||||
{
|
|
||||||
*pfSecure = TRUE;
|
|
||||||
pszDestinationUrl += 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*pszDestinationUrl == L'\0')
|
|
||||||
{
|
|
||||||
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find the 3rd slash corresponding to the url
|
|
||||||
//
|
|
||||||
LPCWSTR pszSlash = wcschr(pszDestinationUrl, L'/');
|
|
||||||
if (pszSlash == NULL)
|
|
||||||
{
|
|
||||||
if (FAILED(hr = pstrUrl->Copy(L"/", 1)) ||
|
|
||||||
FAILED(hr = pstrDestination->Copy(pszDestinationUrl)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FAILED(hr = pstrUrl->Copy(pszSlash)) ||
|
|
||||||
FAILED(hr = pstrDestination->Copy(pszDestinationUrl,
|
|
||||||
(DWORD)(pszSlash - pszDestinationUrl))))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change a hexadecimal digit to its numerical equivalent
|
|
||||||
#define TOHEX( ch ) \
|
|
||||||
((ch) > L'9' ? \
|
|
||||||
(ch) >= L'a' ? \
|
|
||||||
(ch) - L'a' + 10 : \
|
|
||||||
(ch) - L'A' + 10 \
|
|
||||||
: (ch) - L'0')
|
|
||||||
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
UTILITY::UnEscapeUrl(
|
|
||||||
PCWSTR pszUrl,
|
|
||||||
DWORD cchUrl,
|
|
||||||
bool fCopyQuery,
|
|
||||||
STRA * pstrResult
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
CHAR pch[2];
|
|
||||||
pch[1] = '\0';
|
|
||||||
DWORD cchStart = 0;
|
|
||||||
DWORD index = 0;
|
|
||||||
|
|
||||||
while (index < cchUrl &&
|
|
||||||
(fCopyQuery || pszUrl[index] != L'?'))
|
|
||||||
{
|
|
||||||
switch (pszUrl[index])
|
|
||||||
{
|
|
||||||
case L'%':
|
|
||||||
if (iswxdigit(pszUrl[index+1]) && iswxdigit(pszUrl[index+2]))
|
|
||||||
{
|
|
||||||
if (index > cchStart &&
|
|
||||||
FAILED(hr = pstrResult->AppendW(pszUrl + cchStart,
|
|
||||||
index - cchStart)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
cchStart = index+3;
|
|
||||||
|
|
||||||
pch[0] = static_cast<CHAR>(TOHEX(pszUrl[index+1]) * 16 +
|
|
||||||
TOHEX(pszUrl[index+2]));
|
|
||||||
if (FAILED(hr = pstrResult->Append(pch, 1)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
index += 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
__fallthrough;
|
|
||||||
default:
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > cchStart)
|
|
||||||
{
|
|
||||||
return pstrResult->AppendW(pszUrl + cchStart,
|
|
||||||
index - cchStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
UTILITY::UnEscapeUrl(
|
|
||||||
PCWSTR pszUrl,
|
|
||||||
DWORD cchUrl,
|
|
||||||
STRU * pstrResult
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
WCHAR pch[2];
|
|
||||||
pch[1] = L'\0';
|
|
||||||
DWORD cchStart = 0;
|
|
||||||
DWORD index = 0;
|
|
||||||
bool fInQuery = FALSE;
|
|
||||||
|
|
||||||
while (index < cchUrl)
|
|
||||||
{
|
|
||||||
switch (pszUrl[index])
|
|
||||||
{
|
|
||||||
case L'%':
|
|
||||||
if (iswxdigit(pszUrl[index+1]) && iswxdigit(pszUrl[index+2]))
|
|
||||||
{
|
|
||||||
if (index > cchStart &&
|
|
||||||
FAILED(hr = pstrResult->Append(pszUrl + cchStart,
|
|
||||||
index - cchStart)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
cchStart = index+3;
|
|
||||||
|
|
||||||
pch[0] = static_cast<WCHAR>(TOHEX(pszUrl[index+1]) * 16 +
|
|
||||||
TOHEX(pszUrl[index+2]));
|
|
||||||
if (FAILED(hr = pstrResult->Append(pch, 1)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
index += 3;
|
|
||||||
if (pch[0] == L'?')
|
|
||||||
{
|
|
||||||
fInQuery = TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case L'/':
|
|
||||||
if (fInQuery)
|
|
||||||
{
|
|
||||||
if (index > cchStart &&
|
|
||||||
FAILED(hr = pstrResult->Append(pszUrl + cchStart,
|
|
||||||
index - cchStart)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
cchStart = index+1;
|
|
||||||
|
|
||||||
if (FAILED(hr = pstrResult->Append(L"\\", 1)))
|
|
||||||
{
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
index += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
__fallthrough;
|
|
||||||
default:
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > cchStart)
|
|
||||||
{
|
|
||||||
return pstrResult->Append(pszUrl + cchStart,
|
|
||||||
index - cchStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
UTILITY::EscapeAbsPath(
|
|
||||||
IHttpRequest * pRequest,
|
|
||||||
STRU * strEscapedUrl
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU strAbsPath;
|
|
||||||
LPCWSTR pszAbsPath = NULL;
|
|
||||||
LPCWSTR pszFindStr = NULL;
|
|
||||||
|
|
||||||
hr = strAbsPath.Copy( pRequest->GetRawHttpRequest()->CookedUrl.pAbsPath,
|
|
||||||
pRequest->GetRawHttpRequest()->CookedUrl.AbsPathLength / sizeof(WCHAR) );
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszAbsPath = strAbsPath.QueryStr();
|
|
||||||
pszFindStr = wcschr(pszAbsPath, L'?');
|
|
||||||
|
|
||||||
while(pszFindStr != NULL)
|
|
||||||
{
|
|
||||||
strEscapedUrl->Append( pszAbsPath, pszFindStr - pszAbsPath);
|
|
||||||
strEscapedUrl->Append(L"%3F");
|
|
||||||
pszAbsPath = pszFindStr + 1;
|
|
||||||
pszFindStr = wcschr(pszAbsPath, L'?');
|
|
||||||
}
|
|
||||||
|
|
||||||
strEscapedUrl->Append(pszAbsPath);
|
|
||||||
strEscapedUrl->Append(pRequest->GetRawHttpRequest()->CookedUrl.pQueryString,
|
|
||||||
pRequest->GetRawHttpRequest()->CookedUrl.QueryStringLength / sizeof(WCHAR));
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool
|
|
||||||
UTILITY::IsValidAttributeNameChar(
|
|
||||||
WCHAR ch
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Values based on ASP.NET rendering for cookie names. RFC 2965 is not clear
|
|
||||||
// what the non-special characters are.
|
|
||||||
//
|
|
||||||
return ch == L'\t' || (ch > 31 && ch < 127);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool
|
|
||||||
UTILITY::FindInMultiString(
|
|
||||||
PCWSTR pszMultiString,
|
|
||||||
PCWSTR pszStringToFind
|
|
||||||
)
|
|
||||||
{
|
|
||||||
while (*pszMultiString != L'\0')
|
|
||||||
{
|
|
||||||
if (wcscmp(pszMultiString, pszStringToFind) == 0)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
pszMultiString += wcslen(pszMultiString) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool
|
|
||||||
UTILITY::IsValidQueryStringName(
|
|
||||||
PCWSTR pszName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
while (*pszName != L'\0')
|
|
||||||
{
|
|
||||||
WCHAR c = *pszName;
|
|
||||||
if (c != L'-' && c != L'_' && c != L'+' &&
|
|
||||||
c != L'.' && c != L'*' && c != L'$' && c != L'%' && c != L',' &&
|
|
||||||
!iswalnum(c))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
pszName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool
|
|
||||||
UTILITY::IsValidHeaderName(
|
|
||||||
PCWSTR pszName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
while (*pszName != L'\0')
|
|
||||||
{
|
|
||||||
WCHAR c = *pszName;
|
|
||||||
if (c != L'-' && c != L'_' && c != L'+' &&
|
|
||||||
c != L'.' && c != L'*' && c != L'$' && c != L'%'
|
|
||||||
&& !iswalnum(c))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
pszName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
UTILITY::IsPathUnc(
|
|
||||||
__in LPCWSTR pszPath,
|
|
||||||
__out BOOL * pfIsUnc
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU strTempPath;
|
|
||||||
|
|
||||||
if ( pszPath == NULL || pfIsUnc == NULL )
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = MakePathCanonicalizationProof( (LPWSTR) pszPath, &strTempPath );
|
|
||||||
if ( FAILED(hr) )
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// MakePathCanonicalizationProof will map \\?\UNC, \\.\UNC and \\ to \\?\UNC
|
|
||||||
//
|
|
||||||
(*pfIsUnc) = ( _wcsnicmp( strTempPath.QueryStr(), L"\\\\?\\UNC\\", 8 /* sizeof \\?\UNC\ */) == 0 );
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
UTILITY::ConvertPathToFullPath(
|
|
||||||
_In_ LPCWSTR pszPath,
|
|
||||||
_In_ LPCWSTR pszRootPath,
|
|
||||||
_Out_ STRU* pStruFullPath
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
STRU strFileFullPath;
|
|
||||||
LPWSTR pszFullPath = NULL;
|
|
||||||
|
|
||||||
// if relative path, prefix with root path and then convert to absolute path.
|
|
||||||
if ( PathIsRelative(pszPath) )
|
|
||||||
{
|
|
||||||
hr = strFileFullPath.Copy(pszRootPath);
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!strFileFullPath.EndsWith(L"\\"))
|
|
||||||
{
|
|
||||||
hr = strFileFullPath.Append(L"\\");
|
|
||||||
if(FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = strFileFullPath.Append( pszPath );
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszFullPath = new WCHAR[ strFileFullPath.QueryCCH() + 1];
|
|
||||||
if ( pszFullPath == NULL )
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_wfullpath( pszFullPath,
|
|
||||||
strFileFullPath.QueryStr(),
|
|
||||||
strFileFullPath.QueryCCH() + 1 ) == NULL )
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert to canonical path
|
|
||||||
hr = MakePathCanonicalizationProof( pszFullPath, pStruFullPath );
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
UTILITY::CheckIfFileExists(
|
|
||||||
_In_ PCWSTR pszFilePath
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HANDLE hFileHandle = INVALID_HANDLE_VALUE;
|
|
||||||
SECURITY_ATTRIBUTES saAttr;
|
|
||||||
BOOL fFileExists = FALSE;
|
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
||||||
saAttr.bInheritHandle = TRUE;
|
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
|
||||||
|
|
||||||
hFileHandle = CreateFile(pszFilePath,
|
|
||||||
GENERIC_READ,
|
|
||||||
FILE_SHARE_READ,
|
|
||||||
&saAttr,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
fFileExists = hFileHandle != INVALID_HANDLE_VALUE || GetLastError() == ERROR_SHARING_VIOLATION;
|
|
||||||
|
|
||||||
if (fFileExists)
|
|
||||||
{
|
|
||||||
CloseHandle(hFileHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fFileExists;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
UTILITY::LogEvent(
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_In_ WORD dwEventInfoType,
|
|
||||||
_In_ DWORD dwEventId,
|
|
||||||
_In_ LPCWSTR pstrMsg
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (hEventLog != NULL)
|
|
||||||
{
|
|
||||||
ReportEventW(hEventLog,
|
|
||||||
dwEventInfoType,
|
|
||||||
0, // wCategory
|
|
||||||
dwEventId,
|
|
||||||
NULL, // lpUserSid
|
|
||||||
1, // wNumStrings
|
|
||||||
0, // dwDataSize,
|
|
||||||
&pstrMsg,
|
|
||||||
NULL // lpRawData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dwEventInfoType == EVENTLOG_ERROR_TYPE)
|
|
||||||
{
|
|
||||||
fwprintf(stderr, L"ERROR: %s\n", pstrMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
UTILITY::LogEventF(
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_In_ WORD dwEventInfoType,
|
|
||||||
_In_ DWORD dwEventId,
|
|
||||||
_In_ LPCWSTR pstrMsg,
|
|
||||||
...
|
|
||||||
)
|
|
||||||
{
|
|
||||||
va_list argsList;
|
|
||||||
va_start(argsList, pstrMsg);
|
|
||||||
|
|
||||||
STACK_STRU ( strEventMsg, 256 );
|
|
||||||
|
|
||||||
if (SUCCEEDED(strEventMsg.SafeVsnwprintf(
|
|
||||||
pstrMsg,
|
|
||||||
argsList)))
|
|
||||||
{
|
|
||||||
UTILITY::LogEvent(hEventLog,
|
|
||||||
dwEventInfoType,
|
|
||||||
dwEventId,
|
|
||||||
strEventMsg.QueryStr());
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end( argsList );
|
|
||||||
}
|
|
||||||
|
|
@ -1,137 +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 UTILITY
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
SplitUrl(
|
|
||||||
PCWSTR pszDestinationUrl,
|
|
||||||
BOOL *pfSecure,
|
|
||||||
STRU *pstrDestination,
|
|
||||||
STRU *pstrUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
UnEscapeUrl(
|
|
||||||
PCWSTR pszUrl,
|
|
||||||
DWORD cchUrl,
|
|
||||||
bool fCopyQuery,
|
|
||||||
STRA * pstrResult
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
UnEscapeUrl(
|
|
||||||
PCWSTR pszUrl,
|
|
||||||
DWORD cchUrl,
|
|
||||||
STRU * pstrResult
|
|
||||||
);
|
|
||||||
|
|
||||||
static HRESULT
|
|
||||||
EscapeAbsPath(
|
|
||||||
IHttpRequest * pRequest,
|
|
||||||
STRU * strEscapedUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
bool
|
|
||||||
IsValidAttributeNameChar(
|
|
||||||
WCHAR ch
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
bool
|
|
||||||
IsValidQueryStringName(
|
|
||||||
PCWSTR pszName
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
bool
|
|
||||||
IsValidHeaderName(
|
|
||||||
PCWSTR pszName
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
bool
|
|
||||||
FindInMultiString(
|
|
||||||
PCWSTR pszMultiString,
|
|
||||||
PCWSTR pszStringToFind
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
IsPathUnc(
|
|
||||||
__in LPCWSTR pszPath,
|
|
||||||
__out BOOL * pfIsUnc
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
ConvertPathToFullPath(
|
|
||||||
_In_ LPCWSTR pszPath,
|
|
||||||
_In_ LPCWSTR pszRootPath,
|
|
||||||
_Out_ STRU* pStrFullPath
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
EnsureDirectoryPathExist(
|
|
||||||
_In_ LPCWSTR pszPath
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
DirectoryExists(
|
|
||||||
_In_ STRU *pstrPath
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
FindDotNetFolders(
|
|
||||||
_In_ PCWSTR pszPath,
|
|
||||||
_Out_ std::vector<std::wstring> *pvFolders
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
FindHighestDotNetVersion(
|
|
||||||
_In_ std::vector<std::wstring> vFolders,
|
|
||||||
_Out_ STRU *pstrResult
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
CheckIfFileExists(
|
|
||||||
PCWSTR pszFilePath
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
LogEvent(
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_In_ WORD dwEventInfoType,
|
|
||||||
_In_ DWORD dwEventId,
|
|
||||||
_In_ LPCWSTR pstrMsg
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
LogEventF(
|
|
||||||
_In_ HANDLE hEventLog,
|
|
||||||
_In_ WORD dwEventInfoType,
|
|
||||||
_In_ DWORD dwEventId,
|
|
||||||
__in PCWSTR pstrMsg,
|
|
||||||
...
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
UTILITY() {}
|
|
||||||
~UTILITY() {}
|
|
||||||
};
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
<?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="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{09D9D1D6-2951-4E14-BC35-76A23CF9391A}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>IISLib</RootNamespace>
|
|
||||||
<ProjectName>IISLib</ProjectName>
|
|
||||||
<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)'=='Debug|x64'" 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)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>StaticLibrary</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="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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
|
||||||
<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 Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
|
||||||
<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)'=='Release|Win32'">
|
|
||||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<OutDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\$(Platform)\</OutDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<ShowIncludes>false</ShowIncludes>
|
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
<ShowIncludes>false</ShowIncludes>
|
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<ShowIncludes>false</ShowIncludes>
|
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<ShowIncludes>false</ShowIncludes>
|
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="acache.h" />
|
|
||||||
<ClInclude Include="ahutil.h" />
|
|
||||||
<ClInclude Include="base64.h" />
|
|
||||||
<ClInclude Include="buffer.h" />
|
|
||||||
<ClInclude Include="datetime.h" />
|
|
||||||
<ClInclude Include="dbgutil.h" />
|
|
||||||
<ClInclude Include="hashfn.h" />
|
|
||||||
<ClInclude Include="hashtable.h" />
|
|
||||||
<ClInclude Include="listentry.h" />
|
|
||||||
<ClInclude Include="macros.h" />
|
|
||||||
<ClInclude Include="multisz.h" />
|
|
||||||
<ClInclude Include="multisza.h" />
|
|
||||||
<ClInclude Include="ntassert.h" />
|
|
||||||
<ClInclude Include="percpu.h" />
|
|
||||||
<ClInclude Include="precomp.h" />
|
|
||||||
<ClInclude Include="prime.h" />
|
|
||||||
<ClInclude Include="pudebug.h" />
|
|
||||||
<ClInclude Include="reftrace.h" />
|
|
||||||
<ClInclude Include="rwlock.h" />
|
|
||||||
<ClInclude Include="stringa.h" />
|
|
||||||
<ClInclude Include="stringu.h" />
|
|
||||||
<ClInclude Include="tracelog.h" />
|
|
||||||
<ClInclude Include="treehash.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="acache.cxx" />
|
|
||||||
<ClCompile Include="ahutil.cpp" />
|
|
||||||
<ClCompile Include="base64.cpp" />
|
|
||||||
<ClCompile Include="multisz.cpp" />
|
|
||||||
<ClCompile Include="multisza.cpp" />
|
|
||||||
<ClCompile Include="reftrace.c" />
|
|
||||||
<ClCompile Include="stringa.cpp" />
|
|
||||||
<ClCompile Include="stringu.cpp" />
|
|
||||||
<ClCompile Include="tracelog.c" />
|
|
||||||
<ClCompile Include="util.cxx" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,443 +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.h"
|
|
||||||
|
|
||||||
LONG ALLOC_CACHE_HANDLER::sm_nFillPattern = 0xACA50000;
|
|
||||||
HANDLE ALLOC_CACHE_HANDLER::sm_hHeap;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This class is used to implement the free list. We cast the free'd
|
|
||||||
// memory block to a FREE_LIST_HEADER*. The signature is used to guard against
|
|
||||||
// double deletion. We also fill memory with a pattern.
|
|
||||||
//
|
|
||||||
class FREE_LIST_HEADER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SLIST_ENTRY ListEntry;
|
|
||||||
DWORD dwSignature;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FREE_SIGNATURE = (('A') | ('C' << 8) | ('a' << 16) | (('$' << 24) | 0x80)),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
ALLOC_CACHE_HANDLER::ALLOC_CACHE_HANDLER(
|
|
||||||
VOID
|
|
||||||
) : m_nThreshold(0),
|
|
||||||
m_cbSize(0),
|
|
||||||
m_pFreeLists(NULL),
|
|
||||||
m_nTotal(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ALLOC_CACHE_HANDLER::~ALLOC_CACHE_HANDLER(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (m_pFreeLists != NULL)
|
|
||||||
{
|
|
||||||
CleanupLookaside();
|
|
||||||
m_pFreeLists->Dispose();
|
|
||||||
m_pFreeLists = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ALLOC_CACHE_HANDLER::Initialize(
|
|
||||||
DWORD cbSize,
|
|
||||||
LONG nThreshold
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
m_nThreshold = nThreshold;
|
|
||||||
if ( m_nThreshold > 0xffff)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// This will be compared against QueryDepthSList return value (USHORT).
|
|
||||||
//
|
|
||||||
m_nThreshold = 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( IsPageheapEnabled() )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Disable acache.
|
|
||||||
//
|
|
||||||
m_nThreshold = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make sure the block is big enough to hold a FREE_LIST_HEADER.
|
|
||||||
//
|
|
||||||
m_cbSize = cbSize;
|
|
||||||
m_cbSize = max(m_cbSize, sizeof(FREE_LIST_HEADER));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Round up the block size to a multiple of the size of a LONG (for
|
|
||||||
// the fill pattern in Free()).
|
|
||||||
//
|
|
||||||
m_cbSize = (m_cbSize + sizeof(LONG) - 1) & ~(sizeof(LONG) - 1);
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
|
|
||||||
auto Init = [] (SLIST_HEADER* pHead)
|
|
||||||
{
|
|
||||||
InitializeSListHead(pHead);
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class Functor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void operator()(SLIST_HEADER* pHead)
|
|
||||||
{
|
|
||||||
InitializeSListHead(pHead);
|
|
||||||
}
|
|
||||||
} Init;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hr = PER_CPU<SLIST_HEADER>::Create(Init,
|
|
||||||
&m_pFreeLists );
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_nFillPattern = InterlockedIncrement(&sm_nFillPattern);
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
ALLOC_CACHE_HANDLER::StaticInitialize(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Since the memory allocated is fixed size,
|
|
||||||
// a heap is not really needed, allocations can be done
|
|
||||||
// using VirtualAllocEx[Numa]. For now use Windows Heap.
|
|
||||||
//
|
|
||||||
// Be aware that creating one private heap consumes more
|
|
||||||
// virtual address space for the worker process.
|
|
||||||
//
|
|
||||||
sm_hHeap = GetProcessHeap();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
VOID
|
|
||||||
ALLOC_CACHE_HANDLER::StaticTerminate(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
sm_hHeap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ALLOC_CACHE_HANDLER::CleanupLookaside(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
This function cleans up the lookaside list by removing storage space.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
None
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Free up all the entries in the list.
|
|
||||||
// Don't use InterlockedFlushSList, in order to work
|
|
||||||
// memory must be 16 bytes aligned and currently it is 64.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
|
|
||||||
auto Predicate = [=] (SLIST_HEADER * pListHeader)
|
|
||||||
{
|
|
||||||
PSLIST_ENTRY pl;
|
|
||||||
LONG NodesToDelete = QueryDepthSList( pListHeader );
|
|
||||||
|
|
||||||
pl = InterlockedPopEntrySList( pListHeader );
|
|
||||||
while ( pl != NULL && --NodesToDelete >= 0 )
|
|
||||||
{
|
|
||||||
InterlockedDecrement( &m_nTotal);
|
|
||||||
|
|
||||||
::HeapFree( sm_hHeap, 0, pl );
|
|
||||||
|
|
||||||
pl = InterlockedPopEntrySList(pListHeader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class Functor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Functor(ALLOC_CACHE_HANDLER * pThis) : _pThis(pThis)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void operator()(SLIST_HEADER * pListHeader)
|
|
||||||
{
|
|
||||||
PSLIST_ENTRY pl;
|
|
||||||
LONG NodesToDelete = QueryDepthSList( pListHeader );
|
|
||||||
|
|
||||||
pl = InterlockedPopEntrySList( pListHeader );
|
|
||||||
while ( pl != NULL && --NodesToDelete >= 0 )
|
|
||||||
{
|
|
||||||
InterlockedDecrement( &_pThis->m_nTotal);
|
|
||||||
|
|
||||||
::HeapFree( sm_hHeap, 0, pl );
|
|
||||||
|
|
||||||
pl = InterlockedPopEntrySList(pListHeader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
ALLOC_CACHE_HANDLER * _pThis;
|
|
||||||
} Predicate(this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_pFreeLists ->ForEach(Predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
LPVOID
|
|
||||||
ALLOC_CACHE_HANDLER::Alloc(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
LPVOID pMemory = NULL;
|
|
||||||
|
|
||||||
if ( m_nThreshold > 0 )
|
|
||||||
{
|
|
||||||
SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal();
|
|
||||||
pMemory = (LPVOID) InterlockedPopEntrySList(pListHeader); // get the real object
|
|
||||||
|
|
||||||
if (pMemory != NULL)
|
|
||||||
{
|
|
||||||
FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
|
|
||||||
//
|
|
||||||
// If the signature is wrong then somebody's been scribbling
|
|
||||||
// on memory that they've freed.
|
|
||||||
//
|
|
||||||
DBG_ASSERT(pfl->dwSignature == FREE_LIST_HEADER::FREE_SIGNATURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pMemory == NULL )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// No free entry. Need to alloc a new object.
|
|
||||||
//
|
|
||||||
pMemory = (LPVOID) ::HeapAlloc( sm_hHeap,
|
|
||||||
0,
|
|
||||||
m_cbSize );
|
|
||||||
|
|
||||||
if ( pMemory != NULL )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Update counters.
|
|
||||||
//
|
|
||||||
m_nTotal++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pMemory == NULL )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
|
|
||||||
pfl->dwSignature = 0; // clear; just in case caller never overwrites
|
|
||||||
}
|
|
||||||
|
|
||||||
return pMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ALLOC_CACHE_HANDLER::Free(
|
|
||||||
__in LPVOID pMemory
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Assume that this is allocated using the Alloc() function.
|
|
||||||
//
|
|
||||||
DBG_ASSERT(NULL != pMemory);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Use a signature to check against double deletions.
|
|
||||||
//
|
|
||||||
FREE_LIST_HEADER* pfl = (FREE_LIST_HEADER*) pMemory;
|
|
||||||
DBG_ASSERT(pfl->dwSignature != FREE_LIST_HEADER::FREE_SIGNATURE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start filling the space beyond the portion overlaid by the initial
|
|
||||||
// FREE_LIST_HEADER. Fill at most 6 DWORDS.
|
|
||||||
//
|
|
||||||
LONG* pl = (LONG*) (pfl+1);
|
|
||||||
|
|
||||||
for (LONG cb = (LONG)min(6 * sizeof(LONG),m_cbSize) - sizeof(FREE_LIST_HEADER);
|
|
||||||
cb > 0;
|
|
||||||
cb -= sizeof(LONG))
|
|
||||||
{
|
|
||||||
*pl++ = m_nFillPattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now, set the signature.
|
|
||||||
//
|
|
||||||
pfl->dwSignature = FREE_LIST_HEADER::FREE_SIGNATURE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Store the items in the alloc cache.
|
|
||||||
//
|
|
||||||
SLIST_HEADER * pListHeader = m_pFreeLists ->GetLocal();
|
|
||||||
|
|
||||||
if ( QueryDepthSList(pListHeader) >= m_nThreshold )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Threshold for free entries is exceeded. Free the object to
|
|
||||||
// process pool.
|
|
||||||
//
|
|
||||||
::HeapFree( sm_hHeap, 0, pMemory );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Store the given pointer in the single linear list
|
|
||||||
//
|
|
||||||
InterlockedPushEntrySList(pListHeader, &pfl->ListEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
ALLOC_CACHE_HANDLER::QueryDepthForAllSLists(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Description:
|
|
||||||
|
|
||||||
Aggregates the total count of elements in all lists.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
Total count (snapshot).
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
DWORD Count = 0;
|
|
||||||
|
|
||||||
if (m_pFreeLists != NULL)
|
|
||||||
{
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 // VC10
|
|
||||||
auto Predicate = [&Count] (SLIST_HEADER * pListHeader)
|
|
||||||
{
|
|
||||||
Count += QueryDepthSList(pListHeader);
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class Functor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Functor(DWORD& Count) : _Count(Count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void operator()(SLIST_HEADER * pListHeader)
|
|
||||||
{
|
|
||||||
_Count += QueryDepthSList(pListHeader);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
DWORD& _Count;
|
|
||||||
} Predicate(Count);
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// [&Count] means that the method can modify local variable Count.
|
|
||||||
//
|
|
||||||
m_pFreeLists ->ForEach(Predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
BOOL
|
|
||||||
ALLOC_CACHE_HANDLER::IsPageheapEnabled(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
BOOL fRet = FALSE;
|
|
||||||
BOOL fLockedHeap = FALSE;
|
|
||||||
HMODULE hModule = NULL;
|
|
||||||
HANDLE hHeap = NULL;
|
|
||||||
PROCESS_HEAP_ENTRY heapEntry = {0};
|
|
||||||
|
|
||||||
//
|
|
||||||
// If verifier.dll is loaded - we are running under app verifier == pageheap is enabled
|
|
||||||
//
|
|
||||||
hModule = GetModuleHandle( L"verifier.dll" );
|
|
||||||
if ( hModule != NULL )
|
|
||||||
{
|
|
||||||
hModule = NULL;
|
|
||||||
fRet = TRUE;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create a heap for calling heapwalk
|
|
||||||
// otherwise HeapWalk turns off lookasides for a useful heap
|
|
||||||
//
|
|
||||||
hHeap = ::HeapCreate( 0, 0, 0 );
|
|
||||||
if ( hHeap == NULL )
|
|
||||||
{
|
|
||||||
fRet = FALSE;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
fRet = ::HeapLock( hHeap );
|
|
||||||
if ( !fRet )
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
fLockedHeap = TRUE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If HeapWalk is unsupported -> then running page heap
|
|
||||||
//
|
|
||||||
fRet = ::HeapWalk( hHeap, &heapEntry );
|
|
||||||
if ( !fRet )
|
|
||||||
{
|
|
||||||
if ( GetLastError() == ERROR_INVALID_FUNCTION )
|
|
||||||
{
|
|
||||||
fRet = TRUE;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fRet = FALSE;
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if ( fLockedHeap )
|
|
||||||
{
|
|
||||||
fLockedHeap = FALSE;
|
|
||||||
DBG_REQUIRE( ::HeapUnlock( hHeap ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( hHeap )
|
|
||||||
{
|
|
||||||
DBG_REQUIRE( ::HeapDestroy( hHeap ) );
|
|
||||||
hHeap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fRet;
|
|
||||||
}
|
|
||||||
|
|
@ -1,115 +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 "percpu.h"
|
|
||||||
|
|
||||||
class ALLOC_CACHE_HANDLER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
ALLOC_CACHE_HANDLER(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
~ALLOC_CACHE_HANDLER(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
Initialize(
|
|
||||||
DWORD cbSize,
|
|
||||||
LONG nThreshold
|
|
||||||
);
|
|
||||||
|
|
||||||
LPVOID
|
|
||||||
Alloc(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
Free(
|
|
||||||
__in LPVOID pMemory
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CleanupLookaside(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QueryDepthForAllSLists(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
LONG m_nThreshold;
|
|
||||||
DWORD m_cbSize;
|
|
||||||
|
|
||||||
PER_CPU<SLIST_HEADER> * m_pFreeLists;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Total heap allocations done over the lifetime.
|
|
||||||
// Note that this is not interlocked, it is just a hint for debugging.
|
|
||||||
//
|
|
||||||
volatile LONG m_nTotal;
|
|
||||||
|
|
||||||
LONG m_nFillPattern;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
StaticInitialize(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
VOID
|
|
||||||
StaticTerminate(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
IsPageheapEnabled();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static LONG sm_nFillPattern;
|
|
||||||
static HANDLE sm_hHeap;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// You can use ALLOC_CACHE_HANDLER as a per-class allocator
|
|
||||||
// in your C++ classes. Add the following to your class definition:
|
|
||||||
//
|
|
||||||
// protected:
|
|
||||||
// static ALLOC_CACHE_HANDLER* sm_palloc;
|
|
||||||
// public:
|
|
||||||
// static void* operator new(size_t s)
|
|
||||||
// {
|
|
||||||
// IRTLASSERT(s == sizeof(C));
|
|
||||||
// IRTLASSERT(sm_palloc != NULL);
|
|
||||||
// return sm_palloc->Alloc();
|
|
||||||
// }
|
|
||||||
// static void operator delete(void* pv)
|
|
||||||
// {
|
|
||||||
// IRTLASSERT(pv != NULL);
|
|
||||||
// if (sm_palloc != NULL)
|
|
||||||
// sm_palloc->Free(pv);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Obviously, you must initialize sm_palloc before you can allocate
|
|
||||||
// any objects of this class.
|
|
||||||
//
|
|
||||||
// Note that if you derive a class from this base class, the derived class
|
|
||||||
// must also provide its own operator new and operator delete. If not, the
|
|
||||||
// base class's allocator will be called, but the size of the derived
|
|
||||||
// object will almost certainly be larger than that of the base object.
|
|
||||||
// Furthermore, the allocator will not be used for arrays of objects
|
|
||||||
// (override operator new[] and operator delete[]), but this is a
|
|
||||||
// harder problem since the allocator works with one fixed size.
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,258 +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<Windows.h>
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SetElementProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN CONST WCHAR * szPropName,
|
|
||||||
IN CONST VARIANT * varPropValue
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SetElementStringProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN CONST WCHAR * szPropName,
|
|
||||||
IN CONST WCHAR * szPropValue
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementStringProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN CONST WCHAR * szPropName,
|
|
||||||
OUT BSTR * pbstrPropValue
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementStringProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN CONST WCHAR * szPropName,
|
|
||||||
OUT STRU * pstrPropValue
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementBoolProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszPropertyName,
|
|
||||||
OUT BOOL * pBool
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementBoolProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszPropertyName,
|
|
||||||
OUT bool * pBool
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementChildByName(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszElementName,
|
|
||||||
OUT IAppHostElement ** ppChildElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementDWORDProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszPropertyName,
|
|
||||||
OUT DWORD * pdwValue
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementLONGLONGProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszPropertyName,
|
|
||||||
OUT LONGLONG * pllValue
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetElementRawTimeSpanProperty(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN LPCWSTR pszPropertyName,
|
|
||||||
OUT ULONGLONG * pulonglong
|
|
||||||
);
|
|
||||||
|
|
||||||
#define FIND_ELEMENT_CASE_SENSITIVE 0x00000000
|
|
||||||
#define FIND_ELEMENT_CASE_INSENSITIVE 0x00000001
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
DeleteElementFromCollection(
|
|
||||||
IAppHostElementCollection *pCollection,
|
|
||||||
CONST WCHAR * szKeyName,
|
|
||||||
CONST WCHAR * szKeyValue,
|
|
||||||
ULONG BehaviorFlags,
|
|
||||||
BOOL * pfDeleted
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
DeleteAllElementsFromCollection(
|
|
||||||
IAppHostElementCollection *pCollection,
|
|
||||||
CONST WCHAR * szKeyName,
|
|
||||||
CONST WCHAR * szKeyValue,
|
|
||||||
ULONG BehaviorFlags,
|
|
||||||
UINT * pNumDeleted
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindElementInCollection(
|
|
||||||
IAppHostElementCollection *pCollection,
|
|
||||||
CONST WCHAR * szKeyName,
|
|
||||||
CONST WCHAR * szKeyValue,
|
|
||||||
ULONG BehaviorFlags,
|
|
||||||
OUT ULONG * pIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
VariantAssign(
|
|
||||||
IN OUT VARIANT * pv,
|
|
||||||
IN CONST WCHAR * sz
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetLocationFromFile(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
IN CONST WCHAR * szLocationPath,
|
|
||||||
OUT IAppHostConfigLocation ** ppLocation,
|
|
||||||
OUT BOOL * pFound
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetSectionFromLocation(
|
|
||||||
IN IAppHostConfigLocation * pLocation,
|
|
||||||
IN CONST WCHAR * szSectionName,
|
|
||||||
OUT IAppHostElement ** ppSectionElement,
|
|
||||||
OUT BOOL * pFound
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetAdminElement(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
IN CONST WCHAR * szElementName,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ClearAdminElement(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
IN CONST WCHAR * szElementName
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ClearElementFromAllSites(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
IN CONST WCHAR * szElementName
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ClearElementFromAllLocations(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
IN CONST WCHAR * szElementName
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ClearLocationElements(
|
|
||||||
IN IAppHostConfigLocation * pLocation,
|
|
||||||
IN CONST WCHAR * szElementName
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
CompareElementName(
|
|
||||||
IN IAppHostElement * pElement,
|
|
||||||
IN CONST WCHAR * szNameToMatch,
|
|
||||||
OUT BOOL * pMatched
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
ClearChildElementsByName(
|
|
||||||
IN IAppHostChildElementCollection * pCollection,
|
|
||||||
IN CONST WCHAR * szElementName,
|
|
||||||
OUT BOOL * pFound
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetSitesCollection(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
OUT IAppHostElementCollection ** pSitesCollection
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
GetLocationCollection(
|
|
||||||
IN IAppHostAdminManager * pAdminMgr,
|
|
||||||
IN CONST WCHAR * szConfigPath,
|
|
||||||
OUT IAppHostConfigLocationCollection ** pLocationCollection
|
|
||||||
);
|
|
||||||
|
|
||||||
struct ENUM_INDEX
|
|
||||||
{
|
|
||||||
VARIANT Index;
|
|
||||||
ULONG Count;
|
|
||||||
};
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindFirstElement(
|
|
||||||
IN IAppHostElementCollection * pCollection,
|
|
||||||
OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindNextElement(
|
|
||||||
IN IAppHostElementCollection * pCollection,
|
|
||||||
IN OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindFirstChildElement(
|
|
||||||
IN IAppHostChildElementCollection * pCollection,
|
|
||||||
OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindNextChildElement(
|
|
||||||
IN IAppHostChildElementCollection * pCollection,
|
|
||||||
IN OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindFirstLocation(
|
|
||||||
IN IAppHostConfigLocationCollection * pCollection,
|
|
||||||
OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostConfigLocation ** pLocation
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindNextLocation(
|
|
||||||
IN IAppHostConfigLocationCollection * pCollection,
|
|
||||||
IN OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostConfigLocation ** pLocation
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindFirstLocationElement(
|
|
||||||
IN IAppHostConfigLocation * pLocation,
|
|
||||||
OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
FindNextLocationElement(
|
|
||||||
IN IAppHostConfigLocation * pLocation,
|
|
||||||
IN OUT ENUM_INDEX * pIndex,
|
|
||||||
OUT IAppHostElement ** pElement
|
|
||||||
);
|
|
||||||
|
|
||||||
HRESULT GetSharedConfigEnabled(
|
|
||||||
BOOL * pfIsSharedConfig
|
|
||||||
);
|
|
||||||
|
|
@ -1,482 +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.h"
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Encode(
|
|
||||||
__in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer,
|
|
||||||
IN DWORD cbDecodedBufferSize,
|
|
||||||
__out_ecount_opt(cchEncodedStringSize) PWSTR pszEncodedString,
|
|
||||||
IN DWORD cchEncodedStringSize,
|
|
||||||
__out_opt DWORD * pcchEncoded
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Decode a base64-encoded string.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pDecodedBuffer (IN) - buffer to encode.
|
|
||||||
cbDecodedBufferSize (IN) - size of buffer to encode.
|
|
||||||
cchEncodedStringSize (IN) - size of the buffer for the encoded string.
|
|
||||||
pszEncodedString (OUT) = the encoded string.
|
|
||||||
pcchEncoded (OUT) - size in characters of the encoded string.
|
|
||||||
|
|
||||||
Return Values:
|
|
||||||
|
|
||||||
0 - success.
|
|
||||||
E_OUTOFMEMORY
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
static WCHAR rgchEncodeTable[64] = {
|
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
|
||||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|
||||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD ib;
|
|
||||||
DWORD ich;
|
|
||||||
DWORD cchEncoded;
|
|
||||||
BYTE b0, b1, b2;
|
|
||||||
BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer;
|
|
||||||
|
|
||||||
// Calculate encoded string size.
|
|
||||||
cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4;
|
|
||||||
|
|
||||||
if (NULL != pcchEncoded) {
|
|
||||||
*pcchEncoded = cchEncoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cchEncodedStringSize == 0 && pszEncodedString == NULL) {
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cchEncodedStringSize < cchEncoded) {
|
|
||||||
// Given buffer is too small to hold encoded string.
|
|
||||||
return ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode data byte triplets into four-byte clusters.
|
|
||||||
ib = ich = 0;
|
|
||||||
while (ib < cbDecodedBufferSize) {
|
|
||||||
b0 = pbDecodedBuffer[ib++];
|
|
||||||
b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
|
|
||||||
b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The checks below for buffer overflow seems redundant to me.
|
|
||||||
// But it's the only way I can find to keep OACR quiet so it
|
|
||||||
// will have to do.
|
|
||||||
//
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pad the last cluster as necessary to indicate the number of data bytes
|
|
||||||
// it represents.
|
|
||||||
switch (cbDecodedBufferSize % 3) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pszEncodedString[ich - 2] = '=';
|
|
||||||
__fallthrough;
|
|
||||||
case 2:
|
|
||||||
pszEncodedString[ich - 1] = '=';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Null-terminate the encoded string.
|
|
||||||
pszEncodedString[ich++] = '\0';
|
|
||||||
|
|
||||||
DBG_ASSERT(ich == cchEncoded);
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Decode(
|
|
||||||
__in PCWSTR pszEncodedString,
|
|
||||||
__out_opt VOID * pDecodeBuffer,
|
|
||||||
__in DWORD cbDecodeBufferSize,
|
|
||||||
__out_opt DWORD * pcbDecoded
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Decode a base64-encoded string.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pszEncodedString (IN) - base64-encoded string to decode.
|
|
||||||
cbDecodeBufferSize (IN) - size in bytes of the decode buffer.
|
|
||||||
pbDecodeBuffer (OUT) - holds the decoded data.
|
|
||||||
pcbDecoded (OUT) - number of data bytes in the decoded data (if success or
|
|
||||||
STATUS_BUFFER_TOO_SMALL).
|
|
||||||
|
|
||||||
Return Values:
|
|
||||||
|
|
||||||
0 - success.
|
|
||||||
E_OUTOFMEMORY
|
|
||||||
E_INVALIDARG
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
#define NA (255)
|
|
||||||
#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA)
|
|
||||||
|
|
||||||
static BYTE rgbDecodeTable[128] = {
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63
|
|
||||||
NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95
|
|
||||||
NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD cbDecoded;
|
|
||||||
DWORD cchEncodedSize;
|
|
||||||
DWORD ich;
|
|
||||||
DWORD ib;
|
|
||||||
BYTE b0, b1, b2, b3;
|
|
||||||
BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer;
|
|
||||||
|
|
||||||
cchEncodedSize = (DWORD)wcslen(pszEncodedString);
|
|
||||||
if (NULL != pcbDecoded) {
|
|
||||||
*pcbDecoded = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) {
|
|
||||||
// Input string is not sized correctly to be base64.
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate decoded buffer size.
|
|
||||||
cbDecoded = (cchEncodedSize + 3) / 4 * 3;
|
|
||||||
if (pszEncodedString[cchEncodedSize-1] == '=') {
|
|
||||||
if (pszEncodedString[cchEncodedSize-2] == '=') {
|
|
||||||
// Only one data byte is encoded in the last cluster.
|
|
||||||
cbDecoded -= 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Only two data bytes are encoded in the last cluster.
|
|
||||||
cbDecoded -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != pcbDecoded) {
|
|
||||||
*pcbDecoded = cbDecoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) {
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cbDecoded > cbDecodeBufferSize) {
|
|
||||||
// Supplied buffer is too small.
|
|
||||||
return ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode each four-byte cluster into the corresponding three data bytes.
|
|
||||||
ich = ib = 0;
|
|
||||||
while (ich < cchEncodedSize) {
|
|
||||||
b0 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b1 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b2 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b3 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
|
|
||||||
if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) {
|
|
||||||
// Contents of input string are not base64.
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4);
|
|
||||||
|
|
||||||
if (ib < cbDecoded) {
|
|
||||||
pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2);
|
|
||||||
|
|
||||||
if (ib < cbDecoded) {
|
|
||||||
pbDecodeBuffer[ib++] = (b2 << 6) | b3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_ASSERT(ib == cbDecoded);
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Encode(
|
|
||||||
__in_bcount(cbDecodedBufferSize) VOID * pDecodedBuffer,
|
|
||||||
IN DWORD cbDecodedBufferSize,
|
|
||||||
__out_ecount_opt(cchEncodedStringSize) PSTR pszEncodedString,
|
|
||||||
IN DWORD cchEncodedStringSize,
|
|
||||||
__out_opt DWORD * pcchEncoded
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Decode a base64-encoded string.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pDecodedBuffer (IN) - buffer to encode.
|
|
||||||
cbDecodedBufferSize (IN) - size of buffer to encode.
|
|
||||||
cchEncodedStringSize (IN) - size of the buffer for the encoded string.
|
|
||||||
pszEncodedString (OUT) = the encoded string.
|
|
||||||
pcchEncoded (OUT) - size in characters of the encoded string.
|
|
||||||
|
|
||||||
Return Values:
|
|
||||||
|
|
||||||
0 - success.
|
|
||||||
E_OUTOFMEMORY
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
static CHAR rgchEncodeTable[64] = {
|
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
|
||||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|
||||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD ib;
|
|
||||||
DWORD ich;
|
|
||||||
DWORD cchEncoded;
|
|
||||||
BYTE b0, b1, b2;
|
|
||||||
BYTE * pbDecodedBuffer = (BYTE *) pDecodedBuffer;
|
|
||||||
|
|
||||||
// Calculate encoded string size.
|
|
||||||
cchEncoded = 1 + (cbDecodedBufferSize + 2) / 3 * 4;
|
|
||||||
|
|
||||||
if (NULL != pcchEncoded) {
|
|
||||||
*pcchEncoded = cchEncoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cchEncodedStringSize == 0 && pszEncodedString == NULL) {
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cchEncodedStringSize < cchEncoded) {
|
|
||||||
// Given buffer is too small to hold encoded string.
|
|
||||||
return ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode data byte triplets into four-byte clusters.
|
|
||||||
ib = ich = 0;
|
|
||||||
while (ib < cbDecodedBufferSize) {
|
|
||||||
b0 = pbDecodedBuffer[ib++];
|
|
||||||
b1 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
|
|
||||||
b2 = (ib < cbDecodedBufferSize) ? pbDecodedBuffer[ib++] : 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The checks below for buffer overflow seems redundant to me.
|
|
||||||
// But it's the only way I can find to keep OACR quiet so it
|
|
||||||
// will have to do.
|
|
||||||
//
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[b0 >> 2];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[((b0 << 4) & 0x30) | ((b1 >> 4) & 0x0f)];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[((b1 << 2) & 0x3c) | ((b2 >> 6) & 0x03)];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszEncodedString[ich++] = rgchEncodeTable[b2 & 0x3f];
|
|
||||||
if ( ich >= cchEncodedStringSize )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pad the last cluster as necessary to indicate the number of data bytes
|
|
||||||
// it represents.
|
|
||||||
switch (cbDecodedBufferSize % 3) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pszEncodedString[ich - 2] = '=';
|
|
||||||
__fallthrough;
|
|
||||||
case 2:
|
|
||||||
pszEncodedString[ich - 1] = '=';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Null-terminate the encoded string.
|
|
||||||
pszEncodedString[ich++] = '\0';
|
|
||||||
|
|
||||||
DBG_ASSERT(ich == cchEncoded);
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Decode(
|
|
||||||
__in PCSTR pszEncodedString,
|
|
||||||
__out_opt VOID * pDecodeBuffer,
|
|
||||||
__in DWORD cbDecodeBufferSize,
|
|
||||||
__out_opt DWORD * pcbDecoded
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Decode a base64-encoded string.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pszEncodedString (IN) - base64-encoded string to decode.
|
|
||||||
cbDecodeBufferSize (IN) - size in bytes of the decode buffer.
|
|
||||||
pbDecodeBuffer (OUT) - holds the decoded data.
|
|
||||||
pcbDecoded (OUT) - number of data bytes in the decoded data (if success or
|
|
||||||
STATUS_BUFFER_TOO_SMALL).
|
|
||||||
|
|
||||||
Return Values:
|
|
||||||
|
|
||||||
0 - success.
|
|
||||||
E_OUTOFMEMORY
|
|
||||||
E_INVALIDARG
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
#define NA (255)
|
|
||||||
#define DECODE(x) (((ULONG)(x) < sizeof(rgbDecodeTable)) ? rgbDecodeTable[x] : NA)
|
|
||||||
|
|
||||||
static BYTE rgbDecodeTable[128] = {
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 0-15
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, // 16-31
|
|
||||||
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, 63, // 32-47
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NA, NA, NA, 0, NA, NA, // 48-63
|
|
||||||
NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NA, NA, NA, NA, NA, // 80-95
|
|
||||||
NA, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NA, NA, NA, NA, NA, // 112-127
|
|
||||||
};
|
|
||||||
|
|
||||||
DWORD cbDecoded;
|
|
||||||
DWORD cchEncodedSize;
|
|
||||||
DWORD ich;
|
|
||||||
DWORD ib;
|
|
||||||
BYTE b0, b1, b2, b3;
|
|
||||||
BYTE * pbDecodeBuffer = (BYTE *) pDecodeBuffer;
|
|
||||||
|
|
||||||
cchEncodedSize = (DWORD)strlen(pszEncodedString);
|
|
||||||
if (NULL != pcbDecoded) {
|
|
||||||
*pcbDecoded = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((0 == cchEncodedSize) || (0 != (cchEncodedSize % 4))) {
|
|
||||||
// Input string is not sized correctly to be base64.
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate decoded buffer size.
|
|
||||||
cbDecoded = (cchEncodedSize + 3) / 4 * 3;
|
|
||||||
if (pszEncodedString[cchEncodedSize-1] == '=') {
|
|
||||||
if (pszEncodedString[cchEncodedSize-2] == '=') {
|
|
||||||
// Only one data byte is encoded in the last cluster.
|
|
||||||
cbDecoded -= 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Only two data bytes are encoded in the last cluster.
|
|
||||||
cbDecoded -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != pcbDecoded) {
|
|
||||||
*pcbDecoded = cbDecoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cbDecodeBufferSize == 0 && pDecodeBuffer == NULL) {
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cbDecoded > cbDecodeBufferSize) {
|
|
||||||
// Supplied buffer is too small.
|
|
||||||
return ERROR_INSUFFICIENT_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode each four-byte cluster into the corresponding three data bytes.
|
|
||||||
ich = ib = 0;
|
|
||||||
while (ich < cchEncodedSize) {
|
|
||||||
b0 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b1 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b2 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
b3 = DECODE(pszEncodedString[ich]); ich++;
|
|
||||||
|
|
||||||
if ((NA == b0) || (NA == b1) || (NA == b2) || (NA == b3)) {
|
|
||||||
// Contents of input string are not base64.
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbDecodeBuffer[ib++] = (b0 << 2) | (b1 >> 4);
|
|
||||||
|
|
||||||
if (ib < cbDecoded) {
|
|
||||||
pbDecodeBuffer[ib++] = (b1 << 4) | (b2 >> 2);
|
|
||||||
|
|
||||||
if (ib < cbDecoded) {
|
|
||||||
pbDecodeBuffer[ib++] = (b2 << 6) | b3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_ASSERT(ib == cbDecoded);
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _BASE64_H_
|
|
||||||
#define _BASE64_H_
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Encode(
|
|
||||||
__in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer,
|
|
||||||
IN DWORD cbDecodedBufferSize,
|
|
||||||
__out_ecount_opt( cchEncodedStringSize ) PWSTR pszEncodedString,
|
|
||||||
IN DWORD cchEncodedStringSize,
|
|
||||||
__out_opt DWORD * pcchEncoded
|
|
||||||
);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Decode(
|
|
||||||
__in PCWSTR pszEncodedString,
|
|
||||||
__out_opt VOID * pDecodeBuffer,
|
|
||||||
__in DWORD cbDecodeBufferSize,
|
|
||||||
__out_opt DWORD * pcbDecoded
|
|
||||||
);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Encode(
|
|
||||||
__in_bcount( cbDecodedBufferSize ) VOID * pDecodedBuffer,
|
|
||||||
IN DWORD cbDecodedBufferSize,
|
|
||||||
__out_ecount_opt( cchEncodedStringSize ) PSTR pszEncodedString,
|
|
||||||
IN DWORD cchEncodedStringSize,
|
|
||||||
__out_opt DWORD * pcchEncoded
|
|
||||||
);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Base64Decode(
|
|
||||||
__in PCSTR pszEncodedString,
|
|
||||||
__out_opt VOID * pDecodeBuffer,
|
|
||||||
__in DWORD cbDecodeBufferSize,
|
|
||||||
__out_opt DWORD * pcbDecoded
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif // _BASE64_HXX_
|
|
||||||
|
|
||||||
|
|
@ -1,271 +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 <crtdbg.h>
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// BUFFER_T class shouldn't be used directly. Use BUFFER specialization class instead.
|
|
||||||
// The only BUFFER_T partners are STRU and STRA classes.
|
|
||||||
// BUFFER_T cannot hold other but primitive types since it doesn't call
|
|
||||||
// constructor and destructor.
|
|
||||||
//
|
|
||||||
// Note: Size is in bytes.
|
|
||||||
//
|
|
||||||
template<typename T, DWORD LENGTH>
|
|
||||||
class BUFFER_T
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
BUFFER_T()
|
|
||||||
: m_cbBuffer( sizeof(m_rgBuffer) ),
|
|
||||||
m_fHeapAllocated( false ),
|
|
||||||
m_pBuffer(m_rgBuffer)
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
|
|
||||||
Default constructor where the inline buffer is used.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BUFFER_T(
|
|
||||||
__inout_bcount(cbInit) T* pbInit,
|
|
||||||
__in DWORD cbInit
|
|
||||||
) : m_pBuffer( pbInit ),
|
|
||||||
m_cbBuffer( cbInit ),
|
|
||||||
m_fHeapAllocated( false )
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
|
|
||||||
Instantiate BUFFER, initially using pbInit as buffer
|
|
||||||
This is useful for stack-buffers and inline-buffer class members
|
|
||||||
(see STACK_BUFFER and INLINE_BUFFER_INIT below)
|
|
||||||
|
|
||||||
BUFFER does not free pbInit.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pbInit - Initial buffer to use.
|
|
||||||
cbInit - Size of pbInit in bytes (not in elements).
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
_ASSERTE( NULL != pbInit );
|
|
||||||
_ASSERTE( cbInit > 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
~BUFFER_T()
|
|
||||||
{
|
|
||||||
if( IsHeapAllocated() )
|
|
||||||
{
|
|
||||||
_ASSERTE( NULL != m_pBuffer );
|
|
||||||
HeapFree( GetProcessHeap(), 0, m_pBuffer );
|
|
||||||
m_pBuffer = NULL;
|
|
||||||
m_cbBuffer = 0;
|
|
||||||
m_fHeapAllocated = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T*
|
|
||||||
QueryPtr(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Return pointer to data buffer.
|
|
||||||
//
|
|
||||||
return m_pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
QuerySize(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Return number of bytes.
|
|
||||||
//
|
|
||||||
return m_cbBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
__success(return == true)
|
|
||||||
bool
|
|
||||||
Resize(
|
|
||||||
const SIZE_T cbNewSize,
|
|
||||||
const bool fZeroMemoryBeyondOldSize = false
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
|
|
||||||
Resizes the buffer.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
cbNewSize - Size in bytes to grow to.
|
|
||||||
fZeroMemoryBeyondOldSize
|
|
||||||
- Whether to zero the region of memory of the
|
|
||||||
new buffer beyond the original size.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
TRUE on success, FALSE on failure.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
PVOID pNewMem;
|
|
||||||
|
|
||||||
if ( cbNewSize <= m_cbBuffer )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( cbNewSize > MAXDWORD )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD dwHeapAllocFlags = fZeroMemoryBeyondOldSize ? HEAP_ZERO_MEMORY : 0;
|
|
||||||
|
|
||||||
if( IsHeapAllocated() )
|
|
||||||
{
|
|
||||||
pNewMem = HeapReAlloc( GetProcessHeap(), dwHeapAllocFlags, m_pBuffer, cbNewSize );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pNewMem = HeapAlloc( GetProcessHeap(), dwHeapAllocFlags, cbNewSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pNewMem == NULL )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !IsHeapAllocated() )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// First time this block is allocated. Copy over old contents.
|
|
||||||
//
|
|
||||||
memcpy_s( pNewMem, static_cast<DWORD>(cbNewSize), m_pBuffer, m_cbBuffer );
|
|
||||||
m_fHeapAllocated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pBuffer = reinterpret_cast<T*>(pNewMem);
|
|
||||||
m_cbBuffer = static_cast<DWORD>(cbNewSize);
|
|
||||||
|
|
||||||
_ASSERTE( m_pBuffer != NULL );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsHeapAllocated(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return m_fHeapAllocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// The default inline buffer.
|
|
||||||
// This member should be at the beginning for alignment purposes.
|
|
||||||
//
|
|
||||||
T m_rgBuffer[LENGTH];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Is m_pBuffer dynamically allocated?
|
|
||||||
//
|
|
||||||
bool m_fHeapAllocated;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Size of the buffer as requested by client in bytes.
|
|
||||||
//
|
|
||||||
DWORD m_cbBuffer;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pointer to buffer.
|
|
||||||
//
|
|
||||||
__field_bcount_full(m_cbBuffer)
|
|
||||||
T* m_pBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Resizes the buffer by 2 if the ideal size is bigger
|
|
||||||
// than the buffer length. That give us lg(n) allocations.
|
|
||||||
//
|
|
||||||
// Use template inferring like:
|
|
||||||
//
|
|
||||||
// BUFFER buff;
|
|
||||||
// hr = ResizeBufferByTwo(buff, 100);
|
|
||||||
//
|
|
||||||
template<typename T, DWORD LENGTH>
|
|
||||||
HRESULT
|
|
||||||
ResizeBufferByTwo(
|
|
||||||
BUFFER_T<T,LENGTH>& Buffer,
|
|
||||||
SIZE_T cbIdealSize,
|
|
||||||
bool fZeroMemoryBeyondOldSize = false
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (cbIdealSize > Buffer.QuerySize())
|
|
||||||
{
|
|
||||||
if (!Buffer.Resize(max(cbIdealSize, static_cast<SIZE_T>(Buffer.QuerySize() * 2)),
|
|
||||||
fZeroMemoryBeyondOldSize))
|
|
||||||
{
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Lots of code uses BUFFER class to store a bunch of different
|
|
||||||
// structures, so m_rgBuffer needs to be 8 byte aligned when it is used
|
|
||||||
// as an opaque buffer.
|
|
||||||
//
|
|
||||||
#define INLINED_BUFFER_LEN 32
|
|
||||||
typedef BUFFER_T<BYTE, INLINED_BUFFER_LEN> BUFFER;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Assumption of macros below for pointer alignment purposes
|
|
||||||
//
|
|
||||||
C_ASSERT( sizeof(VOID*) <= sizeof(ULONGLONG) );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Declare a BUFFER that will use stack memory of <size>
|
|
||||||
// bytes. If the buffer overflows then a heap buffer will be allocated.
|
|
||||||
//
|
|
||||||
#define STACK_BUFFER( _name, _size ) \
|
|
||||||
ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \
|
|
||||||
BUFFER _name( (BYTE*)__aqw##_name, sizeof(__aqw##_name) )
|
|
||||||
|
|
||||||
//
|
|
||||||
// Macros for declaring and initializing a BUFFER that will use inline memory
|
|
||||||
// of <size> bytes as a member of an object.
|
|
||||||
//
|
|
||||||
#define INLINE_BUFFER( _name, _size ) \
|
|
||||||
ULONGLONG __aqw##_name[ ( ( (_size) + sizeof(ULONGLONG) - 1 ) / sizeof(ULONGLONG) ) ]; \
|
|
||||||
BUFFER _name;
|
|
||||||
|
|
||||||
#define INLINE_BUFFER_INIT( _name ) \
|
|
||||||
_name( (BYTE*)__aqw##_name, sizeof( __aqw##_name ) )
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _DATETIME_H_
|
|
||||||
#define _DATETIME_H_
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
StringTimeToFileTime(
|
|
||||||
PCSTR pszTime,
|
|
||||||
ULONGLONG * pulTime
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _DBGUTIL_H_
|
|
||||||
#define _DBGUTIL_H_
|
|
||||||
|
|
||||||
#include <crtdbg.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO
|
|
||||||
// Using _CrtDbg implementation. If hooking is desired
|
|
||||||
// wrappers should be provided here so that we can reimplement
|
|
||||||
// if neecessary.
|
|
||||||
//
|
|
||||||
// IF_DEBUG/DEBUG FLAGS
|
|
||||||
//
|
|
||||||
// registry configuration
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Debug error levels for DEBUG_FLAGS_VAR.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DEBUG_FLAG_INFO 0x00000001
|
|
||||||
#define DEBUG_FLAG_WARN 0x00000002
|
|
||||||
#define DEBUG_FLAG_ERROR 0x00000004
|
|
||||||
|
|
||||||
//
|
|
||||||
// Predefined error level values. These are backwards from the
|
|
||||||
// windows definitions.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN | DEBUG_FLAG_INFO)
|
|
||||||
#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ERROR | DEBUG_FLAG_WARN)
|
|
||||||
#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ERROR)
|
|
||||||
#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Global variables to control tracing. Generally per module
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef DEBUG_FLAGS_VAR
|
|
||||||
#define DEBUG_FLAGS_VAR g_dwDebugFlags
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DEBUG_LABEL_VAR
|
|
||||||
#define DEBUG_LABEL_VAR g_szDebugLabel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern PCSTR DEBUG_LABEL_VAR;
|
|
||||||
extern DWORD DEBUG_FLAGS_VAR;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Module should make this declaration globally.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DECLARE_DEBUG_PRINT_OBJECT( _pszLabel_ ) \
|
|
||||||
PCSTR DEBUG_LABEL_VAR = _pszLabel_; \
|
|
||||||
DWORD DEBUG_FLAGS_VAR = DEBUG_FLAGS_ANY; \
|
|
||||||
|
|
||||||
#define DECLARE_DEBUG_PRINT_OBJECT2( _pszLabel_, _dwLevel_ ) \
|
|
||||||
PCSTR DEBUG_LABEL_VAR = _pszLabel_; \
|
|
||||||
DWORD DEBUG_FLAGS_VAR = _dwLevel_; \
|
|
||||||
|
|
||||||
//
|
|
||||||
// This doesn't do anything now. Should be safe to call in dll main.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define CREATE_DEBUG_PRINT_OBJECT
|
|
||||||
|
|
||||||
//
|
|
||||||
// Trace macros
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DBG_CONTEXT _CRT_WARN, __FILE__, __LINE__, DEBUG_LABEL_VAR
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define DBGINFO(args) \
|
|
||||||
{if (DEBUG_FLAGS_VAR & DEBUG_FLAG_INFO) { _CrtDbgReport args; }}
|
|
||||||
#define DBGWARN(args) \
|
|
||||||
{if (DEBUG_FLAGS_VAR & DEBUG_FLAG_WARN) { _CrtDbgReport args; }}
|
|
||||||
#define DBGERROR(args) \
|
|
||||||
{if (DEBUG_FLAGS_VAR & DEBUG_FLAG_ERROR) { _CrtDbgReport args; }}
|
|
||||||
#else
|
|
||||||
#define DBGINFO
|
|
||||||
#define DBGWARN
|
|
||||||
#define DBGERROR
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DBGPRINTF DBGINFO
|
|
||||||
|
|
||||||
//
|
|
||||||
// Simple error traces
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DBGERROR_HR( _hr_ ) \
|
|
||||||
DBGERROR((DBG_CONTEXT, "hr=0x%x\n", _hr_))
|
|
||||||
|
|
||||||
#define DBGERROR_STATUS( _status_ ) \
|
|
||||||
DBGERROR((DBG_CONTEXT, "status=%d\n", _status_))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,325 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef __HASHFN_H__
|
|
||||||
#define __HASHFN_H__
|
|
||||||
|
|
||||||
|
|
||||||
// Produce a scrambled, randomish number in the range 0 to RANDOM_PRIME-1.
|
|
||||||
// Applying this to the results of the other hash functions is likely to
|
|
||||||
// produce a much better distribution, especially for the identity hash
|
|
||||||
// functions such as Hash(char c), where records will tend to cluster at
|
|
||||||
// the low end of the hashtable otherwise. LKRhash applies this internally
|
|
||||||
// to all hash signatures for exactly this reason.
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashScramble(DWORD dwHash)
|
|
||||||
{
|
|
||||||
// Here are 10 primes slightly greater than 10^9
|
|
||||||
// 1000000007, 1000000009, 1000000021, 1000000033, 1000000087,
|
|
||||||
// 1000000093, 1000000097, 1000000103, 1000000123, 1000000181.
|
|
||||||
|
|
||||||
// default value for "scrambling constant"
|
|
||||||
const DWORD RANDOM_CONSTANT = 314159269UL;
|
|
||||||
// large prime number, also used for scrambling
|
|
||||||
const DWORD RANDOM_PRIME = 1000000007UL;
|
|
||||||
|
|
||||||
return (RANDOM_CONSTANT * dwHash) % RANDOM_PRIME ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Faster scrambling function suggested by Eric Jacobsen
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashRandomizeBits(DWORD dw)
|
|
||||||
{
|
|
||||||
return (((dw * 1103515245 + 12345) >> 16)
|
|
||||||
| ((dw * 69069 + 1) & 0xffff0000));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Small prime number used as a multiplier in the supplied hash functions
|
|
||||||
const DWORD HASH_MULTIPLIER = 101;
|
|
||||||
|
|
||||||
#undef HASH_SHIFT_MULTIPLY
|
|
||||||
|
|
||||||
#ifdef HASH_SHIFT_MULTIPLY
|
|
||||||
# define HASH_MULTIPLY(dw) (((dw) << 7) - (dw))
|
|
||||||
#else
|
|
||||||
# define HASH_MULTIPLY(dw) ((dw) * HASH_MULTIPLIER)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fast, simple hash function that tends to give a good distribution.
|
|
||||||
// Apply HashScramble to the result if you're using this for something
|
|
||||||
// other than LKRhash.
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashString(
|
|
||||||
const char* psz,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
// force compiler to use unsigned arithmetic
|
|
||||||
const unsigned char* upsz = (const unsigned char*) psz;
|
|
||||||
|
|
||||||
for ( ; *upsz; ++upsz)
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + *upsz;
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashString(
|
|
||||||
__in_ecount(cch) const char* psz,
|
|
||||||
__in DWORD cch,
|
|
||||||
__in DWORD dwHash
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// force compiler to use unsigned arithmetic
|
|
||||||
const unsigned char* upsz = (const unsigned char*) psz;
|
|
||||||
|
|
||||||
for (DWORD Index = 0;
|
|
||||||
Index < cch;
|
|
||||||
++Index, ++upsz)
|
|
||||||
{
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + *upsz;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Unicode version of above
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashString(
|
|
||||||
const wchar_t* pwsz,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
for ( ; *pwsz; ++pwsz)
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + *pwsz;
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on length of the string instead of null-terminating character
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashString(
|
|
||||||
__in_ecount(cch) const wchar_t* pwsz,
|
|
||||||
__in DWORD cch,
|
|
||||||
__in DWORD dwHash
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (DWORD Index = 0;
|
|
||||||
Index < cch;
|
|
||||||
++Index, ++pwsz)
|
|
||||||
{
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + *pwsz;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Quick-'n'-dirty case-insensitive string hash function.
|
|
||||||
// Make sure that you follow up with _stricmp or _mbsicmp. You should
|
|
||||||
// also cache the length of strings and check those first. Caching
|
|
||||||
// an uppercase version of a string can help too.
|
|
||||||
// Again, apply HashScramble to the result if using with something other
|
|
||||||
// than LKRhash.
|
|
||||||
// Note: this is not really adequate for MBCS strings.
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashStringNoCase(
|
|
||||||
const char* psz,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
const unsigned char* upsz = (const unsigned char*) psz;
|
|
||||||
|
|
||||||
for ( ; *upsz; ++upsz)
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash)
|
|
||||||
+ (*upsz & 0xDF); // strip off lowercase bit
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashStringNoCase(
|
|
||||||
__in_ecount(cch)
|
|
||||||
const char* psz,
|
|
||||||
SIZE_T cch,
|
|
||||||
DWORD dwHash)
|
|
||||||
{
|
|
||||||
const unsigned char* upsz = (const unsigned char*) psz;
|
|
||||||
|
|
||||||
for (SIZE_T Index = 0;
|
|
||||||
Index < cch;
|
|
||||||
++Index, ++upsz)
|
|
||||||
{
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash)
|
|
||||||
+ (*upsz & 0xDF); // strip off lowercase bit
|
|
||||||
}
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Unicode version of above
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashStringNoCase(
|
|
||||||
const wchar_t* pwsz,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
for ( ; *pwsz; ++pwsz)
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF);
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unicode version of above with length
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashStringNoCase(
|
|
||||||
__in_ecount(cch)
|
|
||||||
const wchar_t* pwsz,
|
|
||||||
SIZE_T cch,
|
|
||||||
DWORD dwHash)
|
|
||||||
{
|
|
||||||
for (SIZE_T Index = 0;
|
|
||||||
Index < cch;
|
|
||||||
++Index, ++pwsz)
|
|
||||||
{
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + (*pwsz & 0xFFDF);
|
|
||||||
}
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// HashBlob returns the hash of a blob of arbitrary binary data.
|
|
||||||
//
|
|
||||||
// Warning: HashBlob is generally not the right way to hash a class object.
|
|
||||||
// Consider:
|
|
||||||
// class CFoo {
|
|
||||||
// public:
|
|
||||||
// char m_ch;
|
|
||||||
// double m_d;
|
|
||||||
// char* m_psz;
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// inline DWORD Hash(const CFoo& rFoo)
|
|
||||||
// { return HashBlob(&rFoo, sizeof(CFoo)); }
|
|
||||||
//
|
|
||||||
// This is the wrong way to hash a CFoo for two reasons: (a) there will be
|
|
||||||
// a 7-byte gap between m_ch and m_d imposed by the alignment restrictions
|
|
||||||
// of doubles, which will be filled with random data (usually non-zero for
|
|
||||||
// stack variables), and (b) it hashes the address (rather than the
|
|
||||||
// contents) of the string m_psz. Similarly,
|
|
||||||
//
|
|
||||||
// bool operator==(const CFoo& rFoo1, const CFoo& rFoo2)
|
|
||||||
// { return memcmp(&rFoo1, &rFoo2, sizeof(CFoo)) == 0; }
|
|
||||||
//
|
|
||||||
// does the wrong thing. Much better to do this:
|
|
||||||
//
|
|
||||||
// DWORD Hash(const CFoo& rFoo)
|
|
||||||
// {
|
|
||||||
// return HashString(rFoo.m_psz,
|
|
||||||
// HASH_MULTIPLIER * Hash(rFoo.m_ch)
|
|
||||||
// + Hash(rFoo.m_d));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Again, apply HashScramble if using with something other than LKRhash.
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
HashBlob(
|
|
||||||
const void* pv,
|
|
||||||
size_t cb,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
const BYTE * pb = static_cast<const BYTE *>(pv);
|
|
||||||
|
|
||||||
while (cb-- > 0)
|
|
||||||
dwHash = HASH_MULTIPLY(dwHash) + *pb++;
|
|
||||||
|
|
||||||
return dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Overloaded hash functions for all the major builtin types.
|
|
||||||
// Again, apply HashScramble to result if using with something other than
|
|
||||||
// LKRhash.
|
|
||||||
//
|
|
||||||
|
|
||||||
inline DWORD Hash(const char* psz)
|
|
||||||
{ return HashString(psz); }
|
|
||||||
|
|
||||||
inline DWORD Hash(const unsigned char* pusz)
|
|
||||||
{ return HashString(reinterpret_cast<const char*>(pusz)); }
|
|
||||||
|
|
||||||
inline DWORD Hash(const signed char* pssz)
|
|
||||||
{ return HashString(reinterpret_cast<const char*>(pssz)); }
|
|
||||||
|
|
||||||
inline DWORD Hash(const wchar_t* pwsz)
|
|
||||||
{ return HashString(pwsz); }
|
|
||||||
|
|
||||||
inline DWORD
|
|
||||||
Hash(
|
|
||||||
const GUID* pguid,
|
|
||||||
DWORD dwHash = 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
return * reinterpret_cast<const DWORD *>(const_cast<GUID*>(pguid)) + dwHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identity hash functions: scalar values map to themselves
|
|
||||||
inline DWORD Hash(char c)
|
|
||||||
{ return c; }
|
|
||||||
|
|
||||||
inline DWORD Hash(unsigned char uc)
|
|
||||||
{ return uc; }
|
|
||||||
|
|
||||||
inline DWORD Hash(signed char sc)
|
|
||||||
{ return sc; }
|
|
||||||
|
|
||||||
inline DWORD Hash(short sh)
|
|
||||||
{ return sh; }
|
|
||||||
|
|
||||||
inline DWORD Hash(unsigned short ush)
|
|
||||||
{ return ush; }
|
|
||||||
|
|
||||||
inline DWORD Hash(int i)
|
|
||||||
{ return i; }
|
|
||||||
|
|
||||||
inline DWORD Hash(unsigned int u)
|
|
||||||
{ return u; }
|
|
||||||
|
|
||||||
inline DWORD Hash(long l)
|
|
||||||
{ return l; }
|
|
||||||
|
|
||||||
inline DWORD Hash(unsigned long ul)
|
|
||||||
{ return ul; }
|
|
||||||
|
|
||||||
inline DWORD Hash(float f)
|
|
||||||
{
|
|
||||||
// be careful of rounding errors when computing keys
|
|
||||||
union {
|
|
||||||
float f;
|
|
||||||
DWORD dw;
|
|
||||||
} u;
|
|
||||||
u.f = f;
|
|
||||||
return u.dw;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DWORD Hash(double dbl)
|
|
||||||
{
|
|
||||||
// be careful of rounding errors when computing keys
|
|
||||||
union {
|
|
||||||
double dbl;
|
|
||||||
DWORD dw[2];
|
|
||||||
} u;
|
|
||||||
u.dbl = dbl;
|
|
||||||
return u.dw[0] * HASH_MULTIPLIER + u.dw[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __HASHFN_H__
|
|
||||||
|
|
@ -1,666 +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 <crtdbg.h>
|
|
||||||
#include "rwlock.h"
|
|
||||||
#include "prime.h"
|
|
||||||
|
|
||||||
template <class _Record>
|
|
||||||
class HASH_NODE
|
|
||||||
{
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
friend class HASH_TABLE;
|
|
||||||
|
|
||||||
HASH_NODE(
|
|
||||||
_Record * pRecord,
|
|
||||||
DWORD dwHash
|
|
||||||
) : _pNext (NULL),
|
|
||||||
_pRecord (pRecord),
|
|
||||||
_dwHash (dwHash)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~HASH_NODE()
|
|
||||||
{
|
|
||||||
_ASSERTE(_pRecord == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Next node in the hash table look-aside
|
|
||||||
HASH_NODE<_Record> *_pNext;
|
|
||||||
|
|
||||||
// actual record
|
|
||||||
_Record * _pRecord;
|
|
||||||
|
|
||||||
// hash value
|
|
||||||
DWORD _dwHash;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
class HASH_TABLE
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
typedef BOOL
|
|
||||||
(PFN_DELETE_IF)(
|
|
||||||
_Record * pRecord,
|
|
||||||
PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef VOID
|
|
||||||
(PFN_APPLY)(
|
|
||||||
_Record * pRecord,
|
|
||||||
PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
public:
|
|
||||||
HASH_TABLE(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
: _ppBuckets( NULL ),
|
|
||||||
_nBuckets( 0 ),
|
|
||||||
_nItems( 0 )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual
|
|
||||||
~HASH_TABLE();
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
ReferenceRecord(
|
|
||||||
_Record * pRecord
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
DereferenceRecord(
|
|
||||||
_Record * pRecord
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
_Key
|
|
||||||
ExtractKey(
|
|
||||||
_Record * pRecord
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
DWORD
|
|
||||||
CalcKeyHash(
|
|
||||||
_Key key
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
BOOL
|
|
||||||
EqualKeys(
|
|
||||||
_Key key1,
|
|
||||||
_Key key2
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
Count(
|
|
||||||
VOID
|
|
||||||
) const;
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsInitialized(
|
|
||||||
VOID
|
|
||||||
) const;
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
Clear();
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
Initialize(
|
|
||||||
DWORD nBucketSize
|
|
||||||
);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
FindKey(
|
|
||||||
_Key key,
|
|
||||||
_Record ** ppRecord
|
|
||||||
);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
HRESULT
|
|
||||||
InsertRecord(
|
|
||||||
_Record * pRecord
|
|
||||||
);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
DeleteKey(
|
|
||||||
_Key key
|
|
||||||
);
|
|
||||||
|
|
||||||
virtual
|
|
||||||
VOID
|
|
||||||
DeleteIf(
|
|
||||||
PFN_DELETE_IF pfnDeleteIf,
|
|
||||||
PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
Apply(
|
|
||||||
PFN_APPLY pfnApply,
|
|
||||||
PVOID pvContext
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
__success(*ppNode != NULL && return != FALSE)
|
|
||||||
BOOL
|
|
||||||
FindNodeInternal(
|
|
||||||
_Key key,
|
|
||||||
DWORD dwHash,
|
|
||||||
__deref_out
|
|
||||||
HASH_NODE<_Record> ** ppNode,
|
|
||||||
__deref_opt_out
|
|
||||||
HASH_NODE<_Record> *** pppPreviousNodeNextPointer = NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DeleteNode(
|
|
||||||
HASH_NODE<_Record> * pNode
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (pNode->_pRecord != NULL)
|
|
||||||
{
|
|
||||||
DereferenceRecord(pNode->_pRecord);
|
|
||||||
pNode->_pRecord = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
RehashTableIfNeeded(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
HASH_NODE<_Record> ** _ppBuckets;
|
|
||||||
DWORD _nBuckets;
|
|
||||||
DWORD _nItems;
|
|
||||||
//
|
|
||||||
// Allow to use lock object in const methods.
|
|
||||||
//
|
|
||||||
mutable
|
|
||||||
CWSDRWLock _tableLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
HRESULT
|
|
||||||
HASH_TABLE<_Record,_Key>::Initialize(
|
|
||||||
DWORD nBuckets
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if ( nBuckets == 0 )
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nBuckets >= MAXDWORD/sizeof(HASH_NODE<_Record> *))
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ASSERTE(_ppBuckets == NULL );
|
|
||||||
if ( _ppBuckets != NULL )
|
|
||||||
{
|
|
||||||
hr = E_INVALIDARG;
|
|
||||||
goto Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = _tableLock.Init();
|
|
||||||
if ( FAILED( hr ) )
|
|
||||||
{
|
|
||||||
goto Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ppBuckets = (HASH_NODE<_Record> **)HeapAlloc(
|
|
||||||
GetProcessHeap(),
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
nBuckets*sizeof(HASH_NODE<_Record> *));
|
|
||||||
if (_ppBuckets == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
goto Failed;
|
|
||||||
}
|
|
||||||
_nBuckets = nBuckets;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
Failed:
|
|
||||||
|
|
||||||
if (_ppBuckets)
|
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(),
|
|
||||||
0,
|
|
||||||
_ppBuckets);
|
|
||||||
_ppBuckets = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
HASH_TABLE<_Record,_Key>::~HASH_TABLE()
|
|
||||||
{
|
|
||||||
if (_ppBuckets == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ASSERTE(_nItems == 0);
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(),
|
|
||||||
0,
|
|
||||||
_ppBuckets);
|
|
||||||
_ppBuckets = NULL;
|
|
||||||
_nBuckets = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template< class _Record, class _Key>
|
|
||||||
DWORD
|
|
||||||
HASH_TABLE<_Record,_Key>::Count() const
|
|
||||||
{
|
|
||||||
return _nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
template< class _Record, class _Key>
|
|
||||||
bool
|
|
||||||
HASH_TABLE<_Record,_Key>::IsInitialized(
|
|
||||||
VOID
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return _ppBuckets != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::Clear()
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> *pCurrent;
|
|
||||||
HASH_NODE<_Record> *pNext;
|
|
||||||
|
|
||||||
// This is here in the off cases where someone instantiates a hashtable
|
|
||||||
// and then does an automatic "clear" before its destruction WITHOUT
|
|
||||||
// ever initializing it.
|
|
||||||
if ( ! _tableLock.QueryInited() )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.ExclusiveAcquire();
|
|
||||||
|
|
||||||
for (DWORD i=0; i<_nBuckets; i++)
|
|
||||||
{
|
|
||||||
pCurrent = _ppBuckets[i];
|
|
||||||
_ppBuckets[i] = NULL;
|
|
||||||
while (pCurrent != NULL)
|
|
||||||
{
|
|
||||||
pNext = pCurrent->_pNext;
|
|
||||||
DeleteNode(pCurrent);
|
|
||||||
pCurrent = pNext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_nItems = 0;
|
|
||||||
_tableLock.ExclusiveRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
__success(*ppNode != NULL && return != FALSE)
|
|
||||||
BOOL
|
|
||||||
HASH_TABLE<_Record,_Key>::FindNodeInternal(
|
|
||||||
_Key key,
|
|
||||||
DWORD dwHash,
|
|
||||||
__deref_out
|
|
||||||
HASH_NODE<_Record> ** ppNode,
|
|
||||||
__deref_opt_out
|
|
||||||
HASH_NODE<_Record> *** pppPreviousNodeNextPointer
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
Return value indicates whether the item is found
|
|
||||||
key, dwHash - key and hash for the node to find
|
|
||||||
ppNode - on successful return, the node found, on failed return, the first
|
|
||||||
node with hash value greater than the node to be found
|
|
||||||
pppPreviousNodeNextPointer - the pointer to previous node's _pNext
|
|
||||||
|
|
||||||
This routine may be called under either read or write lock
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> **ppPreviousNodeNextPointer;
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
BOOL fFound = FALSE;
|
|
||||||
|
|
||||||
ppPreviousNodeNextPointer = _ppBuckets + (dwHash % _nBuckets);
|
|
||||||
pNode = *ppPreviousNodeNextPointer;
|
|
||||||
while (pNode != NULL)
|
|
||||||
{
|
|
||||||
if (pNode->_dwHash == dwHash)
|
|
||||||
{
|
|
||||||
if (EqualKeys(key,
|
|
||||||
ExtractKey(pNode->_pRecord)))
|
|
||||||
{
|
|
||||||
fFound = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pNode->_dwHash > dwHash)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppPreviousNodeNextPointer = &(pNode->_pNext);
|
|
||||||
pNode = *ppPreviousNodeNextPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
__analysis_assume( (pNode == NULL && fFound == FALSE) ||
|
|
||||||
(pNode != NULL && fFound == TRUE ) );
|
|
||||||
*ppNode = pNode;
|
|
||||||
if (pppPreviousNodeNextPointer != NULL)
|
|
||||||
{
|
|
||||||
*pppPreviousNodeNextPointer = ppPreviousNodeNextPointer;
|
|
||||||
}
|
|
||||||
return fFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::FindKey(
|
|
||||||
_Key key,
|
|
||||||
_Record ** ppRecord
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
|
|
||||||
*ppRecord = NULL;
|
|
||||||
|
|
||||||
DWORD dwHash = CalcKeyHash(key);
|
|
||||||
|
|
||||||
_tableLock.SharedAcquire();
|
|
||||||
|
|
||||||
if (FindNodeInternal(key, dwHash, &pNode) &&
|
|
||||||
pNode->_pRecord != NULL)
|
|
||||||
{
|
|
||||||
ReferenceRecord(pNode->_pRecord);
|
|
||||||
*ppRecord = pNode->_pRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.SharedRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
HRESULT
|
|
||||||
HASH_TABLE<_Record,_Key>::InsertRecord(
|
|
||||||
_Record * pRecord
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
This method inserts a node for this record and also empty nodes for paths
|
|
||||||
in the heirarchy leading upto this path
|
|
||||||
|
|
||||||
The insert is done under only a read-lock - this is possible by keeping
|
|
||||||
the hashes in a bucket in increasing order and using interlocked operations
|
|
||||||
to actually insert the item in the hash-bucket lookaside list and the parent
|
|
||||||
children list
|
|
||||||
|
|
||||||
Returns HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) if the record already exists.
|
|
||||||
Never leak this error to the end user because "*file* already exists" may be confusing.
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
BOOL fLocked = FALSE;
|
|
||||||
_Key key = ExtractKey(pRecord);
|
|
||||||
DWORD dwHash = CalcKeyHash(key);
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
HASH_NODE<_Record> * pNewNode;
|
|
||||||
HASH_NODE<_Record> * pNextNode;
|
|
||||||
HASH_NODE<_Record> ** ppPreviousNodeNextPointer;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Ownership of pRecord is not transferred to pNewNode yet, so remember
|
|
||||||
// to either set it to null before deleting pNewNode or add an extra
|
|
||||||
// reference later - this is to make sure we do not do an extra ref/deref
|
|
||||||
// which users may view as getting flushed out of the hash-table
|
|
||||||
//
|
|
||||||
pNewNode = new HASH_NODE<_Record>(pRecord, dwHash);
|
|
||||||
if (pNewNode == NULL)
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.SharedAcquire();
|
|
||||||
fLocked = TRUE;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Find the right place to add this node
|
|
||||||
//
|
|
||||||
if (FindNodeInternal(key, dwHash, &pNextNode, &ppPreviousNodeNextPointer))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// If node already there, return error
|
|
||||||
//
|
|
||||||
pNewNode->_pRecord = NULL;
|
|
||||||
DeleteNode(pNewNode);
|
|
||||||
|
|
||||||
//
|
|
||||||
// We should never leak this error to the end user
|
|
||||||
// because "file already exists" may be confusing.
|
|
||||||
//
|
|
||||||
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// If another node got inserted in between, we will have to retry
|
|
||||||
//
|
|
||||||
pNewNode->_pNext = pNextNode;
|
|
||||||
} while (InterlockedCompareExchangePointer((PVOID *)ppPreviousNodeNextPointer,
|
|
||||||
pNewNode,
|
|
||||||
pNextNode) != pNextNode);
|
|
||||||
// pass ownership of pRecord now
|
|
||||||
if (pRecord != NULL)
|
|
||||||
{
|
|
||||||
ReferenceRecord(pRecord);
|
|
||||||
pRecord = NULL;
|
|
||||||
}
|
|
||||||
InterlockedIncrement((LONG *)&_nItems);
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (fLocked)
|
|
||||||
{
|
|
||||||
_tableLock.SharedRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
RehashTableIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::DeleteKey(
|
|
||||||
_Key key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
HASH_NODE<_Record> **ppPreviousNodeNextPointer;
|
|
||||||
|
|
||||||
DWORD dwHash = CalcKeyHash(key);
|
|
||||||
|
|
||||||
_tableLock.ExclusiveAcquire();
|
|
||||||
|
|
||||||
if (FindNodeInternal(key, dwHash, &pNode, &ppPreviousNodeNextPointer))
|
|
||||||
{
|
|
||||||
*ppPreviousNodeNextPointer = pNode->_pNext;
|
|
||||||
DeleteNode(pNode);
|
|
||||||
_nItems--;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.ExclusiveRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::DeleteIf(
|
|
||||||
PFN_DELETE_IF pfnDeleteIf,
|
|
||||||
PVOID pvContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
HASH_NODE<_Record> **ppPreviousNodeNextPointer;
|
|
||||||
|
|
||||||
_tableLock.ExclusiveAcquire();
|
|
||||||
|
|
||||||
for (DWORD i=0; i<_nBuckets; i++)
|
|
||||||
{
|
|
||||||
ppPreviousNodeNextPointer = _ppBuckets + i;
|
|
||||||
pNode = *ppPreviousNodeNextPointer;
|
|
||||||
while (pNode != NULL)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Non empty nodes deleted based on DeleteIf, empty nodes deleted
|
|
||||||
// if they have no children
|
|
||||||
//
|
|
||||||
if (pfnDeleteIf(pNode->_pRecord, pvContext))
|
|
||||||
{
|
|
||||||
*ppPreviousNodeNextPointer = pNode->_pNext;
|
|
||||||
DeleteNode(pNode);
|
|
||||||
_nItems--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ppPreviousNodeNextPointer = &pNode->_pNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
pNode = *ppPreviousNodeNextPointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.ExclusiveRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::Apply(
|
|
||||||
PFN_APPLY pfnApply,
|
|
||||||
PVOID pvContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
|
|
||||||
_tableLock.SharedAcquire();
|
|
||||||
|
|
||||||
for (DWORD i=0; i<_nBuckets; i++)
|
|
||||||
{
|
|
||||||
pNode = _ppBuckets[i];
|
|
||||||
while (pNode != NULL)
|
|
||||||
{
|
|
||||||
if (pNode->_pRecord != NULL)
|
|
||||||
{
|
|
||||||
pfnApply(pNode->_pRecord, pvContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
pNode = pNode->_pNext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.SharedRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Record, class _Key>
|
|
||||||
VOID
|
|
||||||
HASH_TABLE<_Record,_Key>::RehashTableIfNeeded(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HASH_NODE<_Record> **ppBuckets;
|
|
||||||
DWORD nBuckets;
|
|
||||||
HASH_NODE<_Record> *pNode;
|
|
||||||
HASH_NODE<_Record> *pNextNode;
|
|
||||||
HASH_NODE<_Record> **ppNextPointer;
|
|
||||||
HASH_NODE<_Record> *pNewNextNode;
|
|
||||||
DWORD nNewBuckets;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If number of items has become too many, we will double the hash table
|
|
||||||
// size (we never reduce it however)
|
|
||||||
//
|
|
||||||
if (_nItems <= PRIME::GetPrime(2*_nBuckets))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_tableLock.ExclusiveAcquire();
|
|
||||||
|
|
||||||
nNewBuckets = PRIME::GetPrime(2*_nBuckets);
|
|
||||||
|
|
||||||
if (_nItems <= nNewBuckets)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
nBuckets = nNewBuckets;
|
|
||||||
if (nBuckets >= 0xffffffff/sizeof(HASH_NODE<_Record> *))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
ppBuckets = (HASH_NODE<_Record> **)HeapAlloc(
|
|
||||||
GetProcessHeap(),
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
nBuckets*sizeof(HASH_NODE<_Record> *));
|
|
||||||
if (ppBuckets == NULL)
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Take out nodes from the old hash table and insert in the new one, make
|
|
||||||
// sure to keep the hashes in increasing order
|
|
||||||
//
|
|
||||||
for (DWORD i=0; i<_nBuckets; i++)
|
|
||||||
{
|
|
||||||
pNode = _ppBuckets[i];
|
|
||||||
while (pNode != NULL)
|
|
||||||
{
|
|
||||||
pNextNode = pNode->_pNext;
|
|
||||||
|
|
||||||
ppNextPointer = ppBuckets + (pNode->_dwHash % nBuckets);
|
|
||||||
pNewNextNode = *ppNextPointer;
|
|
||||||
while (pNewNextNode != NULL &&
|
|
||||||
pNewNextNode->_dwHash <= pNode->_dwHash)
|
|
||||||
{
|
|
||||||
ppNextPointer = &pNewNextNode->_pNext;
|
|
||||||
pNewNextNode = pNewNextNode->_pNext;
|
|
||||||
}
|
|
||||||
pNode->_pNext = pNewNextNode;
|
|
||||||
*ppNextPointer = pNode;
|
|
||||||
|
|
||||||
pNode = pNextNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, _ppBuckets);
|
|
||||||
_ppBuckets = ppBuckets;
|
|
||||||
_nBuckets = nBuckets;
|
|
||||||
ppBuckets = NULL;
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
_tableLock.ExclusiveRelease();
|
|
||||||
}
|
|
||||||
|
|
@ -1,163 +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
|
|
||||||
|
|
||||||
#ifndef _LIST_ENTRY_H
|
|
||||||
#define _LIST_ENTRY_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// Doubly-linked list manipulation routines.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#define InitializeListHead32(ListHead) (\
|
|
||||||
(ListHead)->Flink = (ListHead)->Blink = PtrToUlong((ListHead)))
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
InitializeListHead(
|
|
||||||
IN PLIST_ENTRY ListHead
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ListHead->Flink = ListHead->Blink = ListHead;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
BOOLEAN
|
|
||||||
IsListEmpty(
|
|
||||||
IN const LIST_ENTRY * ListHead
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return (BOOLEAN)(ListHead->Flink == ListHead);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
BOOLEAN
|
|
||||||
RemoveEntryList(
|
|
||||||
IN PLIST_ENTRY Entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Blink;
|
|
||||||
PLIST_ENTRY Flink;
|
|
||||||
|
|
||||||
Flink = Entry->Flink;
|
|
||||||
Blink = Entry->Blink;
|
|
||||||
Blink->Flink = Flink;
|
|
||||||
Flink->Blink = Blink;
|
|
||||||
return (BOOLEAN)(Flink == Blink);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
PLIST_ENTRY
|
|
||||||
RemoveHeadList(
|
|
||||||
IN PLIST_ENTRY ListHead
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Flink;
|
|
||||||
PLIST_ENTRY Entry;
|
|
||||||
|
|
||||||
Entry = ListHead->Flink;
|
|
||||||
Flink = Entry->Flink;
|
|
||||||
ListHead->Flink = Flink;
|
|
||||||
Flink->Blink = ListHead;
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
PLIST_ENTRY
|
|
||||||
RemoveTailList(
|
|
||||||
IN PLIST_ENTRY ListHead
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Blink;
|
|
||||||
PLIST_ENTRY Entry;
|
|
||||||
|
|
||||||
Entry = ListHead->Blink;
|
|
||||||
Blink = Entry->Blink;
|
|
||||||
ListHead->Blink = Blink;
|
|
||||||
Blink->Flink = ListHead;
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
InsertTailList(
|
|
||||||
IN PLIST_ENTRY ListHead,
|
|
||||||
IN PLIST_ENTRY Entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Blink;
|
|
||||||
|
|
||||||
Blink = ListHead->Blink;
|
|
||||||
Entry->Flink = ListHead;
|
|
||||||
Entry->Blink = Blink;
|
|
||||||
Blink->Flink = Entry;
|
|
||||||
ListHead->Blink = Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
InsertHeadList(
|
|
||||||
IN PLIST_ENTRY ListHead,
|
|
||||||
IN PLIST_ENTRY Entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Flink;
|
|
||||||
|
|
||||||
Flink = ListHead->Flink;
|
|
||||||
Entry->Flink = Flink;
|
|
||||||
Entry->Blink = ListHead;
|
|
||||||
Flink->Blink = Entry;
|
|
||||||
ListHead->Flink = Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
AppendTailList(
|
|
||||||
IN PLIST_ENTRY ListHead,
|
|
||||||
IN PLIST_ENTRY ListToAppend
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY ListEnd = ListHead->Blink;
|
|
||||||
|
|
||||||
ListHead->Blink->Flink = ListToAppend;
|
|
||||||
ListHead->Blink = ListToAppend->Blink;
|
|
||||||
ListToAppend->Blink->Flink = ListHead;
|
|
||||||
ListToAppend->Blink = ListEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
PSINGLE_LIST_ENTRY
|
|
||||||
PopEntryList(
|
|
||||||
PSINGLE_LIST_ENTRY ListHead
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PSINGLE_LIST_ENTRY FirstEntry;
|
|
||||||
FirstEntry = ListHead->Next;
|
|
||||||
if (FirstEntry != NULL) {
|
|
||||||
ListHead->Next = FirstEntry->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirstEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
PushEntryList(
|
|
||||||
PSINGLE_LIST_ENTRY ListHead,
|
|
||||||
PSINGLE_LIST_ENTRY Entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Entry->Next = ListHead->Next;
|
|
||||||
ListHead->Next = Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _MACROS_H
|
|
||||||
#define _MACROS_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// The DIFF macro should be used around an expression involving pointer
|
|
||||||
// subtraction. The expression passed to DIFF is cast to a size_t type,
|
|
||||||
// allowing the result to be easily assigned to any 32-bit variable or
|
|
||||||
// passed to a function expecting a 32-bit argument.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define DIFF(x) ((size_t)(x))
|
|
||||||
|
|
||||||
// Change a hexadecimal digit to its numerical equivalent
|
|
||||||
#define TOHEX( ch ) \
|
|
||||||
((ch) > L'9' ? \
|
|
||||||
(ch) >= L'a' ? \
|
|
||||||
(ch) - L'a' + 10 : \
|
|
||||||
(ch) - L'A' + 10 \
|
|
||||||
: (ch) - L'0')
|
|
||||||
|
|
||||||
|
|
||||||
// Change a number to its Hexadecimal equivalent
|
|
||||||
|
|
||||||
#define TODIGIT( nDigit ) \
|
|
||||||
(CHAR)((nDigit) > 9 ? \
|
|
||||||
(nDigit) - 10 + 'A' \
|
|
||||||
: (nDigit) + '0')
|
|
||||||
|
|
||||||
|
|
||||||
inline int
|
|
||||||
SAFEIsSpace(UCHAR c)
|
|
||||||
{
|
|
||||||
return isspace( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
|
||||||
SAFEIsAlNum(UCHAR c)
|
|
||||||
{
|
|
||||||
return isalnum( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
|
||||||
SAFEIsAlpha(UCHAR c)
|
|
||||||
{
|
|
||||||
return isalpha( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
|
||||||
SAFEIsXDigit(UCHAR c)
|
|
||||||
{
|
|
||||||
return isxdigit( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
|
||||||
SAFEIsDigit(UCHAR c)
|
|
||||||
{
|
|
||||||
return isdigit( c );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _MACROS_H
|
|
||||||
|
|
@ -1,474 +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 warning (disable : 4267)
|
|
||||||
|
|
||||||
#include "precomp.h"
|
|
||||||
#include "multisz.h"
|
|
||||||
#include <tchar.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// Private Definitions
|
|
||||||
//
|
|
||||||
|
|
||||||
#define MAXULONG 4294967295
|
|
||||||
#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r')
|
|
||||||
|
|
||||||
//
|
|
||||||
// When appending data, this is the extra amount we request to avoid
|
|
||||||
// reallocations
|
|
||||||
//
|
|
||||||
#define STR_SLOP 128
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
MULTISZ::CalcLength( const WCHAR * str,
|
|
||||||
LPDWORD pcStrings )
|
|
||||||
{
|
|
||||||
DWORD count = 0;
|
|
||||||
DWORD total = 1;
|
|
||||||
DWORD len;
|
|
||||||
|
|
||||||
while( *str ) {
|
|
||||||
len = ::wcslen( str ) + 1;
|
|
||||||
total += len;
|
|
||||||
str += len;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pcStrings != NULL ) {
|
|
||||||
*pcStrings = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
|
|
||||||
} // MULTISZ::CalcLength
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZ::FindString( const WCHAR * str )
|
|
||||||
{
|
|
||||||
|
|
||||||
WCHAR * multisz;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sanity check.
|
|
||||||
//
|
|
||||||
|
|
||||||
DBG_ASSERT( QueryStr() != NULL );
|
|
||||||
DBG_ASSERT( str != NULL );
|
|
||||||
DBG_ASSERT( *str != '\0' );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scan it.
|
|
||||||
//
|
|
||||||
|
|
||||||
multisz = QueryStr();
|
|
||||||
|
|
||||||
while( *multisz != '\0' ) {
|
|
||||||
|
|
||||||
if( !::wcscmp( multisz, str ) ) {
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
multisz += ::wcslen( multisz ) + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
} // MULTISZ::FindString
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZ::FindStringNoCase( const WCHAR * str )
|
|
||||||
{
|
|
||||||
|
|
||||||
WCHAR * multisz;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sanity check.
|
|
||||||
//
|
|
||||||
|
|
||||||
DBG_ASSERT( QueryStr() != NULL );
|
|
||||||
DBG_ASSERT( str != NULL );
|
|
||||||
DBG_ASSERT( *str != '\0' );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scan it.
|
|
||||||
//
|
|
||||||
|
|
||||||
multisz = QueryStr();
|
|
||||||
|
|
||||||
while( *multisz != '\0' ) {
|
|
||||||
|
|
||||||
if( !_wcsicmp( multisz, str ) ) {
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
multisz += wcslen( multisz ) + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
} // MULTISZ::FindStringNoCase
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MULTISZ::AuxInit( const WCHAR * pInit )
|
|
||||||
{
|
|
||||||
BOOL fRet;
|
|
||||||
|
|
||||||
if ( pInit )
|
|
||||||
{
|
|
||||||
DWORD cStrings;
|
|
||||||
int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(WCHAR);
|
|
||||||
fRet = Resize( cbCopy );
|
|
||||||
|
|
||||||
if ( fRet ) {
|
|
||||||
CopyMemory( QueryPtr(), pInit, cbCopy );
|
|
||||||
m_cchLen = (cbCopy)/sizeof(WCHAR);
|
|
||||||
m_cStrings = cStrings;
|
|
||||||
} else {
|
|
||||||
// BUFFER::SetValid( FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // MULTISZ::AuxInit()
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
|
|
||||||
NAME: MULTISZ::AuxAppend
|
|
||||||
|
|
||||||
SYNOPSIS: Appends the string onto the multisz.
|
|
||||||
|
|
||||||
ENTRY: Object to append
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
BOOL MULTISZ::AuxAppend( const WCHAR * pStr, UINT cbStr, BOOL fAddSlop )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( pStr != NULL );
|
|
||||||
|
|
||||||
UINT cbThis = QueryCB();
|
|
||||||
|
|
||||||
DBG_ASSERT( cbThis >= 2 );
|
|
||||||
|
|
||||||
if( cbThis == 4 ) {
|
|
||||||
|
|
||||||
//
|
|
||||||
// It's empty, so start at the beginning.
|
|
||||||
//
|
|
||||||
|
|
||||||
cbThis = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//
|
|
||||||
// It's not empty, so back up over the final terminating NULL.
|
|
||||||
//
|
|
||||||
|
|
||||||
cbThis -= sizeof(WCHAR);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Only resize when we have to. When we do resize, we tack on
|
|
||||||
// some extra space to avoid extra reallocations.
|
|
||||||
//
|
|
||||||
// Note: QuerySize returns the requested size of the string buffer,
|
|
||||||
// *not* the strlen of the buffer
|
|
||||||
//
|
|
||||||
|
|
||||||
//AcIncrement( CacMultiszAppend);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for the arithmetic overflow
|
|
||||||
//
|
|
||||||
// ( 2 * sizeof( WCHAR ) ) is for the double terminator
|
|
||||||
//
|
|
||||||
ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(WCHAR);
|
|
||||||
if ( cb64Required > MAXULONG )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_ARITHMETIC_OVERFLOW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ( QuerySize() < (DWORD) cb64Required )
|
|
||||||
{
|
|
||||||
ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 );
|
|
||||||
//
|
|
||||||
// Check for the arithmetic overflow
|
|
||||||
//
|
|
||||||
if ( cb64AllocSize > MAXULONG )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_ARITHMETIC_OVERFLOW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ( !Resize( (DWORD) cb64AllocSize ) )
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the exact string and tack on the double terminator
|
|
||||||
memcpy( (BYTE *) QueryPtr() + cbThis,
|
|
||||||
pStr,
|
|
||||||
cbStr);
|
|
||||||
*(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0';
|
|
||||||
*(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(WCHAR) ) = L'\0';
|
|
||||||
|
|
||||||
m_cchLen = CalcLength( (const WCHAR *)QueryPtr(), &m_cStrings );
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
} // MULTISZ::AuxAppend()
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZ::CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcch) const
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
Copies the string into the WCHAR buffer passed in if the buffer
|
|
||||||
is sufficient to hold the translated string.
|
|
||||||
If the buffer is small, the function returns small and sets *lpcch
|
|
||||||
to contain the required number of characters.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
lpszBuffer pointer to WCHAR buffer which on return contains
|
|
||||||
the UNICODE version of string on success.
|
|
||||||
lpcch pointer to DWORD containing the length of the buffer.
|
|
||||||
If *lpcch == 0 then the function returns TRUE with
|
|
||||||
the count of characters required stored in *lpcch.
|
|
||||||
Also in this case lpszBuffer is not affected.
|
|
||||||
Returns:
|
|
||||||
TRUE on success.
|
|
||||||
FALSE on failure. Use GetLastError() for further details.
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
BOOL fReturn = TRUE;
|
|
||||||
|
|
||||||
if ( lpcch == NULL) {
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER);
|
|
||||||
return ( FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( *lpcch == 0) {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inquiring the size of buffer alone
|
|
||||||
//
|
|
||||||
*lpcch = QueryCCH() + 1; // add one character for terminating null
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copy after conversion from ANSI to Unicode
|
|
||||||
//
|
|
||||||
int iRet;
|
|
||||||
iRet = MultiByteToWideChar( CP_ACP,
|
|
||||||
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
||||||
QueryStrA(), QueryCCH() + 1,
|
|
||||||
lpszBuffer, (int )*lpcch);
|
|
||||||
|
|
||||||
if ( iRet == 0 || iRet != (int ) *lpcch) {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Error in conversion.
|
|
||||||
//
|
|
||||||
fReturn = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ( fReturn);
|
|
||||||
} // MULTISZ::CopyToBuffer()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZ::CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
Copies the string into the WCHAR buffer passed in if the buffer
|
|
||||||
is sufficient to hold the translated string.
|
|
||||||
If the buffer is small, the function returns small and sets *lpcch
|
|
||||||
to contain the required number of characters.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
lpszBuffer pointer to WCHAR buffer which on return contains
|
|
||||||
the string on success.
|
|
||||||
lpcch pointer to DWORD containing the length of the buffer.
|
|
||||||
If *lpcch == 0 then the function returns TRUE with
|
|
||||||
the count of characters required stored in lpcch.
|
|
||||||
Also in this case lpszBuffer is not affected.
|
|
||||||
Returns:
|
|
||||||
TRUE on success.
|
|
||||||
FALSE on failure. Use GetLastError() for further details.
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
BOOL fReturn = TRUE;
|
|
||||||
|
|
||||||
if ( lpcch == NULL) {
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER);
|
|
||||||
return ( FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
register DWORD cch = QueryCCH();
|
|
||||||
|
|
||||||
if ( *lpcch >= cch) {
|
|
||||||
|
|
||||||
DBG_ASSERT( lpszBuffer);
|
|
||||||
memcpy( lpszBuffer, QueryStr(), cch * sizeof(WCHAR));
|
|
||||||
} else {
|
|
||||||
DBG_ASSERT( *lpcch < cch);
|
|
||||||
SetLastError( ERROR_INSUFFICIENT_BUFFER);
|
|
||||||
fReturn = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*lpcch = cch;
|
|
||||||
|
|
||||||
return ( fReturn);
|
|
||||||
} // MULTISZ::CopyToBuffer()
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZ::Equals(
|
|
||||||
MULTISZ* pmszRhs
|
|
||||||
)
|
|
||||||
//
|
|
||||||
// Compares this to pmszRhs, returns TRUE if equal
|
|
||||||
//
|
|
||||||
{
|
|
||||||
DBG_ASSERT( NULL != pmszRhs );
|
|
||||||
|
|
||||||
PCWSTR pszLhs = First( );
|
|
||||||
PCWSTR pszRhs = pmszRhs->First( );
|
|
||||||
|
|
||||||
if( m_cStrings != pmszRhs->m_cStrings )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( NULL != pszLhs )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( NULL != pszRhs );
|
|
||||||
|
|
||||||
if( 0 != wcscmp( pszLhs, pszRhs ) )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszLhs = Next( pszLhs );
|
|
||||||
pszRhs = pmszRhs->Next( pszRhs );
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SplitCommaDelimitedString(
|
|
||||||
PCWSTR pszList,
|
|
||||||
BOOL fTrimEntries,
|
|
||||||
BOOL fRemoveEmptyEntries,
|
|
||||||
MULTISZ * pmszList
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Split comma delimited string into a multisz. Additional leading empty
|
|
||||||
entries after the first are discarded.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pszList - List to split up
|
|
||||||
fTrimEntries - Whether each entry should be trimmed before added to multisz
|
|
||||||
fRemoveEmptyEntries - Whether empty entires should be discarded
|
|
||||||
pmszList - Filled with MULTISZ list
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if ( pszList == NULL ||
|
|
||||||
pmszList == NULL )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmszList->Reset();
|
|
||||||
|
|
||||||
/*
|
|
||||||
pszCurrent: start of the current entry which may be the comma that
|
|
||||||
precedes the next entry if the entry is empty
|
|
||||||
|
|
||||||
pszNext: the comma that precedes the next entry. If
|
|
||||||
pszCurrent == pszNext, then the entry is empty
|
|
||||||
|
|
||||||
pszEnd: just past the end of the current entry
|
|
||||||
*/
|
|
||||||
|
|
||||||
for ( PCWSTR pszCurrent = pszList,
|
|
||||||
pszNext = wcschr( pszCurrent, L',' )
|
|
||||||
;
|
|
||||||
;
|
|
||||||
pszCurrent = pszNext + 1,
|
|
||||||
pszNext = wcschr( pszCurrent, L',' ) )
|
|
||||||
{
|
|
||||||
PCWSTR pszEnd = NULL;
|
|
||||||
|
|
||||||
if ( pszNext != NULL )
|
|
||||||
{
|
|
||||||
pszEnd = pszNext;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pszEnd = pszCurrent + wcslen( pszCurrent );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( fTrimEntries )
|
|
||||||
{
|
|
||||||
while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) )
|
|
||||||
{
|
|
||||||
pszCurrent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) )
|
|
||||||
{
|
|
||||||
pszEnd--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pszCurrent != pszEnd || !fRemoveEmptyEntries )
|
|
||||||
{
|
|
||||||
if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) )
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pszNext == NULL )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(default:4267)
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _MULTISZ_H_
|
|
||||||
#define _MULTISZ_H_
|
|
||||||
|
|
||||||
#include "stringu.h"
|
|
||||||
#include "ntassert.h"
|
|
||||||
|
|
||||||
/*++
|
|
||||||
class MULTISZ:
|
|
||||||
|
|
||||||
Intention:
|
|
||||||
A light-weight multi-string class supporting encapsulated string class.
|
|
||||||
|
|
||||||
This object is derived from BUFFER class.
|
|
||||||
It maintains following state:
|
|
||||||
|
|
||||||
m_fValid - whether this object is valid -
|
|
||||||
used only by MULTISZ() init functions
|
|
||||||
* NYI: I need to kill this someday *
|
|
||||||
m_cchLen - string length cached when we update the string.
|
|
||||||
m_cStrings - number of strings.
|
|
||||||
|
|
||||||
Member Functions:
|
|
||||||
There are two categories of functions:
|
|
||||||
1) Safe Functions - which do integrity checking of state
|
|
||||||
2) UnSafe Functions - which do not do integrity checking, but
|
|
||||||
enable writing to the data stream freely.
|
|
||||||
(someday this will be enabled as Safe versions without
|
|
||||||
problem for users)
|
|
||||||
|
|
||||||
--*/
|
|
||||||
class MULTISZ : public BUFFER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MULTISZ()
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ Reset(); }
|
|
||||||
|
|
||||||
// creates a stack version of the MULTISZ object - uses passed in stack buffer
|
|
||||||
// MULTISZ does not free this pbInit on its own.
|
|
||||||
MULTISZ( __in_bcount(cbInit) WCHAR * pbInit, DWORD cbInit)
|
|
||||||
: BUFFER( (BYTE *) pbInit, cbInit),
|
|
||||||
m_cchLen (0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
MULTISZ( const WCHAR * pchInit )
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ AuxInit(pchInit); }
|
|
||||||
|
|
||||||
MULTISZ( const MULTISZ & str )
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ AuxInit( str.QueryStr()); }
|
|
||||||
|
|
||||||
// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
|
|
||||||
//
|
|
||||||
// Checks and returns TRUE if this string has no valid data else FALSE
|
|
||||||
//
|
|
||||||
BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); }
|
|
||||||
|
|
||||||
BOOL Append( const WCHAR * pchInit ) {
|
|
||||||
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
||||||
(DWORD) (::wcslen(pchInit)) * sizeof(WCHAR)
|
|
||||||
)) :
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL Append( const WCHAR * pchInit, DWORD cchLen ) {
|
|
||||||
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
||||||
cchLen * sizeof(WCHAR))) :
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Append( STRU & str )
|
|
||||||
{ return AuxAppend( str.QueryStr(),
|
|
||||||
(str.QueryCCH()) * sizeof(WCHAR)); }
|
|
||||||
|
|
||||||
// Resets the internal string to be NULL string. Buffer remains cached.
|
|
||||||
VOID Reset( VOID)
|
|
||||||
{ DBG_ASSERT( QueryPtr() != NULL);
|
|
||||||
QueryStr()[0] = L'\0';
|
|
||||||
QueryStr()[1] = L'\0';
|
|
||||||
m_cchLen = 2;
|
|
||||||
m_cStrings = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Copy( const WCHAR * pchInit, IN DWORD cbLen ) {
|
|
||||||
if ( QueryPtr() ) { Reset(); }
|
|
||||||
return ( (pchInit != NULL) ?
|
|
||||||
AuxAppend( pchInit, cbLen, FALSE ):
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Copy( const MULTISZ & str )
|
|
||||||
{ return ( Copy(str.QueryStr(), str.QueryCB())); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns the number of bytes in the string including the terminating
|
|
||||||
// NULLs
|
|
||||||
//
|
|
||||||
UINT QueryCB( VOID ) const
|
|
||||||
{ return ( m_cchLen * sizeof(WCHAR)); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns # of characters in the string including the terminating NULLs
|
|
||||||
//
|
|
||||||
UINT QueryCCH( VOID ) const { return (m_cchLen); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns # of strings in the multisz.
|
|
||||||
//
|
|
||||||
|
|
||||||
DWORD QueryStringCount( VOID ) const { return m_cStrings; }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Makes a copy of the stored string in given buffer
|
|
||||||
//
|
|
||||||
BOOL CopyToBuffer( __out_ecount_opt(*lpcch) WCHAR * lpszBuffer, LPDWORD lpcch) const;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the string buffer
|
|
||||||
//
|
|
||||||
WCHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
|
|
||||||
WCHAR * QueryStr( VOID ) const { return ((WCHAR *) QueryPtr()); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Makes a clone of the current string in the string pointer passed in.
|
|
||||||
//
|
|
||||||
BOOL
|
|
||||||
Clone( OUT MULTISZ * pstrClone) const
|
|
||||||
{
|
|
||||||
return ((pstrClone == NULL) ?
|
|
||||||
(SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
|
|
||||||
(pstrClone->Copy( *this))
|
|
||||||
);
|
|
||||||
} // MULTISZ::Clone()
|
|
||||||
|
|
||||||
//
|
|
||||||
// Recalculates the length of *this because we've modified the buffers
|
|
||||||
// directly
|
|
||||||
//
|
|
||||||
|
|
||||||
VOID RecalcLen( VOID )
|
|
||||||
{ m_cchLen = MULTISZ::CalcLength( QueryStr(), &m_cStrings ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate total character length of a MULTI_SZ, including the
|
|
||||||
// terminating NULLs.
|
|
||||||
//
|
|
||||||
|
|
||||||
static DWORD CalcLength( const WCHAR * str,
|
|
||||||
LPDWORD pcStrings = NULL );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine if the MULTISZ contains a specific string.
|
|
||||||
//
|
|
||||||
|
|
||||||
BOOL FindString( const WCHAR * str );
|
|
||||||
|
|
||||||
BOOL FindString( STRU & str )
|
|
||||||
{ return FindString( str.QueryStr() ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine if the MULTISZ contains a specific string - case-insensitive
|
|
||||||
//
|
|
||||||
|
|
||||||
BOOL FindStringNoCase( const WCHAR * str );
|
|
||||||
|
|
||||||
BOOL FindStringNoCase( STRU & str )
|
|
||||||
{ return FindStringNoCase( str.QueryStr() ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Used for scanning a multisz.
|
|
||||||
//
|
|
||||||
|
|
||||||
const WCHAR * First( VOID ) const
|
|
||||||
{ return *QueryStr() == L'\0' ? NULL : QueryStr(); }
|
|
||||||
|
|
||||||
const WCHAR * Next( const WCHAR * Current ) const
|
|
||||||
{ Current += ::wcslen( Current ) + 1;
|
|
||||||
return *Current == L'\0' ? NULL : Current; }
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
Equals(
|
|
||||||
MULTISZ* pmszRhs
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
DWORD m_cchLen;
|
|
||||||
DWORD m_cStrings;
|
|
||||||
VOID AuxInit( const WCHAR * pInit );
|
|
||||||
BOOL AuxAppend( const WCHAR * pInit,
|
|
||||||
UINT cbStr, BOOL fAddSlop = TRUE );
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Quick macro for declaring a MULTISZ that will use stack memory of <size>
|
|
||||||
// bytes. If the buffer overflows then a heap buffer will be allocated
|
|
||||||
//
|
|
||||||
|
|
||||||
#define STACK_MULTISZ( name, size ) WCHAR __ach##name[size]; \
|
|
||||||
MULTISZ name( __ach##name, sizeof( __ach##name ))
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SplitCommaDelimitedString(
|
|
||||||
PCWSTR pszList,
|
|
||||||
BOOL fTrimEntries,
|
|
||||||
BOOL fRemoveEmptyEntries,
|
|
||||||
MULTISZ * pmszList
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif // !_MULTISZ_HXX_
|
|
||||||
|
|
||||||
|
|
@ -1,408 +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 warning (disable : 4267)
|
|
||||||
#include "precomp.h"
|
|
||||||
#include "multisza.h"
|
|
||||||
#include <tchar.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// Private Definitions
|
|
||||||
//
|
|
||||||
|
|
||||||
#define MAXULONG 4294967295
|
|
||||||
#define ISWHITE( ch ) ((ch) == L' ' || (ch) == L'\t' || (ch) == L'\r')
|
|
||||||
|
|
||||||
//
|
|
||||||
// When appending data, this is the extra amount we request to avoid
|
|
||||||
// reallocations
|
|
||||||
//
|
|
||||||
#define STR_SLOP 128
|
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
MULTISZA::CalcLength( const CHAR * str,
|
|
||||||
LPDWORD pcStrings )
|
|
||||||
{
|
|
||||||
DWORD count = 0;
|
|
||||||
DWORD total = 1;
|
|
||||||
DWORD len;
|
|
||||||
|
|
||||||
while( *str ) {
|
|
||||||
len = ::strlen( str ) + 1;
|
|
||||||
total += len;
|
|
||||||
str += len;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pcStrings != NULL ) {
|
|
||||||
*pcStrings = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
|
|
||||||
} // MULTISZA::CalcLength
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZA::FindString( const CHAR * str )
|
|
||||||
{
|
|
||||||
|
|
||||||
CHAR * multisz;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sanity check.
|
|
||||||
//
|
|
||||||
|
|
||||||
DBG_ASSERT( QueryStr() != NULL );
|
|
||||||
DBG_ASSERT( str != NULL );
|
|
||||||
DBG_ASSERT( *str != '\0' );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scan it.
|
|
||||||
//
|
|
||||||
|
|
||||||
multisz = QueryStr();
|
|
||||||
|
|
||||||
while( *multisz != '\0' ) {
|
|
||||||
|
|
||||||
if( !::strcmp( multisz, str ) ) {
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
multisz += ::strlen( multisz ) + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
} // MULTISZA::FindString
|
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZA::FindStringNoCase( const CHAR * str )
|
|
||||||
{
|
|
||||||
|
|
||||||
CHAR * multisz;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sanity check.
|
|
||||||
//
|
|
||||||
|
|
||||||
DBG_ASSERT( QueryStr() != NULL );
|
|
||||||
DBG_ASSERT( str != NULL );
|
|
||||||
DBG_ASSERT( *str != '\0' );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scan it.
|
|
||||||
//
|
|
||||||
|
|
||||||
multisz = QueryStr();
|
|
||||||
|
|
||||||
while( *multisz != '\0' ) {
|
|
||||||
|
|
||||||
if( !_stricmp( multisz, str ) ) {
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
multisz += strlen( multisz ) + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
} // MULTISZA::FindStringNoCase
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MULTISZA::AuxInit( const CHAR * pInit )
|
|
||||||
{
|
|
||||||
BOOL fRet;
|
|
||||||
|
|
||||||
if ( pInit )
|
|
||||||
{
|
|
||||||
DWORD cStrings;
|
|
||||||
int cbCopy = CalcLength( pInit, &cStrings ) * sizeof(CHAR);
|
|
||||||
fRet = Resize( cbCopy );
|
|
||||||
|
|
||||||
if ( fRet ) {
|
|
||||||
CopyMemory( QueryPtr(), pInit, cbCopy );
|
|
||||||
m_cchLen = (cbCopy)/sizeof(CHAR);
|
|
||||||
m_cStrings = cStrings;
|
|
||||||
} else {
|
|
||||||
// BUFFER::SetValid( FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // MULTISZA::AuxInit()
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
|
|
||||||
NAME: MULTISZA::AuxAppend
|
|
||||||
|
|
||||||
SYNOPSIS: Appends the string onto the MULTISZA.
|
|
||||||
|
|
||||||
ENTRY: Object to append
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
BOOL MULTISZA::AuxAppend( const CHAR * pStr, UINT cbStr, BOOL fAddSlop )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( pStr != NULL );
|
|
||||||
|
|
||||||
UINT cbThis = QueryCB();
|
|
||||||
|
|
||||||
if( cbThis == 2 ) {
|
|
||||||
|
|
||||||
//
|
|
||||||
// It's empty, so start at the beginning.
|
|
||||||
//
|
|
||||||
|
|
||||||
cbThis = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//
|
|
||||||
// It's not empty, so back up over the final terminating NULL.
|
|
||||||
//
|
|
||||||
|
|
||||||
cbThis -= sizeof(CHAR);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Only resize when we have to. When we do resize, we tack on
|
|
||||||
// some extra space to avoid extra reallocations.
|
|
||||||
//
|
|
||||||
// Note: QuerySize returns the requested size of the string buffer,
|
|
||||||
// *not* the strlen of the buffer
|
|
||||||
//
|
|
||||||
|
|
||||||
//AcIncrement( CacMultiszAppend);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check for the arithmetic overflow
|
|
||||||
//
|
|
||||||
// ( 2 * sizeof( CHAR ) ) is for the double terminator
|
|
||||||
//
|
|
||||||
ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(CHAR);
|
|
||||||
if ( cb64Required > MAXULONG )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_ARITHMETIC_OVERFLOW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ( QuerySize() < (DWORD) cb64Required )
|
|
||||||
{
|
|
||||||
ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 );
|
|
||||||
//
|
|
||||||
// Check for the arithmetic overflow
|
|
||||||
//
|
|
||||||
if ( cb64AllocSize > MAXULONG )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_ARITHMETIC_OVERFLOW );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if ( !Resize( (DWORD) cb64AllocSize ) )
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the exact string and tack on the double terminator
|
|
||||||
memcpy( (BYTE *) QueryPtr() + cbThis,
|
|
||||||
pStr,
|
|
||||||
cbStr);
|
|
||||||
*(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0';
|
|
||||||
*(CHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(CHAR) ) = L'\0';
|
|
||||||
|
|
||||||
m_cchLen = CalcLength( (const CHAR *)QueryPtr(), &m_cStrings );
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
} // MULTISZA::AuxAppend()
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZA::CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const
|
|
||||||
/*++
|
|
||||||
Description:
|
|
||||||
Copies the string into the CHAR buffer passed in if the buffer
|
|
||||||
is sufficient to hold the translated string.
|
|
||||||
If the buffer is small, the function returns small and sets *lpcch
|
|
||||||
to contain the required number of characters.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
lpszBuffer pointer to CHAR buffer which on return contains
|
|
||||||
the string on success.
|
|
||||||
lpcch pointer to DWORD containing the length of the buffer.
|
|
||||||
If *lpcch == 0 then the function returns TRUE with
|
|
||||||
the count of characters required stored in lpcch.
|
|
||||||
Also in this case lpszBuffer is not affected.
|
|
||||||
Returns:
|
|
||||||
TRUE on success.
|
|
||||||
FALSE on failure. Use GetLastError() for further details.
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
BOOL fReturn = TRUE;
|
|
||||||
|
|
||||||
if ( lpcch == NULL) {
|
|
||||||
SetLastError( ERROR_INVALID_PARAMETER);
|
|
||||||
return ( FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
register DWORD cch = QueryCCH();
|
|
||||||
|
|
||||||
if ( *lpcch >= cch) {
|
|
||||||
|
|
||||||
DBG_ASSERT( lpszBuffer);
|
|
||||||
memcpy( lpszBuffer, QueryStr(), cch * sizeof(CHAR));
|
|
||||||
} else {
|
|
||||||
DBG_ASSERT( *lpcch < cch);
|
|
||||||
SetLastError( ERROR_INSUFFICIENT_BUFFER);
|
|
||||||
fReturn = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*lpcch = cch;
|
|
||||||
|
|
||||||
return ( fReturn);
|
|
||||||
} // MULTISZA::CopyToBuffer()
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
MULTISZA::Equals(
|
|
||||||
MULTISZA* pmszRhs
|
|
||||||
)
|
|
||||||
//
|
|
||||||
// Compares this to pmszRhs, returns TRUE if equal
|
|
||||||
//
|
|
||||||
{
|
|
||||||
DBG_ASSERT( NULL != pmszRhs );
|
|
||||||
|
|
||||||
PCSTR pszLhs = First( );
|
|
||||||
PCSTR pszRhs = pmszRhs->First( );
|
|
||||||
|
|
||||||
if( m_cStrings != pmszRhs->m_cStrings )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( NULL != pszLhs )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( NULL != pszRhs );
|
|
||||||
|
|
||||||
if( 0 != strcmp( pszLhs, pszRhs ) )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pszLhs = Next( pszLhs );
|
|
||||||
pszRhs = pmszRhs->Next( pszRhs );
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SplitCommaDelimitedString(
|
|
||||||
PCSTR pszList,
|
|
||||||
BOOL fTrimEntries,
|
|
||||||
BOOL fRemoveEmptyEntries,
|
|
||||||
MULTISZA * pmszList
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Split comma delimited string into a MULTISZA. Additional leading empty
|
|
||||||
entries after the first are discarded.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pszList - List to split up
|
|
||||||
fTrimEntries - Whether each entry should be trimmed before added to MULTISZA
|
|
||||||
fRemoveEmptyEntries - Whether empty entires should be discarded
|
|
||||||
pmszList - Filled with MULTISZA list
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if ( pszList == NULL ||
|
|
||||||
pmszList == NULL )
|
|
||||||
{
|
|
||||||
DBG_ASSERT( FALSE );
|
|
||||||
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmszList->Reset();
|
|
||||||
|
|
||||||
/*
|
|
||||||
pszCurrent: start of the current entry which may be the comma that
|
|
||||||
precedes the next entry if the entry is empty
|
|
||||||
|
|
||||||
pszNext: the comma that precedes the next entry. If
|
|
||||||
pszCurrent == pszNext, then the entry is empty
|
|
||||||
|
|
||||||
pszEnd: just past the end of the current entry
|
|
||||||
*/
|
|
||||||
|
|
||||||
for ( PCSTR pszCurrent = pszList,
|
|
||||||
pszNext = strchr( pszCurrent, L',' )
|
|
||||||
;
|
|
||||||
;
|
|
||||||
pszCurrent = pszNext + 1,
|
|
||||||
pszNext = strchr( pszCurrent, L',' ) )
|
|
||||||
{
|
|
||||||
PCSTR pszEnd = NULL;
|
|
||||||
|
|
||||||
if ( pszNext != NULL )
|
|
||||||
{
|
|
||||||
pszEnd = pszNext;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pszEnd = pszCurrent + strlen( pszCurrent );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( fTrimEntries )
|
|
||||||
{
|
|
||||||
while ( pszCurrent < pszEnd && ISWHITE( pszCurrent[ 0 ] ) )
|
|
||||||
{
|
|
||||||
pszCurrent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( pszEnd > pszCurrent && ISWHITE( pszEnd[ -1 ] ) )
|
|
||||||
{
|
|
||||||
pszEnd--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pszCurrent != pszEnd || !fRemoveEmptyEntries )
|
|
||||||
{
|
|
||||||
if ( !pmszList->Append( pszCurrent, (DWORD) ( pszEnd - pszCurrent ) ) )
|
|
||||||
{
|
|
||||||
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pszNext == NULL )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
#pragma warning(default:4267)
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _MULTISZA_H_
|
|
||||||
#define _MULTISZA_H_
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include "stringa.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*++
|
|
||||||
class MULTISZ:
|
|
||||||
|
|
||||||
Intention:
|
|
||||||
A light-weight multi-string class supporting encapsulated string class.
|
|
||||||
|
|
||||||
This object is derived from BUFFER class.
|
|
||||||
It maintains following state:
|
|
||||||
|
|
||||||
m_fValid - whether this object is valid -
|
|
||||||
used only by MULTISZ() init functions
|
|
||||||
* NYI: I need to kill this someday *
|
|
||||||
m_cchLen - string length cached when we update the string.
|
|
||||||
m_cStrings - number of strings.
|
|
||||||
|
|
||||||
Member Functions:
|
|
||||||
There are two categories of functions:
|
|
||||||
1) Safe Functions - which do integrity checking of state
|
|
||||||
2) UnSafe Functions - which do not do integrity checking, but
|
|
||||||
enable writing to the data stream freely.
|
|
||||||
(someday this will be enabled as Safe versions without
|
|
||||||
problem for users)
|
|
||||||
|
|
||||||
--*/
|
|
||||||
class MULTISZA : public BUFFER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MULTISZA()
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ Reset(); }
|
|
||||||
|
|
||||||
// creates a stack version of the MULTISZA object - uses passed in stack buffer
|
|
||||||
// MULTISZA does not free this pbInit on its own.
|
|
||||||
MULTISZA( __in_bcount(cbInit) CHAR * pbInit, DWORD cbInit)
|
|
||||||
: BUFFER( (BYTE *) pbInit, cbInit),
|
|
||||||
m_cchLen (0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
MULTISZA( const CHAR * pchInit )
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ AuxInit(pchInit); }
|
|
||||||
|
|
||||||
MULTISZA( const MULTISZA & str )
|
|
||||||
: BUFFER (),
|
|
||||||
m_cchLen ( 0),
|
|
||||||
m_cStrings(0)
|
|
||||||
{ AuxInit( str.QueryStr()); }
|
|
||||||
|
|
||||||
// BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
|
|
||||||
//
|
|
||||||
// Checks and returns TRUE if this string has no valid data else FALSE
|
|
||||||
//
|
|
||||||
BOOL IsEmpty( VOID) const { return ( *QueryStr() == L'\0'); }
|
|
||||||
|
|
||||||
BOOL Append( const CHAR * pchInit ) {
|
|
||||||
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
||||||
(DWORD) (::strlen(pchInit)) * sizeof(CHAR)
|
|
||||||
)) :
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL Append( const CHAR * pchInit, DWORD cchLen ) {
|
|
||||||
return ((pchInit != NULL) ? (AuxAppend( pchInit,
|
|
||||||
cchLen * sizeof(CHAR))) :
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Append( STRA & str )
|
|
||||||
{ return AuxAppend( str.QueryStr(),
|
|
||||||
(str.QueryCCH()) * sizeof(CHAR)); }
|
|
||||||
|
|
||||||
// Resets the internal string to be NULL string. Buffer remains cached.
|
|
||||||
VOID Reset( VOID)
|
|
||||||
{ DBG_ASSERT( QueryPtr() != NULL);
|
|
||||||
QueryStr()[0] = L'\0';
|
|
||||||
QueryStr()[1] = L'\0';
|
|
||||||
m_cchLen = 2;
|
|
||||||
m_cStrings = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Copy( const CHAR * pchInit, IN DWORD cbLen ) {
|
|
||||||
if ( QueryPtr() ) { Reset(); }
|
|
||||||
return ( (pchInit != NULL) ?
|
|
||||||
AuxAppend( pchInit, cbLen, FALSE ):
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Copy( const MULTISZA & str )
|
|
||||||
{ return ( Copy(str.QueryStr(), str.QueryCB())); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns the number of bytes in the string including the terminating
|
|
||||||
// NULLs
|
|
||||||
//
|
|
||||||
UINT QueryCB( VOID ) const
|
|
||||||
{ return ( m_cchLen * sizeof(CHAR)); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns # of characters in the string including the terminating NULLs
|
|
||||||
//
|
|
||||||
UINT QueryCCH( VOID ) const { return (m_cchLen); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns # of strings in the MULTISZA.
|
|
||||||
//
|
|
||||||
|
|
||||||
DWORD QueryStringCount( VOID ) const { return m_cStrings; }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Makes a copy of the stored string in given buffer
|
|
||||||
//
|
|
||||||
BOOL CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Return the string buffer
|
|
||||||
//
|
|
||||||
CHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
|
|
||||||
CHAR * QueryStr( VOID ) const { return ((CHAR *) QueryPtr()); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Makes a clone of the current string in the string pointer passed in.
|
|
||||||
//
|
|
||||||
BOOL
|
|
||||||
Clone( OUT MULTISZA * pstrClone) const
|
|
||||||
{
|
|
||||||
return ((pstrClone == NULL) ?
|
|
||||||
(SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
|
|
||||||
(pstrClone->Copy( *this))
|
|
||||||
);
|
|
||||||
} // MULTISZA::Clone()
|
|
||||||
|
|
||||||
//
|
|
||||||
// Recalculates the length of *this because we've modified the buffers
|
|
||||||
// directly
|
|
||||||
//
|
|
||||||
|
|
||||||
VOID RecalcLen( VOID )
|
|
||||||
{ m_cchLen = MULTISZA::CalcLength( QueryStr(), &m_cStrings ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate total character length of a MULTI_SZ, including the
|
|
||||||
// terminating NULLs.
|
|
||||||
//
|
|
||||||
|
|
||||||
static DWORD CalcLength( const CHAR * str,
|
|
||||||
LPDWORD pcStrings = NULL );
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine if the MULTISZA contains a specific string.
|
|
||||||
//
|
|
||||||
|
|
||||||
BOOL FindString( const CHAR * str );
|
|
||||||
|
|
||||||
BOOL FindString( STRA & str )
|
|
||||||
{ return FindString( str.QueryStr() ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine if the MULTISZA contains a specific string - case-insensitive
|
|
||||||
//
|
|
||||||
|
|
||||||
BOOL FindStringNoCase( const CHAR * str );
|
|
||||||
|
|
||||||
BOOL FindStringNoCase( STRA & str )
|
|
||||||
{ return FindStringNoCase( str.QueryStr() ); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Used for scanning a MULTISZA.
|
|
||||||
//
|
|
||||||
|
|
||||||
const CHAR * First( VOID ) const
|
|
||||||
{ return *QueryStr() == L'\0' ? NULL : QueryStr(); }
|
|
||||||
|
|
||||||
const CHAR * Next( const CHAR * Current ) const
|
|
||||||
{ Current += ::strlen( Current ) + 1;
|
|
||||||
return *Current == L'\0' ? NULL : Current; }
|
|
||||||
|
|
||||||
BOOL
|
|
||||||
Equals(
|
|
||||||
MULTISZA* pmszRhs
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
DWORD m_cchLen;
|
|
||||||
DWORD m_cStrings;
|
|
||||||
VOID AuxInit( const CHAR * pInit );
|
|
||||||
BOOL AuxAppend( const CHAR * pInit,
|
|
||||||
UINT cbStr, BOOL fAddSlop = TRUE );
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Quick macro for declaring a MULTISZA that will use stack memory of <size>
|
|
||||||
// bytes. If the buffer overflows then a heap buffer will be allocated
|
|
||||||
//
|
|
||||||
|
|
||||||
#define STACK_MULTISZA( name, size ) CHAR __ach##name[size]; \
|
|
||||||
MULTISZA name( __ach##name, sizeof( __ach##name ))
|
|
||||||
|
|
||||||
HRESULT
|
|
||||||
SplitCommaDelimitedString(
|
|
||||||
PCSTR pszList,
|
|
||||||
BOOL fTrimEntries,
|
|
||||||
BOOL fRemoveEmptyEntries,
|
|
||||||
MULTISZA * pmszList
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif // !_MULTISZA_HXX_
|
|
||||||
|
|
||||||
|
|
@ -1,32 +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
|
|
||||||
|
|
||||||
#ifdef _ASSERTE
|
|
||||||
#undef _ASSERTE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
#undef ASSERT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined( DBG ) && DBG
|
|
||||||
#define SX_ASSERT( _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L#_x ), DbgRaiseAssertionFailure(), FALSE ) ) )
|
|
||||||
#define SX_ASSERTMSG( _m, _x ) ( (VOID)( ( ( _x ) ) ? TRUE : ( __annotation( L"Debug", L"AssertFail", L##_m ), DbgRaiseAssertionFailure(), FALSE ) ) )
|
|
||||||
#define SX_VERIFY( _x ) SX_ASSERT( _x )
|
|
||||||
#define _ASSERTE( _x ) SX_ASSERT( _x )
|
|
||||||
#define ASSERT( _x ) SX_ASSERT( _x )
|
|
||||||
#define assert( _x ) SX_ASSERT( _x )
|
|
||||||
#define DBG_ASSERT( _x ) SX_ASSERT( _x )
|
|
||||||
#define DBG_REQUIRE( _x ) SX_ASSERT( _x )
|
|
||||||
#else
|
|
||||||
#define SX_ASSERT( _x ) ( (VOID)0 )
|
|
||||||
#define SX_ASSERTMSG( _m, _x ) ( (VOID)0 )
|
|
||||||
#define SX_VERIFY( _x ) ( (VOID)( ( _x ) ? TRUE : FALSE ) )
|
|
||||||
#define _ASSERTE( _x ) ( (VOID)0 )
|
|
||||||
#define assert( _x ) ( (VOID)0 )
|
|
||||||
#define DBG_ASSERT( _x ) ( (VOID)0 )
|
|
||||||
#define DBG_REQUIRE( _x ) ((VOID)(_x))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,305 +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
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class PER_CPU
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
template<typename FunctionInitializer>
|
|
||||||
inline
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
Create(
|
|
||||||
FunctionInitializer Initializer,
|
|
||||||
__deref_out PER_CPU<T> ** ppInstance
|
|
||||||
);
|
|
||||||
|
|
||||||
inline
|
|
||||||
T *
|
|
||||||
GetLocal(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
template<typename FunctionForEach>
|
|
||||||
inline
|
|
||||||
VOID
|
|
||||||
ForEach(
|
|
||||||
FunctionForEach Function
|
|
||||||
);
|
|
||||||
|
|
||||||
inline
|
|
||||||
VOID
|
|
||||||
Dispose(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
PER_CPU(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Don't perform any operation during constructor.
|
|
||||||
// Constructor will never be called.
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
~PER_CPU(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Don't perform any operation during destructor.
|
|
||||||
// Constructor will never be called.
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FunctionInitializer>
|
|
||||||
HRESULT
|
|
||||||
Initialize(
|
|
||||||
FunctionInitializer Initializer,
|
|
||||||
DWORD NumberOfVariables,
|
|
||||||
DWORD Alignment
|
|
||||||
);
|
|
||||||
|
|
||||||
T *
|
|
||||||
GetObject(
|
|
||||||
DWORD Index
|
|
||||||
);
|
|
||||||
|
|
||||||
static
|
|
||||||
HRESULT
|
|
||||||
GetProcessorInformation(
|
|
||||||
__out DWORD * pCacheLineSize,
|
|
||||||
__out DWORD * pNumberOfProcessors
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pointer to the begining of the inlined array.
|
|
||||||
//
|
|
||||||
PVOID m_pVariables;
|
|
||||||
SIZE_T m_Alignment;
|
|
||||||
SIZE_T m_VariablesCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
template<typename FunctionInitializer>
|
|
||||||
inline
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
PER_CPU<T>::Create(
|
|
||||||
FunctionInitializer Initializer,
|
|
||||||
__deref_out PER_CPU<T> ** ppInstance
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
DWORD CacheLineSize = 0;
|
|
||||||
DWORD ObjectCacheLineSize = 0;
|
|
||||||
DWORD NumberOfProcessors = 0;
|
|
||||||
PER_CPU<T> * pInstance = NULL;
|
|
||||||
|
|
||||||
hr = GetProcessorInformation(&CacheLineSize,
|
|
||||||
&NumberOfProcessors);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizeof(T) > CacheLineSize)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Round to the next multiple of the cache line size.
|
|
||||||
//
|
|
||||||
ObjectCacheLineSize = (sizeof(T) + CacheLineSize-1) & (CacheLineSize-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ObjectCacheLineSize = CacheLineSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate the size of the PER_CPU<T> object, including the array.
|
|
||||||
// The first cache line is for the member variables and the array
|
|
||||||
// starts in the next cache line.
|
|
||||||
//
|
|
||||||
SIZE_T Size = CacheLineSize + NumberOfProcessors * ObjectCacheLineSize;
|
|
||||||
|
|
||||||
pInstance = (PER_CPU<T>*) _aligned_malloc(Size, CacheLineSize);
|
|
||||||
if (pInstance == NULL)
|
|
||||||
{
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
ZeroMemory(pInstance, Size);
|
|
||||||
|
|
||||||
//
|
|
||||||
// The array start in the 2nd cache line.
|
|
||||||
//
|
|
||||||
pInstance->m_pVariables = reinterpret_cast<PBYTE>(pInstance) + CacheLineSize;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pass a disposer for disposing initialized items in case of failure.
|
|
||||||
//
|
|
||||||
hr = pInstance->Initialize(Initializer,
|
|
||||||
NumberOfProcessors,
|
|
||||||
ObjectCacheLineSize);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
goto Finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppInstance = pInstance;
|
|
||||||
pInstance = NULL;
|
|
||||||
|
|
||||||
Finished:
|
|
||||||
|
|
||||||
if (pInstance != NULL)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Free the instance without disposing it.
|
|
||||||
//
|
|
||||||
pInstance->Dispose();
|
|
||||||
pInstance = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline
|
|
||||||
T *
|
|
||||||
PER_CPU<T>::GetLocal(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Use GetCurrentProcessorNumber (up to 64 logical processors) instead of
|
|
||||||
// GetCurrentProcessorNumberEx (more than 64 logical processors) because
|
|
||||||
// the number of processors are not densely packed per group.
|
|
||||||
// The idea of distributing variables per CPU is to have
|
|
||||||
// a scalability multiplier (could be NUMA node instead).
|
|
||||||
//
|
|
||||||
// Make sure the index don't go beyond the array size, if that happens,
|
|
||||||
// there won't be even distribution, but still better
|
|
||||||
// than one single variable.
|
|
||||||
//
|
|
||||||
return GetObject(GetCurrentProcessorNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline
|
|
||||||
T *
|
|
||||||
PER_CPU<T>::GetObject(
|
|
||||||
DWORD Index
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<T*>(static_cast<PBYTE>(m_pVariables) + Index * m_Alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
template<typename FunctionForEach>
|
|
||||||
inline
|
|
||||||
VOID
|
|
||||||
PER_CPU<T>::ForEach(
|
|
||||||
FunctionForEach Function
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for(DWORD Index = 0; Index < m_VariablesCount; ++Index)
|
|
||||||
{
|
|
||||||
T * pObject = GetObject(Index);
|
|
||||||
Function(pObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
VOID
|
|
||||||
PER_CPU<T>::Dispose(
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_aligned_free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
template<typename FunctionInitializer>
|
|
||||||
inline
|
|
||||||
HRESULT
|
|
||||||
PER_CPU<T>::Initialize(
|
|
||||||
FunctionInitializer Initializer,
|
|
||||||
DWORD NumberOfVariables,
|
|
||||||
DWORD Alignment
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Initialize each object using the initializer function.
|
|
||||||
If initialization for any object fails, it dispose the
|
|
||||||
objects that were successfully initialized.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Initializer - Function for initialize one object.
|
|
||||||
Signature: HRESULT Func(T*)
|
|
||||||
Dispose - Function for disposing initialized objects in case of failure.
|
|
||||||
Signature: void Func(T*)
|
|
||||||
NumberOfVariables - The length of the array of variables.
|
|
||||||
Alignment - Alignment to use for avoiding false sharing.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
|
|
||||||
HRESULT - E_OUTOFMEMORY
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
DWORD Index = 0;
|
|
||||||
|
|
||||||
m_VariablesCount = NumberOfVariables;
|
|
||||||
m_Alignment = Alignment;
|
|
||||||
|
|
||||||
for (; Index < m_VariablesCount; ++Index)
|
|
||||||
{
|
|
||||||
T * pObject = GetObject(Index);
|
|
||||||
Initializer(pObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
// static
|
|
||||||
HRESULT
|
|
||||||
PER_CPU<T>::GetProcessorInformation(
|
|
||||||
__out DWORD * pCacheLineSize,
|
|
||||||
__out DWORD * pNumberOfProcessors
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Gets the CPU cache-line size for the current system.
|
|
||||||
This information is used for avoiding CPU false sharing.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
pCacheLineSize - The processor cache-line size.
|
|
||||||
pNumberOfProcessors - Maximum number of processors per group.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
|
|
||||||
HRESULT - E_OUTOFMEMORY
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
SYSTEM_INFO SystemInfo = { };
|
|
||||||
|
|
||||||
GetSystemInfo(&SystemInfo);
|
|
||||||
*pNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
|
|
||||||
*pCacheLineSize = SYSTEM_CACHE_ALIGNMENT_SIZE;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +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 <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>
|
|
||||||
|
|
||||||
#include "macros.h"
|
|
||||||
#include "stringu.h"
|
|
||||||
#include "stringa.h"
|
|
||||||
#include "dbgutil.h"
|
|
||||||
#include "ntassert.h"
|
|
||||||
#include "ahutil.h"
|
|
||||||
#include "acache.h"
|
|
||||||
//#include "base64.hxx"
|
|
||||||
|
|
||||||
|
|
@ -1,85 +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 <math.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pre-calculated prime numbers (up to 10,049,369).
|
|
||||||
//
|
|
||||||
extern __declspec(selectany) const DWORD g_Primes [] = {
|
|
||||||
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631,
|
|
||||||
761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103,
|
|
||||||
12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631,
|
|
||||||
130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403,
|
|
||||||
968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559,
|
|
||||||
5999471, 7199369, 7849369, 8649369, 9249369, 10049369
|
|
||||||
};
|
|
||||||
|
|
||||||
class PRIME
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
DWORD
|
|
||||||
GetPrime(
|
|
||||||
DWORD dwMinimum
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Try to use the precalculated numbers.
|
|
||||||
//
|
|
||||||
for ( DWORD Index = 0; Index < _countof( g_Primes ); Index++ )
|
|
||||||
{
|
|
||||||
DWORD dwCandidate = g_Primes[Index];
|
|
||||||
if ( dwCandidate >= dwMinimum )
|
|
||||||
{
|
|
||||||
return dwCandidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do calculation.
|
|
||||||
//
|
|
||||||
for ( DWORD dwCandidate = dwMinimum | 1;
|
|
||||||
dwCandidate < MAXDWORD;
|
|
||||||
dwCandidate += 2 )
|
|
||||||
{
|
|
||||||
if ( IsPrime( dwCandidate ) )
|
|
||||||
{
|
|
||||||
return dwCandidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dwMinimum;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static
|
|
||||||
BOOL
|
|
||||||
IsPrime(
|
|
||||||
DWORD dwCandidate
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ((dwCandidate & 1) == 0)
|
|
||||||
{
|
|
||||||
return ( dwCandidate == 2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD dwMax = static_cast<DWORD>(sqrt(static_cast<double>(dwCandidate)));
|
|
||||||
|
|
||||||
for ( DWORD Index = 3; Index <= dwMax; Index += 2 )
|
|
||||||
{
|
|
||||||
if ( (dwCandidate % Index) == 0 )
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRIME() {}
|
|
||||||
~PRIME() {}
|
|
||||||
};
|
|
||||||
|
|
@ -1,736 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
# ifndef _PUDEBUG_H_
|
|
||||||
# define _PUDEBUG_H_
|
|
||||||
|
|
||||||
#ifndef _NO_TRACING_
|
|
||||||
# define _NO_TRACING_
|
|
||||||
#endif // _NO_TRACING_
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
* Include Headers
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
# ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
# endif // __cplusplus
|
|
||||||
|
|
||||||
# include <windows.h>
|
|
||||||
|
|
||||||
# ifndef dllexp
|
|
||||||
# define dllexp __declspec( dllexport)
|
|
||||||
# endif // dllexp
|
|
||||||
|
|
||||||
#include <specstrings.h>
|
|
||||||
|
|
||||||
#ifndef IN_OUT
|
|
||||||
#define IN_OUT __inout
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* Macros
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
enum PRINT_REASONS {
|
|
||||||
PrintNone = 0x0, // Nothing to be printed
|
|
||||||
PrintError = 0x1, // An error message
|
|
||||||
PrintWarning = 0x2, // A warning message
|
|
||||||
PrintLog = 0x3, // Just logging. Indicates a trace of where ...
|
|
||||||
PrintMsg = 0x4, // Echo input message
|
|
||||||
PrintCritical = 0x5, // Print and Exit
|
|
||||||
PrintAssertion= 0x6 // Printing for an assertion failure
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum DEBUG_OUTPUT_FLAGS {
|
|
||||||
DbgOutputNone = 0x0, // None
|
|
||||||
DbgOutputKdb = 0x1, // Output to Kernel Debugger
|
|
||||||
DbgOutputLogFile = 0x2, // Output to LogFile
|
|
||||||
DbgOutputTruncate = 0x4, // Truncate Log File if necessary
|
|
||||||
DbgOutputStderr = 0x8, // Send output to std error
|
|
||||||
DbgOutputBackup = 0x10, // Make backup of debug file ?
|
|
||||||
DbgOutputMemory = 0x20, // Dump to memory buffer
|
|
||||||
DbgOutputAll = 0xFFFFFFFF // All the bits set.
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
# define MAX_LABEL_LENGTH ( 100)
|
|
||||||
|
|
||||||
|
|
||||||
// The following flags are used internally to track what level of tracing we
|
|
||||||
// are currently using. Bitmapped for extensibility.
|
|
||||||
#define DEBUG_FLAG_ODS 0x00000001
|
|
||||||
//#define DEBUG_FLAG_INFO 0x00000002
|
|
||||||
//#define DEBUG_FLAG_WARN 0x00000004
|
|
||||||
//#define DEBUG_FLAG_ERROR 0x00000008
|
|
||||||
// The following are used internally to determine whether to log or not based
|
|
||||||
// on what the current state is
|
|
||||||
//#define DEBUG_FLAGS_INFO (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO)
|
|
||||||
//#define DEBUG_FLAGS_WARN (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN)
|
|
||||||
//#define DEBUG_FLAGS_ERROR (DEBUG_FLAG_ODS | DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
|
|
||||||
|
|
||||||
#define DEBUG_FLAGS_ANY (DEBUG_FLAG_INFO | DEBUG_FLAG_WARN | DEBUG_FLAG_ERROR)
|
|
||||||
|
|
||||||
//
|
|
||||||
// user of DEBUG infrastructure may choose unique variable name for DEBUG_FLAGS
|
|
||||||
// that's specially useful for cases where DEBUG infrastructure is used within
|
|
||||||
// static library (static library may prefer to maintain it's own DebugFlags independent
|
|
||||||
// on the main program it links to
|
|
||||||
//
|
|
||||||
#ifndef DEBUG_FLAGS_VAR
|
|
||||||
#define DEBUG_FLAGS_VAR g_dwDebugFlags
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern
|
|
||||||
#ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
DWORD DEBUG_FLAGS_VAR ; // Debugging Flags
|
|
||||||
|
|
||||||
# define DECLARE_DEBUG_VARIABLE()
|
|
||||||
|
|
||||||
# define SET_DEBUG_FLAGS( dwFlags) DEBUG_FLAGS_VAR = dwFlags
|
|
||||||
# define GET_DEBUG_FLAGS() ( DEBUG_FLAGS_VAR )
|
|
||||||
|
|
||||||
# define LOAD_DEBUG_FLAGS_FROM_REG(hkey, dwDefault) \
|
|
||||||
DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromReg((hkey), (dwDefault))
|
|
||||||
|
|
||||||
# define LOAD_DEBUG_FLAGS_FROM_REG_STR(pszRegKey, dwDefault) \
|
|
||||||
DEBUG_FLAGS_VAR = PuLoadDebugFlagsFromRegStr((pszRegKey), (dwDefault))
|
|
||||||
|
|
||||||
# define SAVE_DEBUG_FLAGS_IN_REG(hkey, dwDbg) \
|
|
||||||
PuSaveDebugFlagsInReg((hkey), (dwDbg))
|
|
||||||
|
|
||||||
# define DEBUG_IF( arg, s) if ( DEBUG_ ## arg & GET_DEBUG_FLAGS()) { \
|
|
||||||
s \
|
|
||||||
} else {}
|
|
||||||
|
|
||||||
# define IF_DEBUG( arg) if ( DEBUG_## arg & GET_DEBUG_FLAGS())
|
|
||||||
|
|
||||||
|
|
||||||
/*++
|
|
||||||
class DEBUG_PRINTS
|
|
||||||
|
|
||||||
This class is responsible for printing messages to log file / kernel debugger
|
|
||||||
|
|
||||||
Currently the class supports only member functions for <ANSI> char.
|
|
||||||
( not unicode-strings).
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _DEBUG_PRINTS {
|
|
||||||
|
|
||||||
CHAR m_rgchLabel[MAX_LABEL_LENGTH];
|
|
||||||
CHAR m_rgchLogFilePath[MAX_PATH];
|
|
||||||
CHAR m_rgchLogFileName[MAX_PATH];
|
|
||||||
HANDLE m_LogFileHandle;
|
|
||||||
HANDLE m_StdErrHandle;
|
|
||||||
BOOL m_fInitialized;
|
|
||||||
BOOL m_fBreakOnAssert;
|
|
||||||
DWORD m_dwOutputFlags;
|
|
||||||
VOID *m_pMemoryLog;
|
|
||||||
} DEBUG_PRINTS, FAR * LPDEBUG_PRINTS;
|
|
||||||
|
|
||||||
|
|
||||||
LPDEBUG_PRINTS
|
|
||||||
PuCreateDebugPrintsObject(
|
|
||||||
IN const char * pszPrintLabel,
|
|
||||||
IN DWORD dwOutputFlags);
|
|
||||||
|
|
||||||
//
|
|
||||||
// frees the debug prints object and closes any file if necessary.
|
|
||||||
// Returns NULL on success or returns pDebugPrints on failure.
|
|
||||||
//
|
|
||||||
LPDEBUG_PRINTS
|
|
||||||
PuDeleteDebugPrintsObject(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
PuDbgPrint(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN const char * pszFormat,
|
|
||||||
...);
|
|
||||||
// arglist
|
|
||||||
VOID
|
|
||||||
PuDbgPrintW(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN const WCHAR * pszFormat,
|
|
||||||
...); // arglist
|
|
||||||
|
|
||||||
// PuDbgPrintError is similar to PuDbgPrint() but allows
|
|
||||||
// one to print error code in friendly manner
|
|
||||||
VOID
|
|
||||||
PuDbgPrintError(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN DWORD dwError,
|
|
||||||
IN const char * pszFormat,
|
|
||||||
...); // arglist
|
|
||||||
|
|
||||||
/*++
|
|
||||||
PuDbgDump() does not do any formatting of output.
|
|
||||||
It just dumps the given message onto the debug destinations.
|
|
||||||
--*/
|
|
||||||
VOID
|
|
||||||
PuDbgDump(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN const char * pszDump
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// PuDbgAssertFailed() *must* be __cdecl to properly capture the
|
|
||||||
// thread context at the time of the failure.
|
|
||||||
//
|
|
||||||
|
|
||||||
INT
|
|
||||||
__cdecl
|
|
||||||
PuDbgAssertFailed(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN const char * pszExpression,
|
|
||||||
IN const char * pszMessage);
|
|
||||||
|
|
||||||
INT
|
|
||||||
WINAPI
|
|
||||||
PuDbgPrintAssertFailed(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName,
|
|
||||||
IN const char * pszExpression,
|
|
||||||
IN const char * pszMessage);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
PuDbgCaptureContext (
|
|
||||||
OUT PCONTEXT ContextRecord
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
PuDbgPrintCurrentTime(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFilePath,
|
|
||||||
IN int nLineNum,
|
|
||||||
IN const char * pszFunctionName
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
PuSetDbgOutputFlags(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN DWORD dwFlags);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuGetDbgOutputFlags(
|
|
||||||
IN const LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Following functions return Win32 error codes.
|
|
||||||
// NO_ERROR if success
|
|
||||||
//
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuOpenDbgPrintFile(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints,
|
|
||||||
IN const char * pszFileName,
|
|
||||||
IN const char * pszPathForFile);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuReOpenDbgPrintFile(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuCloseDbgPrintFile(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuOpenDbgMemoryLog(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuCloseDbgMemoryLog(
|
|
||||||
IN_OUT LPDEBUG_PRINTS pDebugPrints);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuLoadDebugFlagsFromReg(IN HKEY hkey, IN DWORD dwDefault);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuLoadDebugFlagsFromRegStr(IN LPCSTR pszRegKey, IN DWORD dwDefault);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
PuSaveDebugFlagsInReg(IN HKEY hkey, IN DWORD dwDbg);
|
|
||||||
|
|
||||||
|
|
||||||
# define PuPrintToKdb( pszOutput) \
|
|
||||||
if ( pszOutput != NULL) { \
|
|
||||||
OutputDebugString( pszOutput); \
|
|
||||||
} else {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ifdef __cplusplus
|
|
||||||
};
|
|
||||||
# endif // __cplusplus
|
|
||||||
|
|
||||||
// begin_user_unmodifiable
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* Macros
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
extern
|
|
||||||
#ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
DEBUG_PRINTS * g_pDebug; // define a global debug variable
|
|
||||||
|
|
||||||
# if DBG
|
|
||||||
|
|
||||||
// For the CHK build we want ODS enabled. For an explanation of these flags see
|
|
||||||
// the comment just after the definition of DBG_CONTEXT
|
|
||||||
# define DECLARE_DEBUG_PRINTS_OBJECT() \
|
|
||||||
DEBUG_PRINTS * g_pDebug = NULL; \
|
|
||||||
DWORD DEBUG_FLAGS_VAR = DEBUG_FLAG_ERROR;
|
|
||||||
|
|
||||||
#else // !DBG
|
|
||||||
|
|
||||||
# define DECLARE_DEBUG_PRINTS_OBJECT() \
|
|
||||||
DEBUG_PRINTS * g_pDebug = NULL; \
|
|
||||||
DWORD DEBUG_FLAGS_VAR = 0;
|
|
||||||
|
|
||||||
#endif // !DBG
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call the following macro as part of your initialization for program
|
|
||||||
// planning to use the debugging class.
|
|
||||||
//
|
|
||||||
/** DEBUGDEBUG
|
|
||||||
# define CREATE_DEBUG_PRINT_OBJECT( pszLabel) \
|
|
||||||
g_pDebug = PuCreateDebugPrintsObject( pszLabel, DEFAULT_OUTPUT_FLAGS);\
|
|
||||||
if ( g_pDebug == NULL) { \
|
|
||||||
OutputDebugStringA( "Unable to Create Debug Print Object \n"); \
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call the following macro once as part of the termination of program
|
|
||||||
// which uses the debugging class.
|
|
||||||
//
|
|
||||||
# define DELETE_DEBUG_PRINT_OBJECT( ) \
|
|
||||||
g_pDebug = PuDeleteDebugPrintsObject( g_pDebug);
|
|
||||||
|
|
||||||
|
|
||||||
# define VALID_DEBUG_PRINT_OBJECT() \
|
|
||||||
( ( g_pDebug != NULL) && g_pDebug->m_fInitialized)
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Use the DBG_CONTEXT without any surrounding braces.
|
|
||||||
// This is used to pass the values for global DebugPrintObject
|
|
||||||
// and File/Line information
|
|
||||||
//
|
|
||||||
//# define DBG_CONTEXT g_pDebug, __FILE__, __LINE__, __FUNCTION__
|
|
||||||
|
|
||||||
// The 3 main tracing macros, each one corresponds to a different level of
|
|
||||||
// tracing
|
|
||||||
|
|
||||||
// The 3 main tracing macros, each one corresponds to a different level of
|
|
||||||
// tracing
|
|
||||||
//# define DBGINFO(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrint args; }}
|
|
||||||
//# define DBGWARN(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrint args; }}
|
|
||||||
//# define DBGERROR(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrint args; }}
|
|
||||||
|
|
||||||
# define DBGINFOW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_INFO) { PuDbgPrintW args; }}
|
|
||||||
# define DBGWARNW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_WARN) { PuDbgPrintW args; }}
|
|
||||||
# define DBGERRORW(args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintW args; }}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// DBGPRINTF() is printing function ( much like printf) but always called
|
|
||||||
// with the DBG_CONTEXT as follows
|
|
||||||
// DBGPRINTF( ( DBG_CONTEXT, format-string, arguments for format list));
|
|
||||||
//
|
|
||||||
# define DBGPRINTF DBGINFO
|
|
||||||
|
|
||||||
//
|
|
||||||
// DPERROR() is printing function ( much like printf) but always called
|
|
||||||
// with the DBG_CONTEXT as follows
|
|
||||||
// DPERROR( ( DBG_CONTEXT, error, format-string,
|
|
||||||
// arguments for format list));
|
|
||||||
//
|
|
||||||
# define DPERROR( args) {if (DEBUG_FLAGS_VAR & DEBUG_FLAGS_ERROR) { PuDbgPrintError args; }}
|
|
||||||
|
|
||||||
# if DBG
|
|
||||||
|
|
||||||
# define DBG_CODE(s) s /* echoes code in debugging mode */
|
|
||||||
|
|
||||||
// The same 3 main tracing macros however in this case the macros are only compiled
|
|
||||||
// into the CHK build. This is necessary because some tracing info used functions or
|
|
||||||
// variables which are not compiled into the FRE build.
|
|
||||||
# define CHKINFO(args) { PuDbgPrint args; }
|
|
||||||
# define CHKWARN(args) { PuDbgPrint args; }
|
|
||||||
# define CHKERROR(args) { PuDbgPrint args; }
|
|
||||||
|
|
||||||
# define CHKINFOW(args) { PuDbgPrintW args; }
|
|
||||||
# define CHKWARNW(args) { PuDbgPrintW args; }
|
|
||||||
# define CHKERRORW(args) { PuDbgPrintW args; }
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DBG_ASSERT
|
|
||||||
# ifdef _PREFAST_
|
|
||||||
# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */
|
|
||||||
# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */
|
|
||||||
# define DBG_REQUIRE( exp) ((void) (exp))
|
|
||||||
# else // !_PREFAST_
|
|
||||||
# define DBG_ASSERT( exp ) \
|
|
||||||
( (VOID)( ( exp ) || ( DebugBreak(), \
|
|
||||||
PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, "" ) ) ) )
|
|
||||||
|
|
||||||
# define DBG_ASSERT_MSG( exp, pszMsg) \
|
|
||||||
( (VOID)( ( exp ) || ( DebugBreak(), \
|
|
||||||
PuDbgPrintAssertFailed( DBG_CONTEXT, #exp, pszMsg ) ) ) )
|
|
||||||
|
|
||||||
# define DBG_REQUIRE( exp ) \
|
|
||||||
DBG_ASSERT( exp )
|
|
||||||
# endif // !_PREFAST_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
# define DBG_LOG() PuDbgPrint( DBG_CONTEXT, "\n" )
|
|
||||||
|
|
||||||
# define DBG_OPEN_LOG_FILE( pszFile, pszPath ) \
|
|
||||||
PuOpenDbgPrintFile( g_pDebug, (pszFile), (pszPath) )
|
|
||||||
|
|
||||||
# define DBG_CLOSE_LOG_FILE( ) \
|
|
||||||
PuCloseDbgPrintFile( g_pDebug )
|
|
||||||
|
|
||||||
# define DBG_OPEN_MEMORY_LOG( ) \
|
|
||||||
PuOpenDbgMemoryLog( g_pDebug )
|
|
||||||
|
|
||||||
|
|
||||||
# define DBGDUMP( args ) PuDbgDump args
|
|
||||||
|
|
||||||
# define DBGPRINT_CURRENT_TIME() PuDbgPrintCurrentTime( DBG_CONTEXT )
|
|
||||||
|
|
||||||
# else // !DBG
|
|
||||||
|
|
||||||
# define DBG_CODE(s) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define CHKINFO(args) ((void)0) /* Do Nothing */
|
|
||||||
# define CHKWARN(args) ((void)0) /* Do Nothing */
|
|
||||||
# define CHKERROR(args) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define CHKINFOW(args) ((void)0) /* Do Nothing */
|
|
||||||
# define CHKWARNW(args) ((void)0) /* Do Nothing */
|
|
||||||
# define CHKERRORW(args) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
#ifndef DBG_ASSERT
|
|
||||||
# define DBG_ASSERT(exp) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBG_ASSERT_MSG(exp, pszMsg) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBG_REQUIRE( exp) ((void) (exp))
|
|
||||||
#endif // !DBG_ASSERT
|
|
||||||
|
|
||||||
# define DBGDUMP( args) ((void)0) /* Do nothing */
|
|
||||||
|
|
||||||
# define DBG_LOG() ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBG_OPEN_LOG_FILE( pszFile, pszPath) ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBG_OPEN_MEMORY_LOG() ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBG_CLOSE_LOG_FILE() ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# define DBGPRINT_CURRENT_TIME() ((void)0) /* Do Nothing */
|
|
||||||
|
|
||||||
# endif // !DBG
|
|
||||||
|
|
||||||
|
|
||||||
// end_user_unmodifiable
|
|
||||||
|
|
||||||
// begin_user_unmodifiable
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
# undef ASSERT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
# define ASSERT( exp) DBG_ASSERT( exp)
|
|
||||||
|
|
||||||
|
|
||||||
// end_user_unmodifiable
|
|
||||||
|
|
||||||
// begin_user_modifiable
|
|
||||||
|
|
||||||
//
|
|
||||||
// Debugging constants consist of two pieces.
|
|
||||||
// All constants in the range 0x0 to 0x8000 are reserved
|
|
||||||
// User extensions may include additional constants (bit flags)
|
|
||||||
//
|
|
||||||
|
|
||||||
# define DEBUG_API_ENTRY 0x00000001L
|
|
||||||
# define DEBUG_API_EXIT 0x00000002L
|
|
||||||
# define DEBUG_INIT_CLEAN 0x00000004L
|
|
||||||
# define DEBUG_ERROR 0x00000008L
|
|
||||||
|
|
||||||
// End of Reserved Range
|
|
||||||
# define DEBUG_RESERVED 0x00000FFFL
|
|
||||||
|
|
||||||
// end_user_modifiable
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* Platform Type related variables and macros
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Enum for product types
|
|
||||||
//
|
|
||||||
|
|
||||||
typedef enum _PLATFORM_TYPE {
|
|
||||||
|
|
||||||
PtInvalid = 0, // Invalid
|
|
||||||
PtNtWorkstation = 1, // NT Workstation
|
|
||||||
PtNtServer = 2, // NT Server
|
|
||||||
|
|
||||||
} PLATFORM_TYPE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// IISGetPlatformType is the function used to the platform type
|
|
||||||
//
|
|
||||||
|
|
||||||
extern
|
|
||||||
#ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
PLATFORM_TYPE
|
|
||||||
IISGetPlatformType(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// External Macros
|
|
||||||
//
|
|
||||||
|
|
||||||
#define InetIsNtServer( _pt ) ((_pt) == PtNtServer)
|
|
||||||
#define InetIsNtWksta( _pt ) ((_pt) == PtNtWorkstation)
|
|
||||||
#define InetIsValidPT(_pt) ((_pt) != PtInvalid)
|
|
||||||
|
|
||||||
extern
|
|
||||||
#ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
PLATFORM_TYPE g_PlatformType;
|
|
||||||
|
|
||||||
|
|
||||||
// Use the DECLARE_PLATFORM_TYPE macro to declare the platform type
|
|
||||||
#define DECLARE_PLATFORM_TYPE() \
|
|
||||||
PLATFORM_TYPE g_PlatformType = PtInvalid;
|
|
||||||
|
|
||||||
// Use the INITIALIZE_PLATFORM_TYPE to init the platform type
|
|
||||||
// This should typically go inside the DLLInit or equivalent place.
|
|
||||||
#define INITIALIZE_PLATFORM_TYPE() \
|
|
||||||
g_PlatformType = IISGetPlatformType();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Additional Macros to use the Platform Type
|
|
||||||
//
|
|
||||||
|
|
||||||
#define TsIsNtServer( ) InetIsNtServer(g_PlatformType)
|
|
||||||
#define TsIsNtWksta( ) InetIsNtWksta(g_PlatformType)
|
|
||||||
#define IISIsValidPlatform() InetIsValidPT(g_PlatformType)
|
|
||||||
#define IISPlatformType() (g_PlatformType)
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* Some utility functions for Critical Sections
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
//
|
|
||||||
// IISSetCriticalSectionSpinCount() provides a thunk for the
|
|
||||||
// original NT4.0sp3 API SetCriticalSectionSpinCount() for CS with Spin counts
|
|
||||||
// Users of this function should definitely dynlink with kernel32.dll,
|
|
||||||
// Otherwise errors will surface to a large extent
|
|
||||||
//
|
|
||||||
extern
|
|
||||||
# ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
DWORD
|
|
||||||
IISSetCriticalSectionSpinCount(
|
|
||||||
LPCRITICAL_SECTION lpCriticalSection,
|
|
||||||
DWORD dwSpinCount
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Macro for the calls to SetCriticalSectionSpinCount()
|
|
||||||
//
|
|
||||||
# define SET_CRITICAL_SECTION_SPIN_COUNT( lpCS, dwSpins) \
|
|
||||||
IISSetCriticalSectionSpinCount( (lpCS), (dwSpins))
|
|
||||||
|
|
||||||
//
|
|
||||||
// IIS_DEFAULT_CS_SPIN_COUNT is the default value of spins used by
|
|
||||||
// Critical sections defined within IIS.
|
|
||||||
// NYI: We should have to switch the individual values based on experiments!
|
|
||||||
// Current value is an arbitrary choice
|
|
||||||
//
|
|
||||||
# define IIS_DEFAULT_CS_SPIN_COUNT (1000)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initializes a critical section and sets its spin count
|
|
||||||
// to IIS_DEFAULT_CS_SPIN_COUNT. Equivalent to
|
|
||||||
// InitializeCriticalSectionAndSpinCount(lpCS, IIS_DEFAULT_CS_SPIN_COUNT),
|
|
||||||
// but provides a safe thunking layer for older systems that don't provide
|
|
||||||
// this API.
|
|
||||||
//
|
|
||||||
extern
|
|
||||||
# ifdef __cplusplus
|
|
||||||
"C"
|
|
||||||
# endif // _cplusplus
|
|
||||||
BOOL
|
|
||||||
IISInitializeCriticalSection(
|
|
||||||
LPCRITICAL_SECTION lpCriticalSection
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Macro for the calls to InitializeCriticalSection()
|
|
||||||
//
|
|
||||||
# define INITIALIZE_CRITICAL_SECTION(lpCS) IISInitializeCriticalSection(lpCS)
|
|
||||||
|
|
||||||
# endif /* _DEBUG_HXX_ */
|
|
||||||
|
|
||||||
//
|
|
||||||
// The following macros allow the automatic naming of certain Win32 objects.
|
|
||||||
// See IIS\SVCS\IISRTL\WIN32OBJ.C for details on the naming convention.
|
|
||||||
//
|
|
||||||
// Set IIS_NAMED_WIN32_OBJECTS to a non-zero value to enable named events,
|
|
||||||
// semaphores, and mutexes.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if DBG
|
|
||||||
#define IIS_NAMED_WIN32_OBJECTS 1
|
|
||||||
#else
|
|
||||||
#define IIS_NAMED_WIN32_OBJECTS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
PuDbgCreateEvent(
|
|
||||||
__in LPSTR FileName,
|
|
||||||
IN ULONG LineNumber,
|
|
||||||
__in LPSTR MemberName,
|
|
||||||
IN PVOID Address,
|
|
||||||
IN BOOL ManualReset,
|
|
||||||
IN BOOL InitialState
|
|
||||||
);
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
PuDbgCreateSemaphore(
|
|
||||||
__in LPSTR FileName,
|
|
||||||
IN ULONG LineNumber,
|
|
||||||
__in LPSTR MemberName,
|
|
||||||
IN PVOID Address,
|
|
||||||
IN LONG InitialCount,
|
|
||||||
IN LONG MaximumCount
|
|
||||||
);
|
|
||||||
|
|
||||||
HANDLE
|
|
||||||
PuDbgCreateMutex(
|
|
||||||
__in LPSTR FileName,
|
|
||||||
IN ULONG LineNumber,
|
|
||||||
__in LPSTR MemberName,
|
|
||||||
IN PVOID Address,
|
|
||||||
IN BOOL InitialOwner
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if IIS_NAMED_WIN32_OBJECTS
|
|
||||||
|
|
||||||
#define IIS_CREATE_EVENT( membername, address, manual, state ) \
|
|
||||||
PuDbgCreateEvent( \
|
|
||||||
(LPSTR)__FILE__, \
|
|
||||||
(ULONG)__LINE__, \
|
|
||||||
(membername), \
|
|
||||||
(PVOID)(address), \
|
|
||||||
(manual), \
|
|
||||||
(state) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \
|
|
||||||
PuDbgCreateSemaphore( \
|
|
||||||
(LPSTR)__FILE__, \
|
|
||||||
(ULONG)__LINE__, \
|
|
||||||
(membername), \
|
|
||||||
(PVOID)(address), \
|
|
||||||
(initial), \
|
|
||||||
(maximum) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define IIS_CREATE_MUTEX( membername, address, initial ) \
|
|
||||||
PuDbgCreateMutex( \
|
|
||||||
(LPSTR)__FILE__, \
|
|
||||||
(ULONG)__LINE__, \
|
|
||||||
(membername), \
|
|
||||||
(PVOID)(address), \
|
|
||||||
(initial) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#else // !IIS_NAMED_WIN32_OBJECTS
|
|
||||||
|
|
||||||
#define IIS_CREATE_EVENT( membername, address, manual, state ) \
|
|
||||||
CreateEventA( \
|
|
||||||
NULL, \
|
|
||||||
(manual), \
|
|
||||||
(state), \
|
|
||||||
NULL \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define IIS_CREATE_SEMAPHORE( membername, address, initial, maximum ) \
|
|
||||||
CreateSemaphoreA( \
|
|
||||||
NULL, \
|
|
||||||
(initial), \
|
|
||||||
(maximum), \
|
|
||||||
NULL \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define IIS_CREATE_MUTEX( membername, address, initial ) \
|
|
||||||
CreateMutexA( \
|
|
||||||
NULL, \
|
|
||||||
(initial), \
|
|
||||||
NULL \
|
|
||||||
)
|
|
||||||
|
|
||||||
#endif // IIS_NAMED_WIN32_OBJECTS
|
|
||||||
|
|
||||||
|
|
||||||
/************************ End of File ***********************/
|
|
||||||
|
|
||||||
|
|
@ -1,229 +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 <windows.h>
|
|
||||||
#include "dbgutil.h"
|
|
||||||
#include "pudebug.h"
|
|
||||||
#include "reftrace.h"
|
|
||||||
|
|
||||||
|
|
||||||
PTRACE_LOG
|
|
||||||
CreateRefTraceLog(
|
|
||||||
IN LONG LogSize,
|
|
||||||
IN LONG ExtraBytesInHeader
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Creates a new (empty) ref count trace log buffer.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
LogSize - The number of entries in the log.
|
|
||||||
|
|
||||||
ExtraBytesInHeader - The number of extra bytes to include in the
|
|
||||||
log header. This is useful for adding application-specific
|
|
||||||
data to the log.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
PTRACE_LOG - Pointer to the newly created log if successful,
|
|
||||||
NULL otherwise.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
|
|
||||||
return CreateTraceLog(
|
|
||||||
LogSize,
|
|
||||||
ExtraBytesInHeader,
|
|
||||||
sizeof(REF_TRACE_LOG_ENTRY)
|
|
||||||
);
|
|
||||||
|
|
||||||
} // CreateRefTraceLog
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DestroyRefTraceLog(
|
|
||||||
IN PTRACE_LOG Log
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Destroys a ref count trace log buffer created with CreateRefTraceLog().
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Log - The ref count trace log buffer to destroy.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
None.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
|
|
||||||
DestroyTraceLog( Log );
|
|
||||||
|
|
||||||
} // DestroyRefTraceLog
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// N.B. For RtlCaptureBacktrace() to work properly, the calling function
|
|
||||||
// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate
|
|
||||||
// WriteRefTraceLog[Ex]() with the __cdecl modifier and disable the frame
|
|
||||||
// pointer omission (FPO) optimization.
|
|
||||||
//
|
|
||||||
|
|
||||||
//#pragma optimize( "y", off ) // disable frame pointer omission (FPO)
|
|
||||||
#pragma optimize( "", off ) // disable frame pointer omission (FPO)
|
|
||||||
|
|
||||||
LONG
|
|
||||||
__cdecl
|
|
||||||
WriteRefTraceLog(
|
|
||||||
IN PTRACE_LOG Log,
|
|
||||||
IN LONG NewRefCount,
|
|
||||||
IN CONST VOID * Context
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Writes a new entry to the specified ref count trace log. The entry
|
|
||||||
written contains the updated reference count and a stack backtrace
|
|
||||||
leading up to the current caller.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Log - The log to write to.
|
|
||||||
|
|
||||||
NewRefCount - The updated reference count.
|
|
||||||
|
|
||||||
Context - An uninterpreted context to associate with the log entry.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
Index of entry in log.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
|
|
||||||
return WriteRefTraceLogEx(
|
|
||||||
Log,
|
|
||||||
NewRefCount,
|
|
||||||
Context,
|
|
||||||
REF_TRACE_EMPTY_CONTEXT, // suppress use of optional extra contexts
|
|
||||||
REF_TRACE_EMPTY_CONTEXT,
|
|
||||||
REF_TRACE_EMPTY_CONTEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
} // WriteRefTraceLog
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LONG
|
|
||||||
__cdecl
|
|
||||||
WriteRefTraceLogEx(
|
|
||||||
IN PTRACE_LOG Log,
|
|
||||||
IN LONG NewRefCount,
|
|
||||||
IN CONST VOID * Context,
|
|
||||||
IN CONST VOID * Context1, // optional extra context
|
|
||||||
IN CONST VOID * Context2, // optional extra context
|
|
||||||
IN CONST VOID * Context3 // optional extra context
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
|
|
||||||
Writes a new "extended" entry to the specified ref count trace log.
|
|
||||||
The entry written contains the updated reference count, stack backtrace
|
|
||||||
leading up to the current caller and extra context information.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
Log - The log to write to.
|
|
||||||
|
|
||||||
NewRefCount - The updated reference count.
|
|
||||||
|
|
||||||
Context - An uninterpreted context to associate with the log entry.
|
|
||||||
Context1 - An uninterpreted context to associate with the log entry.
|
|
||||||
Context2 - An uninterpreted context to associate with the log entry.
|
|
||||||
Context3 - An uninterpreted context to associate with the log entry.
|
|
||||||
|
|
||||||
NOTE Context1/2/3 are "optional" in that the caller may suppress
|
|
||||||
debug display of these values by passing REF_TRACE_EMPTY_CONTEXT
|
|
||||||
for each of them.
|
|
||||||
|
|
||||||
Return Value:
|
|
||||||
|
|
||||||
Index of entry in log.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
|
|
||||||
REF_TRACE_LOG_ENTRY entry;
|
|
||||||
ULONG hash;
|
|
||||||
DWORD cStackFramesSkipped;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the entry.
|
|
||||||
//
|
|
||||||
|
|
||||||
RtlZeroMemory(
|
|
||||||
&entry,
|
|
||||||
sizeof(entry)
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set log entry members.
|
|
||||||
//
|
|
||||||
|
|
||||||
entry.NewRefCount = NewRefCount;
|
|
||||||
entry.Context = Context;
|
|
||||||
entry.Thread = GetCurrentThreadId();
|
|
||||||
entry.Context1 = Context1;
|
|
||||||
entry.Context2 = Context2;
|
|
||||||
entry.Context3 = Context3;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Capture the stack backtrace. Normally, we skip two stack frames:
|
|
||||||
// one for this routine, and one for RtlCaptureBacktrace() itself.
|
|
||||||
// For non-Ex callers who come in via WriteRefTraceLog,
|
|
||||||
// we skip three stack frames.
|
|
||||||
//
|
|
||||||
|
|
||||||
if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT
|
|
||||||
&& entry.Context2 == REF_TRACE_EMPTY_CONTEXT
|
|
||||||
&& entry.Context3 == REF_TRACE_EMPTY_CONTEXT
|
|
||||||
) {
|
|
||||||
|
|
||||||
cStackFramesSkipped = 2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
cStackFramesSkipped = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlCaptureStackBackTrace(
|
|
||||||
cStackFramesSkipped,
|
|
||||||
REF_TRACE_LOG_STACK_DEPTH,
|
|
||||||
entry.Stack,
|
|
||||||
&hash
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write it to the log.
|
|
||||||
//
|
|
||||||
|
|
||||||
return WriteTraceLog(
|
|
||||||
Log,
|
|
||||||
&entry
|
|
||||||
);
|
|
||||||
|
|
||||||
} // WriteRefTraceLogEx
|
|
||||||
|
|
||||||
#pragma optimize( "", on ) // restore frame pointer omission (FPO)
|
|
||||||
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
#ifndef _REFTRACE_H_
|
|
||||||
#define _REFTRACE_H_
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#include <Windows.h>
|
|
||||||
#include "tracelog.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is the number of stack backtrace values captured in each
|
|
||||||
// trace log entry. This value is chosen to make the log entry
|
|
||||||
// exactly twelve dwords long, making it a bit easier to interpret
|
|
||||||
// from within the debugger without the debugger extension.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define REF_TRACE_LOG_STACK_DEPTH 9
|
|
||||||
|
|
||||||
// No-op value for the Context1,2,3 parameters of WriteRefTraceLogEx
|
|
||||||
//#define REF_TRACE_EMPTY_CONTEXT ((PVOID) -1)
|
|
||||||
#define REF_TRACE_EMPTY_CONTEXT NULL
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// This defines the entry written to the trace log.
|
|
||||||
//
|
|
||||||
|
|
||||||
typedef struct _REF_TRACE_LOG_ENTRY {
|
|
||||||
|
|
||||||
LONG NewRefCount;
|
|
||||||
CONST VOID * Context;
|
|
||||||
CONST VOID * Context1;
|
|
||||||
CONST VOID * Context2;
|
|
||||||
CONST VOID * Context3;
|
|
||||||
DWORD Thread;
|
|
||||||
PVOID Stack[REF_TRACE_LOG_STACK_DEPTH];
|
|
||||||
|
|
||||||
} REF_TRACE_LOG_ENTRY, *PREF_TRACE_LOG_ENTRY;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Manipulators.
|
|
||||||
//
|
|
||||||
|
|
||||||
PTRACE_LOG
|
|
||||||
CreateRefTraceLog(
|
|
||||||
IN LONG LogSize,
|
|
||||||
IN LONG ExtraBytesInHeader
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
DestroyRefTraceLog(
|
|
||||||
IN PTRACE_LOG Log
|
|
||||||
);
|
|
||||||
|
|
||||||
LONG
|
|
||||||
__cdecl
|
|
||||||
WriteRefTraceLog(
|
|
||||||
IN PTRACE_LOG Log,
|
|
||||||
IN LONG NewRefCount,
|
|
||||||
IN CONST VOID * Context
|
|
||||||
);
|
|
||||||
|
|
||||||
LONG
|
|
||||||
__cdecl
|
|
||||||
WriteRefTraceLogEx(
|
|
||||||
IN PTRACE_LOG Log,
|
|
||||||
IN LONG NewRefCount,
|
|
||||||
IN CONST VOID * Context,
|
|
||||||
IN CONST VOID * Context1,
|
|
||||||
IN CONST VOID * Context2,
|
|
||||||
IN CONST VOID * Context3
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
} // extern "C"
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _REFTRACE_H_
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue